Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Rishabh Gupta
purr-data
Commits
341d36c4
Commit
341d36c4
authored
Sep 28, 2014
by
pokergaming
Browse files
first stab at generalizing gpointers to handle gobjs
parent
46933bb2
Changes
7
Hide whitespace changes
Inline
Side-by-side
pd/src/g_array.c
View file @
341d36c4
...
...
@@ -101,10 +101,10 @@ static void array_resize_and_redraw(t_array *array, t_glist *glist, int n)
while
(
a2
->
a_gp
.
gp_stub
->
gs_which
==
GP_ARRAY
)
a2
=
a2
->
a_gp
.
gp_stub
->
gs_un
.
gs_array
;
if
(
vis
)
gobj_vis
(
&
a2
->
a_gp
.
gp_un
.
gp_
scalar
->
sc_
gobj
,
glist
,
0
);
gobj_vis
(
a2
->
a_gp
.
gp_un
.
gp_gobj
,
glist
,
0
);
array_resize
(
array
,
n
);
if
(
vis
)
gobj_vis
(
&
a2
->
a_gp
.
gp_un
.
gp_
scalar
->
sc_
gobj
,
glist
,
1
);
gobj_vis
(
a2
->
a_gp
.
gp_un
.
gp_gobj
,
glist
,
1
);
}
void
word_free
(
t_word
*
wp
,
t_template
*
template
);
...
...
@@ -841,7 +841,8 @@ void array_redraw(t_array *a, t_glist *glist)
{
while
(
a
->
a_gp
.
gp_stub
->
gs_which
==
GP_ARRAY
)
a
=
a
->
a_gp
.
gp_stub
->
gs_un
.
gs_array
;
scalar_redraw
(
a
->
a_gp
.
gp_un
.
gp_scalar
,
glist
);
t_scalar
*
sc
=
(
t_scalar
*
)(
a
->
a_gp
.
gp_un
.
gp_gobj
);
scalar_redraw
(
sc
,
glist
);
}
/* routine to get screen coordinates of a point in an array */
...
...
pd/src/g_canvas.h
View file @
341d36c4
...
...
@@ -612,7 +612,7 @@ int array_joc; /* for "jump on click" array inside a graph */
/* --------------------- gpointers and stubs ---------------- */
EXTERN
t_gstub
*
gstub_new
(
t_glist
*
gl
,
t_array
*
a
);
EXTERN
void
gstub_cutoff
(
t_gstub
*
gs
);
EXTERN
void
gpointer_setglist
(
t_gpointer
*
gp
,
t_glist
*
glist
,
t_
scalar
*
x
);
EXTERN
void
gpointer_setglist
(
t_gpointer
*
gp
,
t_glist
*
glist
,
t_
gobj
*
x
);
EXTERN
void
gpointer_setarray
(
t_gpointer
*
gp
,
t_array
*
array
,
t_word
*
w
);
/* --------------------- scalars ------------------------- */
...
...
pd/src/g_scalar.c
View file @
341d36c4
...
...
@@ -225,7 +225,7 @@ t_scalar *scalar_new(t_glist *owner, t_symbol *templatesym)
(
template
->
t_n
-
1
)
*
sizeof
(
*
x
->
sc_vec
));
x
->
sc_gobj
.
g_pd
=
scalar_class
;
x
->
sc_template
=
templatesym
;
gpointer_setglist
(
&
gp
,
owner
,
x
);
gpointer_setglist
(
&
gp
,
owner
,
&
x
->
sc_gobj
);
word_init
(
x
->
sc_vec
,
template
,
&
gp
);
char
buf
[
50
];
sprintf
(
buf
,
".x%lx"
,
(
long
unsigned
int
)
x
);
...
...
@@ -457,7 +457,7 @@ void scalar_select(t_gobj *z, t_glist *owner, int state)
//t_canvas *templatecanvas = NULL;
t_gpointer
gp
;
gpointer_init
(
&
gp
);
gpointer_setglist
(
&
gp
,
owner
,
x
);
gpointer_setglist
(
&
gp
,
owner
,
&
x
->
sc_gobj
);
SETPOINTER
(
&
at
,
&
gp
);
if
(
tmpl
=
template_findbyname
(
templatesym
))
{
...
...
@@ -523,7 +523,7 @@ static void scalar_displace(t_gobj *z, t_glist *glist, int dx, int dy)
x
->
sc_y2
+=
dy
;
}
gpointer_init
(
&
gp
);
gpointer_setglist
(
&
gp
,
glist
,
x
);
gpointer_setglist
(
&
gp
,
glist
,
&
x
->
sc_gobj
);
SETPOINTER
(
&
at
[
0
],
&
gp
);
SETFLOAT
(
&
at
[
1
],
(
t_float
)
dx
);
SETFLOAT
(
&
at
[
2
],
(
t_float
)
dy
);
...
...
@@ -576,7 +576,7 @@ static void scalar_displace_withtag(t_gobj *z, t_glist *glist, int dx, int dy)
//fprintf(stderr,"gotx=%d goty=%d\n", gotx, goty);
scalar_getbasexy
(
x
,
&
basex
,
&
basey
);
gpointer_init
(
&
gp
);
gpointer_setglist
(
&
gp
,
glist
,
x
);
gpointer_setglist
(
&
gp
,
glist
,
&
x
->
sc_gobj
);
SETPOINTER
(
&
at
[
0
],
&
gp
);
SETFLOAT
(
&
at
[
1
],
(
t_float
)
dx
);
SETFLOAT
(
&
at
[
2
],
(
t_float
)
dy
);
...
...
pd/src/g_template.c
View file @
341d36c4
...
...
@@ -282,7 +282,7 @@ static t_scalar *template_conformscalar(t_template *tfrom, t_template *tto,
(tto->t_n - 1) * sizeof(*x->sc_vec));
x->sc_gobj.g_pd = scalar_class;
x->sc_template = tfrom->t_sym;
gpointer_setglist(&gp, glist,
x
);
gpointer_setglist(&gp, glist,
&x->sc_gobj
);
/* Here we initialize to the new template, but array and list
elements will still belong to old template. */
word_init(x->sc_vec, tto, &gp);
...
...
@@ -503,7 +503,7 @@ void template_notifyforscalar(t_template *template, t_glist *owner,
{
t_gpointer gp;
gpointer_init(&gp);
gpointer_setglist(&gp, owner, sc);
gpointer_setglist(&gp, owner,
&
sc
->sc_gobj
);
SETPOINTER(argv, &gp);
template_notify(template, s, argc, argv);
gpointer_unset(&gp);
...
...
@@ -3717,7 +3717,7 @@ static int draw_click(t_gobj *z, t_glist *glist,
draw_motion_template = template;
if (draw_motion_scalar)
gpointer_setglist(&draw_motion_gpointer, draw_motion_glist,
draw_motion_scalar);
&
draw_motion_scalar
->sc_gobj
);
else gpointer_setarray(&draw_motion_gpointer,
draw_motion_array, draw_motion_wp);
glist_grab(glist, z, draw_motion, 0, xpix, ypix);
...
...
@@ -4323,7 +4323,7 @@ static int curve_click(t_gobj *z, t_glist *glist,
curve_motion_template = template;
if (curve_motion_scalar)
gpointer_setglist(&curve_motion_gpointer, curve_motion_glist,
curve_motion_scalar);
&
curve_motion_scalar
->sc_gobj
);
else gpointer_setarray(&curve_motion_gpointer,
curve_motion_array, curve_motion_wp);
glist_grab(glist, z, curve_motion, 0, xpix, ypix);
...
...
@@ -6551,7 +6551,7 @@ static int drawnumber_click(t_gobj *z, t_glist *glist,
drawnumber_motion_symbol = ((x->x_flags & DRAW_SYMBOL) != 0);
if (drawnumber_motion_scalar)
gpointer_setglist(&drawnumber_motion_gpointer,
drawnumber_motion_glist, drawnumber_motion_scalar);
drawnumber_motion_glist,
&
drawnumber_motion_scalar
->sc_gobj
);
else gpointer_setarray(&drawnumber_motion_gpointer,
drawnumber_motion_array, drawnumber_motion_wp);
glist_grab(glist, z, drawnumber_motion, drawnumber_key,
...
...
@@ -6977,7 +6977,7 @@ static int drawsymbol_click(t_gobj *z, t_glist *glist,
drawsymbol_motion_symbol = ((x->x_flags & DRAW_SYMBOL) != 0);
if (drawsymbol_motion_scalar)
gpointer_setglist(&drawsymbol_motion_gpointer,
drawsymbol_motion_glist, drawsymbol_motion_scalar);
drawsymbol_motion_glist,
&
drawsymbol_motion_scalar
->sc_gobj
);
else gpointer_setarray(&drawsymbol_motion_gpointer,
drawsymbol_motion_array, drawsymbol_motion_wp);
glist_grab(glist, z, drawsymbol_motion, drawsymbol_key,
...
...
@@ -7439,7 +7439,7 @@ static int drawimage_click(t_gobj *z, t_glist *glist,
drawimage_motion_sprite = ((x->x_flags & DRAW_SPRITE) != 0);
if (drawimage_motion_scalar)
gpointer_setglist(&drawimage_motion_gpointer,
drawimage_motion_glist, drawimage_motion_scalar);
drawimage_motion_glist,
&
drawimage_motion_scalar
->sc_gobj
);
else gpointer_setarray(&drawimage_motion_gpointer,
drawimage_motion_array, drawimage_motion_wp);
glist_grab(glist, z, drawimage_motion, drawimage_key,
...
...
pd/src/g_traversal.c
View file @
341d36c4
...
...
@@ -83,9 +83,15 @@ int gpointer_check(const t_gpointer *gp, int headok)
}
else
if
(
gs
->
gs_which
==
GP_GLIST
)
{
if
(
!
headok
&&
!
gp
->
gp_un
.
gp_scalar
)
return
(
0
);
else
if
(
gs
->
gs_un
.
gs_glist
->
gl_valid
!=
gp
->
gp_valid
)
return
(
0
);
else
return
(
1
);
if
(
!
headok
&&
!
((
t_scalar
*
)(
gp
->
gp_un
.
gp_gobj
)))
return
(
0
);
else
if
(
gp
->
gp_un
.
gp_gobj
&&
pd_class
(
&
gp
->
gp_un
.
gp_gobj
->
g_pd
)
!=
scalar_class
)
return
(
0
);
else
if
(
gs
->
gs_un
.
gs_glist
->
gl_valid
!=
gp
->
gp_valid
)
return
(
0
);
else
return
(
1
);
}
else
return
(
0
);
}
...
...
@@ -98,7 +104,7 @@ static t_symbol *gpointer_gettemplatesym(const t_gpointer *gp)
t_gstub
*
gs
=
gp
->
gp_stub
;
if
(
gs
->
gs_which
==
GP_GLIST
)
{
t_scalar
*
sc
=
gp
->
gp_un
.
gp_
scalar
;
t_scalar
*
sc
=
(
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
)
;
if
(
sc
)
return
(
sc
->
sc_template
);
else
return
(
0
);
...
...
@@ -133,13 +139,13 @@ void gpointer_unset(t_gpointer *gp)
}
}
void
gpointer_setglist
(
t_gpointer
*
gp
,
t_glist
*
glist
,
t_
scalar
*
x
)
void
gpointer_setglist
(
t_gpointer
*
gp
,
t_glist
*
glist
,
t_
gobj
*
x
)
{
t_gstub
*
gs
;
if
(
gs
=
gp
->
gp_stub
)
gstub_dis
(
gs
);
gp
->
gp_stub
=
gs
=
glist
->
gl_stub
;
gp
->
gp_valid
=
glist
->
gl_valid
;
gp
->
gp_un
.
gp_
scalar
=
x
;
gp
->
gp_un
.
gp_
gobj
=
x
;
gs
->
gs_refcount
++
;
}
...
...
@@ -157,7 +163,7 @@ void gpointer_init(t_gpointer *gp)
{
gp
->
gp_stub
=
0
;
gp
->
gp_valid
=
0
;
gp
->
gp_un
.
gp_
scalar
=
0
;
gp
->
gp_un
.
gp_
gobj
=
0
;
}
/* ---------------------- pointers ----------------------------- */
...
...
@@ -236,7 +242,7 @@ static void ptrobj_vnext(t_ptrobj *x, t_float f)
"ptrobj_vnext: next-selected only works for a visible window"
);
return
;
}
gobj
=
&
gp
->
gp_un
.
gp_
scalar
->
sc_
gobj
;
gobj
=
gp
->
gp_un
.
gp_gobj
;
if
(
!
gobj
)
gobj
=
glist
->
gl_list
;
else
gobj
=
gobj
->
g_next
;
...
...
@@ -251,7 +257,7 @@ static void ptrobj_vnext(t_ptrobj *x, t_float f)
t_scalar
*
sc
=
(
t_scalar
*
)
gobj
;
t_symbol
*
templatesym
=
sc
->
sc_template
;
gp
->
gp_un
.
gp_
scalar
=
sc
;
gp
->
gp_un
.
gp_
gobj
=
&
sc
->
sc_gobj
;
for
(
n
=
x
->
x_ntypedout
,
to
=
x
->
x_typedout
;
n
--
;
to
++
)
{
if
(
to
->
to_type
==
templatesym
)
...
...
@@ -431,7 +437,7 @@ static void get_pointer(t_get *x, t_gpointer *gp)
return
;
}
if
(
gs
->
gs_which
==
GP_ARRAY
)
vec
=
gp
->
gp_un
.
gp_w
;
else
vec
=
gp
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
vec
=
((
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
for
(
i
=
nitems
-
1
,
vp
=
x
->
x_variables
+
i
;
i
>=
0
;
i
--
,
vp
--
)
{
int
onset
,
type
;
...
...
@@ -552,20 +558,20 @@ static void set_bang(t_set *x)
return
;
if
(
gs
->
gs_which
==
GP_ARRAY
)
vec
=
gp
->
gp_un
.
gp_w
;
else
vec
=
gp
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
vec
=
((
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
if
(
x
->
x_issymbol
)
for
(
i
=
0
,
vp
=
x
->
x_variables
;
i
<
nitems
;
i
++
,
vp
++
)
template_setsymbol
(
template
,
vp
->
gv_sym
,
vec
,
vp
->
gv_w
.
w_symbol
,
1
);
else
for
(
i
=
0
,
vp
=
x
->
x_variables
;
i
<
nitems
;
i
++
,
vp
++
)
template_setfloat
(
template
,
vp
->
gv_sym
,
vec
,
vp
->
gv_w
.
w_float
,
1
);
if
(
gs
->
gs_which
==
GP_GLIST
)
scalar_redraw
(
gp
->
gp_un
.
gp_
scalar
,
gs
->
gs_un
.
gs_glist
);
scalar_redraw
(
(
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
)
,
gs
->
gs_un
.
gs_glist
);
else
{
t_array
*
owner_array
=
gs
->
gs_un
.
gs_array
;
while
(
owner_array
->
a_gp
.
gp_stub
->
gs_which
==
GP_ARRAY
)
owner_array
=
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_array
;
scalar_redraw
(
owner_array
->
a_gp
.
gp_un
.
gp_
scalar
,
scalar_redraw
(
(
t_scalar
*
)(
owner_array
->
a_gp
.
gp_un
.
gp_
gobj
)
,
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_glist
);
}
}
...
...
@@ -654,7 +660,7 @@ static void elem_float(t_elem *x, t_float f)
return
;
}
if
(
gparent
->
gp_stub
->
gs_which
==
GP_ARRAY
)
w
=
gparent
->
gp_un
.
gp_w
;
else
w
=
gparent
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
w
=
((
t_scalar
*
)(
gparent
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
if
(
!
template
)
{
pd_error
(
x
,
"element: couldn't find template %s"
,
templatesym
->
s_name
);
...
...
@@ -761,7 +767,7 @@ static void getsize_pointer(t_getsize *x, t_gpointer *gp)
return
;
}
if
(
gs
->
gs_which
==
GP_ARRAY
)
w
=
gp
->
gp_un
.
gp_w
;
else
w
=
gp
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
w
=
((
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
array
=
*
(
t_array
**
)(((
char
*
)
w
)
+
onset
);
outlet_float
(
x
->
x_obj
.
ob_outlet
,
(
t_float
)(
array
->
a_n
));
...
...
@@ -824,7 +830,7 @@ static void setsize_float(t_setsize *x, t_float f)
return
;
}
if
(
gs
->
gs_which
==
GP_ARRAY
)
w
=
gp
->
gp_un
.
gp_w
;
else
w
=
gp
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
w
=
((
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
if
(
!
template
)
{
...
...
@@ -869,7 +875,7 @@ static void setsize_float(t_setsize *x, t_float f)
if
(
gs
->
gs_which
==
GP_GLIST
)
{
if
(
glist_isvisible
(
gs
->
gs_un
.
gs_glist
))
gobj_vis
(
(
t_gobj
*
)(
gp
->
gp_un
.
gp_
scalar
)
,
gs
->
gs_un
.
gs_glist
,
0
);
gobj_vis
(
gp
->
gp_un
.
gp_
gobj
,
gs
->
gs_un
.
gs_glist
,
0
);
}
else
{
...
...
@@ -877,7 +883,7 @@ static void setsize_float(t_setsize *x, t_float f)
while
(
owner_array
->
a_gp
.
gp_stub
->
gs_which
==
GP_ARRAY
)
owner_array
=
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_array
;
if
(
glist_isvisible
(
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_glist
))
gobj_vis
(
(
t_gobj
*
)(
owner_array
->
a_gp
.
gp_un
.
gp_
scalar
)
,
gobj_vis
(
owner_array
->
a_gp
.
gp_un
.
gp_
gobj
,
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_glist
,
0
);
}
/* now do the resizing and, if growing, initialize new scalars */
...
...
@@ -901,7 +907,7 @@ static void setsize_float(t_setsize *x, t_float f)
if
(
gs
->
gs_which
==
GP_GLIST
)
{
if
(
glist_isvisible
(
gs
->
gs_un
.
gs_glist
))
gobj_vis
(
(
t_gobj
*
)(
gp
->
gp_un
.
gp_
scalar
)
,
gs
->
gs_un
.
gs_glist
,
1
);
gobj_vis
(
gp
->
gp_un
.
gp_
gobj
,
gs
->
gs_un
.
gs_glist
,
1
);
}
else
{
...
...
@@ -909,7 +915,7 @@ static void setsize_float(t_setsize *x, t_float f)
while
(
owner_array
->
a_gp
.
gp_stub
->
gs_which
==
GP_ARRAY
)
owner_array
=
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_array
;
if
(
glist_isvisible
(
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_glist
))
gobj_vis
(
(
t_gobj
*
)(
owner_array
->
a_gp
.
gp_un
.
gp_
scalar
)
,
gobj_vis
(
owner_array
->
a_gp
.
gp_un
.
gp_
gobj
,
owner_array
->
a_gp
.
gp_stub
->
gs_un
.
gs_glist
,
1
);
}
}
...
...
@@ -1013,7 +1019,7 @@ static void append_float(t_append *x, t_float f)
pd_error
(
x
,
"%s: couldn't create scalar"
,
templatesym
->
s_name
);
return
;
}
oldsc
=
gp
->
gp_un
.
gp_
scalar
;
oldsc
=
(
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
)
;
if
(
oldsc
)
{
...
...
@@ -1026,7 +1032,7 @@ static void append_float(t_append *x, t_float f)
glist
->
gl_list
=
&
sc
->
sc_gobj
;
}
gp
->
gp_un
.
gp_
scalar
=
sc
;
gp
->
gp_un
.
gp_
gobj
=
(
t_gobj
*
)
sc
;
vec
=
sc
->
sc_vec
;
for
(
i
=
0
,
vp
=
x
->
x_variables
;
i
<
nitems
;
i
++
,
vp
++
)
{
...
...
@@ -1106,7 +1112,7 @@ static void sublist_pointer(t_sublist *x, t_gpointer *gp)
return
;
}
if
(
gs
->
gs_which
==
GP_ARRAY
)
w
=
gp
->
gp_un
.
gp_w
;
else
w
=
gp
->
gp_un
.
gp_
scalar
->
sc_vec
;
else
w
=
((
t_scalar
*
)(
gp
->
gp_un
.
gp_
gobj
))
->
sc_vec
;
gpointer_setglist
(
&
x
->
x_gp
,
*
(
t_glist
**
)(((
char
*
)
w
)
+
onset
),
0
);
...
...
pd/src/m_pd.h
View file @
341d36c4
...
...
@@ -111,7 +111,8 @@ typedef struct _gpointer /* pointer to a gobj in a glist */
{
union
{
struct
_scalar
*
gp_scalar
;
/* scalar we're in (if glist) */
struct
_gobj
*
gp_gobj
;
/* header for the t_text or
scalar we're in (if glist) */
union
word
*
gp_w
;
/* raw data (if array) */
}
gp_un
;
int
gp_valid
;
/* number which must match gpointee */
...
...
pd/src/x_interface.c
View file @
341d36c4
...
...
@@ -131,6 +131,7 @@ typedef struct _objectinfo {
t_canvas
*
x_canvas
;
t_float
x_index
;
t_float
x_depth
;
t_gobj
*
x_test
;
}
t_objectinfo
;
/* used by all the *info objects */
...
...
@@ -1004,9 +1005,24 @@ t_gobj *objectinfo_getobject(t_canvas *c, int index)
return
y
;
}
void
objectinfo_
float
(
t_floatarg
f
)
void
objectinfo_
bang
(
t_objectinfo
*
x
)
{
t_canvas
*
c
=
canvas_climb
(
x
->
x_canvas
,
x
->
x_depth
);
t_atom
at
[
1
];
t_gpointer
gp
;
gpointer_init
(
&
gp
);
gpointer_setglist
(
&
gp
,
c
,
(
t_gobj
*
)
x
);
SETPOINTER
(
at
,
&
gp
);
info_out
((
t_text
*
)
x
,
&
s_pointer
,
1
,
at
);
gpointer_unset
(
&
gp
);
}
void
objectinfo_float
(
t_objectinfo
*
x
,
t_floatarg
f
)
{
t_canvas
*
c
=
canvas_climb
(
x
->
x_canvas
,
x
->
x_depth
);
t_gobj
*
obj
=
objectinfo_getobject
(
c
,
(
int
)
f
);
post
(
"object is .%x"
,
obj
);
x
->
x_test
=
obj
;
}
void
objectinfo_parseargs
(
t_objectinfo
*
x
,
int
argc
,
t_atom
*
argv
)
...
...
@@ -1156,6 +1172,7 @@ void objectinfo_setup(void)
sizeof
(
t_objectinfo
),
CLASS_DEFAULT
,
A_DEFFLOAT
,
0
);
class_addbang
(
objectinfo_class
,
objectinfo_bang
);
class_addfloat
(
objectinfo_class
,
objectinfo_float
);
class_addmethod
(
objectinfo_class
,
(
t_method
)
objectinfo_bbox
,
gensym
(
"bbox"
),
A_GIMME
,
0
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment