From f7ff410e6d87247af535c1f9d3e71095d898a739 Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Sun, 29 Oct 2017 23:50:14 -0400
Subject: [PATCH] get scalar event callbacks working with the correct gpointers

---
 pd/nw/pd_canvas.js   |  4 +--
 pd/nw/pdgui.js       |  6 ++--
 pd/src/g_template.c  | 70 ++++++++++++++++++++++++++++++++++++++++----
 pd/src/g_traversal.c |  2 +-
 4 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index 8531298f1..a7bc28e4e 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -450,8 +450,8 @@ var canvas_events = (function() {
                     ty = minv.b * dx + minv.d * dy;
                 var obj = scalar_draggables[draggable_elem.id];
                 pdgui.pdsend(obj.cid, "scalar_event", obj.scalar_sym,
-                    obj.drawcommand_sym, obj.event_name, dx, dy, tx, ty,
-                    obj.array_sym, obj.index);
+                    obj.drawcommand_sym, obj.array_sym, obj.index,
+                    obj.event_name, dx, dy, tx, ty);
                 last_draggable_x = new_x;
                 last_draggable_y = new_y;
             },
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index 8b3f1a475..70966a645 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -3351,7 +3351,7 @@ function gui_draw_drag_event(cid, tag, scalar_sym, drawcommand_sym,
         win.canvas_events.remove_scalar_draggable(tag);
     } else {
         win.canvas_events.add_scalar_draggable(cid, tag, scalar_sym,
-            drawcommand_sym, event_name);
+            drawcommand_sym, event_name, array_sym, index);
     }
 }
 
@@ -3362,8 +3362,8 @@ function gui_draw_event(cid, tag, scalar_sym, drawcommand_sym, event_name,
         event_type = "on" + event_name;
     if (state === 1) {
         item[event_type] = function(e) {
-            pdsend(cid, "scalar_event", scalar_sym, drawcommand_sym, event_name,
-                e.pageX, e.pageY, array_sym, index);
+            pdsend(cid, "scalar_event", scalar_sym, drawcommand_sym,
+                array_sym, index, event_name, e.pageX, e.pageY);
         };
     } else {
         item[event_type] = null;
diff --git a/pd/src/g_template.c b/pd/src/g_template.c
index b300d0c4e..6d2442c3f 100644
--- a/pd/src/g_template.c
+++ b/pd/src/g_template.c
@@ -1236,14 +1236,17 @@ typedef struct _drawarray
 
 extern t_outlet *obj_rightmost_outlet(t_object *x);
 
-void draw_notifyforscalar(t_object *x, t_glist *owner,
-    t_scalar *sc, t_symbol *s, int argc, t_atom *argv)
+void draw_notifyforscalar(t_object *x, t_glist *owner, t_array *a,
+    t_word *data, t_scalar *sc, t_symbol *s, int argc, t_atom *argv)
 {
     t_gpointer gp;
     t_binbuf *b = binbuf_new();
     t_atom at[1];
     gpointer_init(&gp);
-    gpointer_setglist(&gp, owner, &sc->sc_gobj);
+    if (a)
+        gpointer_setarray(&gp, a, data);
+    else
+        gpointer_setglist(&gp, owner, &sc->sc_gobj);
     SETPOINTER(at, &gp);
     binbuf_add(b, 1, at);
     binbuf_add(b, argc, argv);
@@ -4311,8 +4314,8 @@ static void draw_motion(void *z, t_floatarg dx, t_floatarg dy)
         /* LATER figure out what to do to notify for an array? */
     if (draw_motion_scalar)
     {
-        draw_notifyforscalar(&x->x_obj, draw_motion_glist, draw_motion_scalar,
-            gensym("drag"), 4, at);
+        draw_notifyforscalar(&x->x_obj, draw_motion_glist, 0, 0,
+            draw_motion_scalar, gensym("drag"), 4, at);
         template_notifyforscalar(draw_motion_template, draw_motion_glist, 
             draw_motion_scalar, gensym("change"), 1, at);
     }
@@ -4462,12 +4465,53 @@ static int draw_click(t_gobj *z, t_glist *glist,
     return (0);
 }
 
+/* given symbol "x123456", search the fields of a scalar's template for
+   a t_array that matches that addy. For now we only search the toplevel.
+   We can probably also search arbitrarily deep by making this recursive.
+   But the one person I know who uses nested ds arrays hasn't asked for
+   that, so let's see if we can just make it to the end of this software's
+   life before that happens. */
+static void scalar_spelunkforword(t_scalar *x, t_symbol *s, int word_index,
+    t_array **array, t_word **data)
+{
+    /* from glob_findinstance */
+    long obj = 0;
+    if (sscanf(s->s_name, "x%lx", &obj))
+    {
+        t_template *template = template_findbyname(x->sc_template);
+        if (!template)
+        {
+            pd_error(x, "scalar: template disappeared before notification "
+                        "from gui arrived");
+            return;
+        }
+        int i, nitems = template->t_n;
+        t_dataslot *datatypes = template->t_vec;
+        t_word *wp = x->sc_vec;
+        for (i = 0; i < nitems; i++, datatypes++, wp++)
+        {
+            if (datatypes->ds_type == DT_ARRAY &&
+                ((void *)wp->w_array) == (void *)obj &&
+                word_index < wp->w_array->a_n)
+            {
+                *array = wp->w_array;
+                *data = ((t_word *)(wp->w_array->a_vec +
+                    word_index * wp->w_array->a_elemsize));
+            }
+        }
+    }
+}
+
 void draw_notify(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
 {
     char canvas_field_namebuf[20];
     t_symbol *canvas_field_event;
     t_symbol *scalarsym = atom_getsymbolarg(0, argc--, argv++);
     t_symbol *drawcommand_sym = atom_getsymbolarg(0, argc--, argv++);
+    t_symbol *array_sym = atom_getsymbolarg(0, argc--, argv++);
+    t_array *a = 0;
+    t_word *data = 0;
+    int index = atom_getintarg(0, argc--, argv++);
     t_scalar *sc;
     t_object *ob = 0;
     if (scalarsym->s_thing)
@@ -4478,6 +4522,20 @@ void draw_notify(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         return;
     }
 
+    /* Now that we have our scalar, check if this callback is for an
+       array element that was drawn with [draw array]. If the index is zero
+       or greater then that's what we have */
+    if (index > -1)
+    {
+        scalar_spelunkforword(sc, array_sym, index, &a, &data);
+        if (!data)
+        {
+            pd_error(x, "scalar: couldn't get array data for event "
+                        "callback");
+            return;
+        }
+    }
+
     /* Generate the symbol that would be bound by any [event] inside
        a canvas field.  If there's any in existence, forward the event
        notification. pd_bind takes care of the details of this-- if 
@@ -4511,7 +4569,7 @@ void draw_notify(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         return;
     }
     if (ob)
-        draw_notifyforscalar(ob, x, sc, event_name, argc, argv);
+        draw_notifyforscalar(ob, x, a, data, sc, event_name, argc, argv);
 }
 
 
diff --git a/pd/src/g_traversal.c b/pd/src/g_traversal.c
index c1ecfd2f7..dc02eb675 100644
--- a/pd/src/g_traversal.c
+++ b/pd/src/g_traversal.c
@@ -752,7 +752,7 @@ static void set_setup(void)
         A_SYMBOL, A_SYMBOL, 0); 
 }
 
-/* ---------------------- elem ----------------------------- */
+/* ---------------------- element ----------------------------- */
 
 static t_class *elem_class;
 
-- 
GitLab