From 1f29bedf5a5f76c83d17dfce4664e7d38e101a1c Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Mon, 17 Aug 2015 01:12:01 -0400
Subject: [PATCH] first shot at "canvas" data type for data structures

---
 pd/src/g_canvas.h    |  2 +-
 pd/src/g_readwrite.c | 20 +++++++++++---------
 pd/src/g_scalar.c    | 45 ++++++++++++++++++++++++++++++++++++++++++--
 pd/src/g_template.c  | 23 +++++++++++++++++++++-
 4 files changed, 77 insertions(+), 13 deletions(-)

diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h
index c67fcb0ff..703b4c18e 100644
--- a/pd/src/g_canvas.h
+++ b/pd/src/g_canvas.h
@@ -255,7 +255,7 @@ typedef struct _dataslot
     int ds_type;
     t_symbol *ds_name;
     t_symbol *ds_fieldtemplate;     /* filled in for arrays only */
-    t_binbuf *ds_canvas;            /* binbuf of an abstraction to be loaded */
+    t_binbuf *ds_binbuf;            /* binbuf of an abstraction to be loaded */
 } t_dataslot;
 
 typedef struct _template
diff --git a/pd/src/g_readwrite.c b/pd/src/g_readwrite.c
index 10f6741c4..78f8dd19e 100644
--- a/pd/src/g_readwrite.c
+++ b/pd/src/g_readwrite.c
@@ -95,12 +95,12 @@ static void glist_readatoms(t_glist *x, int natoms, t_atom *vec,
         }
         else if (template->t_vec[i].ds_type == DT_LIST)
         {
-            while (1)
-            {
-                if (!glist_readscalar(w->w_list, natoms, vec,
-                    p_nextmsg, 0))
-                        break;
-            }
+//            while (1)
+//            {
+//                if (!glist_readscalar(w->w_list, natoms, vec,
+//                    p_nextmsg, 0))
+//                        break;
+//            }
         }
     }
 }
@@ -428,7 +428,7 @@ void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
         }
         else if (template->t_vec[i].ds_type == DT_LIST)
         {
-            glist_writelist(w->w_list->gl_list, b);
+//            glist_writelist(w->w_list->gl_list, b);
             binbuf_addsemi(b);
         }
     }
@@ -475,8 +475,10 @@ static void canvas_addtemplatesforscalar(t_symbol *templatesym,
                         p_ntemplates, p_templatevec);
         }
         else if (ds->ds_type == DT_LIST)
-            canvas_addtemplatesforlist(w->w_list->gl_list,
-                p_ntemplates, p_templatevec);
+        {
+//            canvas_addtemplatesforlist(w->w_list->gl_list,
+//                p_ntemplates, p_templatevec);
+        }
     }
 }
 
diff --git a/pd/src/g_scalar.c b/pd/src/g_scalar.c
index a0b2f7d33..13767fb46 100644
--- a/pd/src/g_scalar.c
+++ b/pd/src/g_scalar.c
@@ -16,6 +16,8 @@ can contain numbers, sublists, and arrays.
 
 t_class *scalar_class;
 
