Commit 087ffd6c authored by pokergaming's avatar pokergaming
Browse files

* fixed crash when a [struct] has an array which (directly or not) uses itself as a template

* suppress redraws for drawing commands if the group that contains them is getting deleted
parent 8d7a2611
......@@ -202,7 +202,10 @@ void glist_delete(t_glist *x, t_gobj *y)
if (drawcommand)
{
tmpl = template_findbydrawcommand(y);
canvas_redrawallfortemplate(tmpl, 2);
if (!(canvas_isgroup(canvas) && canvas->gl_isdeleting))
{
canvas_redrawallfortemplate(tmpl, 2);
}
}
if (glist_isvisible(canvas))
gobj_vis(y, x, 0);
......@@ -234,7 +237,10 @@ void glist_delete(t_glist *x, t_gobj *y)
pd_free(&y->g_pd);
if (chkdsp) canvas_update_dsp();
if (drawcommand)
canvas_redrawallfortemplate(tmpl, 1);
{
if (!(canvas_isgroup(canvas) && canvas->gl_isdeleting))
canvas_redrawallfortemplate(tmpl, 1);
}
canvas_setdeleting(canvas, wasdeleting);
x->gl_valid = ++glist_valid;
if (late_rtext_free)
......
......@@ -137,24 +137,65 @@ int template_hasxy(t_template *template)
return 0;
}
int template_cancreate(t_template *template)
int template_check_array_fields(t_symbol *structname, t_template *template)
{
/* We're calling this from template_cancreate as well as
gtemplate_cancreate.
With gtemplate_cancreate, the t_template doesn't exist yet.
So we send the struct name to see if it matches the name of any
array field templates that our gtemplate will depend on. If we find
a match we will refuse to create the gtemplate.
However, template_cancreate starts from the struct name for a template
that already exists. So on the first time through this recursive
function, there isn't a containing structname yet.
So we suppress this conditional the first
time through the recursive loop, and then set the structname for
all subsequent iterations through the loop. */
if (structname && structname == template->t_sym)
{
return 0;
}
int i, nitems = template->t_n;
t_dataslot *datatypes = template->t_vec;
t_template *elemtemplate;
for (i = 0; i < nitems; i++, datatypes++)
if (datatypes->ds_type == DT_ARRAY &&
(!(elemtemplate = template_findbyname(datatypes->ds_arraytemplate))
|| !template_cancreate(elemtemplate)))
{
t_object *ob = template_getstruct(template);
pd_error(ob, "%s: no such template",
datatypes->ds_arraytemplate->s_name);
return (0);
if (datatypes->ds_type == DT_ARRAY)
{
elemtemplate = template_findbyname(datatypes->ds_arraytemplate);
if (!(elemtemplate))
{
t_object *ob = template_getstruct(template);
pd_error(ob, "%s: no such template",
datatypes->ds_arraytemplate->s_name);
return (0);
}
else if (elemtemplate->t_sym == structname)
{
t_object *ob = template_getstruct(template);
pd_error(ob, "%s: circular dependency",
datatypes->ds_arraytemplate->s_name);
return (0);
}
else
{
if (!structname)
{
structname = template->t_sym;
}
return (template_check_array_fields(structname, elemtemplate));
}
}
}
return (1);
}
int template_cancreate(t_template *template)
{
/* we send "0" for the structname since there is no container struct */
return (template_check_array_fields(0, template));
}
/* make a new scalar and add to the glist. We create a "gp" here which
will be used for array items to point back here. This gp doesn't do
reference counting or "validation" updates though; the parent won't go away
......
......@@ -580,6 +580,8 @@ instructions for the template. The template doesn't go away when the
"struct" is deleted, so that you can replace it with
another one to add new fields, for example. */
static void gtemplate_free(t_gtemplate *x);
static void *gtemplate_donew(t_symbol *sym, int argc, t_atom *argv)
{
t_canvas *cur = canvas_getcurrent();
......@@ -626,16 +628,6 @@ static void *gtemplate_donew(t_symbol *sym, int argc, t_atom *argv)
our own and conform it. */
t_template *y = template_new(&s_, argc, argv);
/* I'm not _exactly_ sure about this. It's possible
that the user could screw up a nested array construction
and end up with scalars that aren't able to conform. On
the other hand, this keeps us from crashing if a non-
existent array template is typed into the box. */
if (!template_cancreate(y))
{
return 0;
}
canvas_redrawallfortemplate(t, 2);
/* Unless the new template is different from the old one,
there's nothing to do. */
......@@ -656,17 +648,66 @@ static void *gtemplate_donew(t_symbol *sym, int argc, t_atom *argv)
/* otherwise make a new one and we're the only struct on it. */
x->x_template = t = template_new(sym, argc, argv);
t->t_list = x;
}
}
outlet_new(&x->x_obj, 0);
return (x);
}
int template_check_array_fields(t_symbol *structname, t_template *template);
/* probably duplicating some code from template_new here... */
int gtemplate_cancreate(t_symbol *templatename, int argc, t_atom *argv)
{
while (argc > 1)
{
t_symbol *typesym = argv[0].a_w.w_symbol;
if (typesym == &s_float || typesym == &s_symbol)
{
argc -= 2;
argv += 2;
}
else if (typesym == gensym("array"))
{
if (argc > 2 && argv[2].a_type == A_SYMBOL)
{
/* check for cancreation here */
t_template *elemtemplate =
template_findbyname(canvas_makebindsym(argv[2].a_w.w_symbol));
if (!elemtemplate ||
!template_check_array_fields(
canvas_makebindsym(templatename), elemtemplate))
{
return 0;
}
argc -= 3;
argv += 3;
}
else
{
argc -= 2;
argv += 2;
}
}
else
{
argc -= 2;
argv += 2;
}
}
return 1;
}
static void *gtemplate_new(t_symbol *s, int argc, t_atom *argv)
{
t_symbol *sym = atom_getsymbolarg(0, argc, argv);
if (argc >= 1)
argc--; argv++;
return (gtemplate_donew(canvas_makebindsym(sym), argc, argv));
if (gtemplate_cancreate(sym, argc, argv))
{
return (gtemplate_donew(canvas_makebindsym(sym), argc, argv));
}
else
return 0;
}
/* old version (0.34) -- delete 2003 or so */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment