From fac506d1fe49dd52c9105bd2baf8cec123273fe9 Mon Sep 17 00:00:00 2001
From: Guillem <guillembartrina@gmail.com>
Date: Sat, 15 Aug 2020 14:11:31 +0200
Subject: [PATCH] ab private abstractions clone integration [abclone]. first
 approach

---
 pd/src/g_canvas.c | 12 ++++++---
 pd/src/g_canvas.h |  1 +
 pd/src/g_clone.c  | 67 +++++++++++++++++++++++++++++++++++++++++++----
 pd/src/g_editor.c | 31 +++++++++++++++++-----
 4 files changed, 97 insertions(+), 14 deletions(-)

diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index f2c717241..b7b6d5ad1 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -1926,7 +1926,8 @@ static t_pd *do_create_ab(t_ab_definition *abdef, int argc, t_atom *argv)
     canvas_popabstraction((t_canvas *)(s__X.s_thing));
     canvas_setargs(0, 0);
 
-    canvas_vis((t_canvas *)newest, !glist_amreloadingabstractions 
+    canvas_vis((t_canvas *)newest, !glist_amreloadingabstractions
+                                    && !abdef->ad_numinstances
                                     && binbuf_getnatom(abdef->ad_source) == 3);
 
     return(newest);
@@ -1935,8 +1936,10 @@ static t_pd *do_create_ab(t_ab_definition *abdef, int argc, t_atom *argv)
 /* get root canvas crossing ab boundaries, where ab definitions are stored */
 static t_canvas *canvas_getrootfor_ab(t_canvas *x)
 {
-    if (!x->gl_owner || (canvas_isabstraction(x) && !x->gl_isab))
+    if ((!x->gl_owner && !x->gl_isclone) || (canvas_isabstraction(x) && !x->gl_isab))
         return (x);
+    else if (x->gl_isab)
+        return (x->gl_absource->ad_owner);
     else
         return (canvas_getrootfor_ab(x->gl_owner));
 }
@@ -1963,7 +1966,7 @@ static int canvas_register_ab(t_canvas *x, t_ab_definition *a)
 {
     t_canvas *r = canvas_getrootfor_ab(x), *c = x;
 
-    while(c != r)
+    while(c && c != r)
     {
         if(c->gl_isab)
         {
@@ -1993,6 +1996,7 @@ static int canvas_register_ab(t_canvas *x, t_ab_definition *a)
             {
                 a->ad_deprefs[i-1]++;
             }
+            return (1);
         }
         c = c->gl_owner;
     }
@@ -2034,6 +2038,7 @@ static int canvas_deregister_ab(t_canvas *x, t_ab_definition *a)
                 }
             }
             else bug("canvas_deregister_ab");
+            return (1);
         }
         c = c->gl_owner;
     }
@@ -2076,6 +2081,7 @@ static t_ab_definition *canvas_add_ab(t_canvas *x, t_symbol *name, t_binbuf *sou
         abdef->ad_name = name;
         abdef->ad_source = source;
         abdef->ad_numinstances = 0;
+        abdef->ad_owner = c;
         abdef->ad_numdep = 0;
         abdef->ad_dep = (t_ab_definition **)getbytes(0);
         abdef->ad_deprefs = (int *)getbytes(0);
diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h
index 4daffab62..dc4ce7f22 100644
--- a/pd/src/g_canvas.h
+++ b/pd/src/g_canvas.h
@@ -172,6 +172,7 @@ typedef struct _ab_definition
     t_binbuf *ad_source;    /* binbuf where source is stored */
     int ad_numinstances;    /* the num of instances of this abstraction */
     struct _ab_definition *ad_next; /* next ab definition */
+    t_canvas *ad_owner;
 
     /* dependency graph stuff */
     int ad_numdep;      /* number of other ab definitions that it depends on */
diff --git a/pd/src/g_clone.c b/pd/src/g_clone.c
index 2529161e6..c58c33f3d 100644
--- a/pd/src/g_clone.c
+++ b/pd/src/g_clone.c
@@ -63,6 +63,7 @@ typedef struct _clone
     int x_phase;
     int x_startvoice;   /* number of first voice, 0 by default */
     int x_suppressvoice; /* suppress voice number as $1 arg */
+    t_canvas *x_owner;
 } t_clone;
 
 int clone_match(t_pd *z, t_symbol *name, t_symbol *dir)
@@ -74,6 +75,36 @@ int clone_match(t_pd *z, t_symbol *name, t_symbol *dir)
         canvas_getdir(x->x_vec[0].c_gl) == dir);
 }
 
+int clone_isab(t_pd *z)
+{
+    t_clone *x = (t_clone *)z;
+    if (!x->x_n)
+        return (0);
+    return (x->x_vec[0].c_gl->gl_isab);
+}
+
+int clone_matchab(t_pd *z, t_ab_definition *source)
+{
+    t_clone *x = (t_clone *)z;
+    return (clone_isab(z) && x->x_vec[0].c_gl->gl_absource == source);
+}
+
+int clone_getncopies(t_pd *z)
+{
+    t_clone *x = (t_clone *)z;
+    return (x->x_n);
+}
+
+t_glist **clone_getglists(t_pd *z)
+{
+    t_clone *x = (t_clone *)z;
+    t_glist **glists = (t_glist *)getbytes(sizeof(t_glist *)*x->x_n);
+    int i;
+    for(i = 0; i < x->x_n; i++)
+        glists[i] = x->x_vec[i].c_gl;
+    return glists;
+}
+
 void obj_sendinlet(t_object *x, int n, t_symbol *s, int argc, t_atom *argv);
 
 static void clone_in_list(t_in *x, t_symbol *s, int argc, t_atom *argv)
@@ -175,6 +206,8 @@ static void clone_free(t_clone *x)
         for (i = 0; i < x->x_n; i++)
         {
             canvas_closebang(x->x_vec[i].c_gl);
+            if(x->x_vec[i].c_gl->gl_isab) //only for abs?
+                x->x_vec[i].c_gl->gl_owner = x->x_owner;
             pd_free(&x->x_vec[i].c_gl->gl_pd);
             t_freebytes(x->x_outvec[i],
                 x->x_nout * sizeof(*x->x_outvec[i]));
@@ -228,7 +261,7 @@ void clone_setn(t_clone *x, t_floatarg f)
     {
         t_canvas *c;
         t_out *outvec;
-        SETFLOAT(x->x_argv, x->x_startvoice + i);
+        SETFLOAT((x->x_vec[0].c_gl->gl_isab ? x->x_argv+1 : x->x_argv), x->x_startvoice + i);
         if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice,
             x->x_argv + x->x_suppressvoice)))
         {
@@ -354,6 +387,7 @@ static void clone_dsp(t_clone *x, t_signal **sp)
     }
 }
 
+static int clone_newab = 0;
 static void *clone_new(t_symbol *s, int argc, t_atom *argv)
 {
     t_clone *x = (t_clone *)pd_new(clone_class);
@@ -393,10 +427,24 @@ static void *clone_new(t_symbol *s, int argc, t_atom *argv)
     else goto usage;
         /* store a copy of the argmuents with an extra space (argc+1) for
         supplying an instance number, which we'll bash as we go. */
-    x->x_argc = argc - 1;
-    x->x_argv = getbytes(x->x_argc * sizeof(*x->x_argv));
-    memcpy(x->x_argv, argv+1, x->x_argc * sizeof(*x->x_argv));
-    SETFLOAT(x->x_argv, x->x_startvoice);
+    if(clone_newab)
+    {
+        x->x_argc = argc;
+        x->x_argv = getbytes(x->x_argc * sizeof(*x->x_argv));
+        memcpy(x->x_argv, argv, x->x_argc * sizeof(*x->x_argv));
+        SETSYMBOL(x->x_argv, x->x_s);
+        SETFLOAT(x->x_argv+1, x->x_startvoice);
+        x->x_s = gensym("ab");
+        x->x_owner = canvas_getcurrent();
+        clone_newab = 0;
+    }
+    else
+    {
+        x->x_argc = argc - 1;
+        x->x_argv = getbytes(x->x_argc * sizeof(*x->x_argv));
+        memcpy(x->x_argv, argv+1, x->x_argc * sizeof(*x->x_argv));
+        SETFLOAT(x->x_argv, x->x_startvoice);
+    }
     if (!(c = clone_makeone(x->x_s, x->x_argc - x->x_suppressvoice,
         x->x_argv + x->x_suppressvoice)))
             goto fail;
@@ -444,10 +492,19 @@ fail:
     return (0);
 }
 
+static void *abclone_new(t_symbol *s, int argc, t_atom *argv)
+{
+    clone_newab = 1;
+    return clone_new(s, argc, argv);
+}
+
 void clone_setup(void)
 {
     clone_class = class_new(gensym("clone"), (t_newmethod)clone_new,
         (t_method)clone_free, sizeof(t_clone), CLASS_NOINLET, A_GIMME, 0);
+
+    class_addcreator((t_newmethod)abclone_new, gensym("abclone"), A_GIMME, 0);
+
     class_addmethod(clone_class, (t_method)clone_click, gensym("click"),
         A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
     class_addmethod(clone_class, (t_method)clone_loadbang, gensym("loadbang"),
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index c78cc7b14..ff61bbd60 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -1401,17 +1401,27 @@ void canvas_reload(t_symbol *name, t_symbol *dir, t_gobj *except)
     canvas_resume_dsp(dspwas);
 }
 
+int clone_isab(t_pd *z);
+int clone_matchab(t_pd *z, t_ab_definition *source);
+int clone_getncopies(t_pd *z);
+t_glist **clone_getglists(t_pd *z);
+
 /* recursive ab reload method */
 void canvas_reload_ab_rec(t_canvas *x, t_ab_definition *a, t_gobj *e)
 {
     t_gobj *g;
     int i, nobj = glist_getindex(x, 0);
     int hadwindow = x->gl_havewindow, found = 0;
+    int remakeit = 0;
 
     for (g = x->gl_list, i = 0; g && i < nobj; i++)
     {
-        if(g != e && pd_class(&g->g_pd) == canvas_class && canvas_isabstraction((t_canvas *)g)
-            && ((t_canvas *)g)->gl_isab && ((t_canvas *)g)->gl_absource == a)
+        remakeit = (g != e && pd_class(&g->g_pd) == canvas_class && canvas_isabstraction((t_canvas *)g)
+            && ((t_canvas *)g)->gl_isab && ((t_canvas *)g)->gl_absource == a);
+
+        remakeit = remakeit || (pd_class(&g->g_pd) == clone_class && clone_matchab(&g->g_pd, a));
+
+        if(remakeit)
         {
             canvas_create_editor(x);
 
@@ -1439,11 +1449,20 @@ void canvas_reload_ab_rec(t_canvas *x, t_ab_definition *a, t_gobj *e)
 
     for (g = x->gl_list, i = 0; g && i < nobj; i++)
     {
-        if(pd_class(&g->g_pd) == canvas_class
-            && (!canvas_isabstraction((t_canvas *)g)
-                    || (((t_canvas *)g)->gl_isab
-                        && (((t_canvas *)g)->gl_absource != a))))
+        if(pd_class(&g->g_pd) == canvas_class && (!canvas_isabstraction((t_canvas *)g)
+                    || (((t_canvas *)g)->gl_isab && (((t_canvas *)g)->gl_absource != a))))
             canvas_reload_ab_rec((t_canvas *)g, a, e);
+
+        if(pd_class(&g->g_pd) == clone_class
+            && clone_isab(&g->g_pd) && !clone_matchab(&g->g_pd, a))
+        {
+            int numglists = clone_getncopies(&g->g_pd), j;
+            t_glist **glists = clone_getglists(&g->g_pd);
+            for(j = 0; j < numglists; j++)
+                canvas_reload_ab_rec((t_canvas *)glists[j], a, e);
+            freebytes(glists, sizeof(t_glist *)*numglists);
+        }
+
         g = g->g_next;
     }
     if (!hadwindow && x->gl_havewindow)
-- 
GitLab