+void pd_doloadbang(void);
+
 void word_init(t_word *wp, t_template *template, t_gpointer *gp)
 {
     int i, nitems = template->t_n;
@@ -33,8 +35,47 @@ void word_init(t_word *wp, t_template *template, t_gpointer *gp)
         }
         else if (type == DT_LIST)
         {
-                /* LATER test this and get it to work */
-            wp->w_list = canvas_new(0, 0, 0, 0);
+            /* copied from glob_evalfile... */
+            t_pd *x = 0;
+            /* even though binbuf_evalfile appears to take care of dspstate,
+            we have to do it again here, because canvas_startdsp() assumes
+            that all toplevel canvases are visible.  LATER check if this
+            is still necessary -- probably not. */
+            int dspstate = canvas_suspend_dsp();
+// this needs to be set to sane symbols, possibly stored in the dataslot...
+            glob_setfilename(0, gensym("foo"), gensym("bar"));
+            t_pd *boundx = s__X.s_thing;
+            s__X.s_thing = 0;       /* don't save #X; we'll need to leave it
+                                       bound for the caller to grab it. */
+
+            /* copied from binbuf_evalfile... we need to refactor at some
+               point... */
+            /* save bindings of symbols #N, #A (and restore afterward) */
+            t_pd *bounda = gensym("#A")->s_thing, *boundn = s__N.s_thing;
+            gensym("#A")->s_thing = 0;
+            s__N.s_thing = &pd_canvasmaker;
+            binbuf_eval(datatypes->ds_binbuf, 0, 0, 0);
+            gensym("#A")->s_thing = bounda;
+            s__N.s_thing = boundn;
+            glob_setfilename(0, &s_, &s_);
+
+            wp->w_list = canvas_getcurrent();
+
+            while ((x != s__X.s_thing) && s__X.s_thing) 
+            {
+                x = s__X.s_thing;
+                vmess(x, gensym("pop"), "i", 1);
+            }
+            /* oops, can't actually do a loadbang here.
+               Why?
+               Consider getting the value of a fielddesc that hasn't
+               been init'd yet... */
+            /* pd_doloadbang(); */
+            canvas_resume_dsp(dspstate);
+
+            s__X.s_thing = boundx;
+            post("eval'd a canvas with addy x%lx", (long unsigned int)
+                wp->w_list);
         }
     }
 }
diff --git a/pd/src/g_template.c b/pd/src/g_template.c
index 9678bc0a6..e0a38c19b 100644
--- a/pd/src/g_template.c
+++ b/pd/src/g_template.c
@@ -74,6 +74,7 @@ t_template *template_new(t_symbol *templatesym, int argc, t_atom *argv)
     {
         int newtype, oldn, newn;
         t_symbol *newname, *newarraytemplate = &s_, *newtypesym;
+        t_binbuf *newbinbuf = NULL;
         if (argc < 2 || argv[0].a_type != A_SYMBOL ||
             argv[1].a_type != A_SYMBOL)
                 goto bad;
@@ -83,8 +84,27 @@ t_template *template_new(t_symbol *templatesym, int argc, t_atom *argv)
             newtype = DT_FLOAT;
         else if (newtypesym == &s_symbol)
             newtype = DT_SYMBOL;
-        else if (newtypesym == &s_list)
+//        else if (newtypesym == &s_list)
+//            newtype = DT_LIST;
+        else if (newtypesym == gensym("canvas"))
+        {
+            t_symbol *filename;
+            t_binbuf *b = binbuf_new();
+            if (argc < 3 || argv[2].a_type != A_SYMBOL)
+            {
+                pd_error(x, "canvas lacks template or name");
+                goto bad;
+            }
+//            filename = canvas_makebindsym(argv[2].a_w.w_symbol);
+            filename = argv[2].a_w.w_symbol;
+            if (binbuf_read_via_canvas(b, filename->s_name, canvas_getcurrent(), 0))
+                post("warning: abstraction %s not found", filename->s_name);
+            else
+                newbinbuf = b;
             newtype = DT_LIST;
+            argc--;
+            argv++;
+        }
         else if (newtypesym == gensym("array"))
         {
             if (argc < 3 || argv[2].a_type != A_SYMBOL)
@@ -109,6 +129,7 @@ t_template *template_new(t_symbol *templatesym, int argc, t_atom *argv)
         x->t_vec[oldn].ds_type = newtype;
         x->t_vec[oldn].ds_name = newname;
         x->t_vec[oldn].ds_fieldtemplate = newarraytemplate;
+        x->t_vec[oldn].ds_binbuf = newbinbuf;
     bad: 
         argc -= 2; argv += 2;
     }
-- 
GitLab