From 4f9cc742c520fd77d64b7b501d0d9319a116c747 Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@vt.edu>
Date: Fri, 13 Jul 2012 21:33:26 -0400
Subject: [PATCH] added first version of the global/universal preset system
 using objects preset_hub and preset_node

---
 src/g_bang.c       |   1 -
 src/g_canvas.c     |  34 +++++++-----
 src/g_canvas.h     | 132 ++++++++++++++++++++++++++++++++++++++-------
 src/g_editor.c     |  79 +++++++++++++++++++++++----
 src/g_hdial.c      |   1 -
 src/g_hslider.c    |   1 -
 src/g_mycanvas.c   |   1 -
 src/g_numbox.c     |   1 -
 src/g_text.c       | 104 +++++++++++++++++++++++++----------
 src/g_toggle.c     |   1 -
 src/g_undo.c       |  10 ++++
 src/g_undo.h       |   2 +-
 src/g_vdial.c      |   1 -
 src/g_vslider.c    |   1 -
 src/g_vumeter.c    |   1 -
 src/m_conf.c       |   1 +
 src/m_pd.c         |  69 ------------------------
 src/m_pd.h         |   2 +-
 src/x_connective.c |   6 +--
 19 files changed, 296 insertions(+), 152 deletions(-)

diff --git a/src/g_bang.c b/src/g_bang.c
index 018ae116d..f259c6b93 100644
--- a/src/g_bang.c
+++ b/src/g_bang.c
@@ -31,7 +31,6 @@ void bng_draw_select(t_bng* x, t_glist* glist);
 /* --------------- bng     gui-bang ------------------------- */
 
 t_widgetbehavior bng_widgetbehavior;
-static t_class *bng_class;
 
 /*  widget helper functions  */
 
diff --git a/src/g_canvas.c b/src/g_canvas.c
index 3577157d1..c12a2816d 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -920,11 +920,12 @@ static void canvas_drawlines(t_canvas *x)
         while (oc = linetraverser_next(&t))
     {
         issignal = (outlet_getsymbol(t.tr_outlet) == &s_signal ? 1 : 0);
-        sys_vgui(".x%lx.c create line %d %d %d %d -width %s -fill %s \
--tags {l%lx all_cords}\n",
-                 glist_getcanvas(x), t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2, 
-                 (issignal ? "$signal_cord_width" : "$msg_cord_width"), (issignal ? "$signal_cord" : "$msg_cord"),
-                 oc);
+		if (!(pd_class(&t.tr_ob2->ob_g.g_pd) == preset_node_class && pd_class(&t.tr_ob->ob_g.g_pd) != message_class))
+		    sys_vgui(".x%lx.c create line %d %d %d %d -width %s -fill %s \
+	-tags {l%lx all_cords}\n",
+		             glist_getcanvas(x), t.tr_lx1, t.tr_ly1, t.tr_lx2, t.tr_ly2, 
+		             (issignal ? "$signal_cord_width" : "$msg_cord_width"), (issignal ? "$signal_cord" : "$msg_cord"),
+		             oc);
     }
 }
 
@@ -1047,29 +1048,29 @@ void canvas_restore(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
     }
 }
 
-static void canvas_loadbangabstractions(t_canvas *x)
+static void canvas_loadbangabstractions(t_canvas *x, t_symbol *s)
 {
     t_gobj *y;
-    t_symbol *s = gensym("loadbang");
+    //t_symbol *s = gensym("loadbang");
     for (y = x->gl_list; y; y = y->g_next)
         if (pd_class(&y->g_pd) == canvas_class)
     {
         if (canvas_isabstraction((t_canvas *)y))
             canvas_loadbang((t_canvas *)y);
         else
-            canvas_loadbangabstractions((t_canvas *)y);
+            canvas_loadbangabstractions((t_canvas *)y, s);
     }
 }
 
-void canvas_loadbangsubpatches(t_canvas *x)
+void canvas_loadbangsubpatches(t_canvas *x, t_symbol *s)
 {
     t_gobj *y;
-    t_symbol *s = gensym("loadbang");
+    //t_symbol *s = gensym("loadbang");
     for (y = x->gl_list; y; y = y->g_next)
         if (pd_class(&y->g_pd) == canvas_class)
     {
         if (!canvas_isabstraction((t_canvas *)y))
-            canvas_loadbangsubpatches((t_canvas *)y);
+            canvas_loadbangsubpatches((t_canvas *)y, s);
     }
     for (y = x->gl_list; y; y = y->g_next)
         if ((pd_class(&y->g_pd) != canvas_class) &&
@@ -1079,9 +1080,14 @@ void canvas_loadbangsubpatches(t_canvas *x)
 
 void canvas_loadbang(t_canvas *x)
 {
-    t_gobj *y;
-    canvas_loadbangabstractions(x);
-    canvas_loadbangsubpatches(x);
+    //t_gobj *y;
+	// first loadbang preset hubs and nodes
+    canvas_loadbangabstractions(x, gensym("pre-loadbang"));
+    canvas_loadbangsubpatches(x, gensym("pre-loadbang"));
+
+	// then do the regular loadbang
+    canvas_loadbangabstractions(x, gensym("loadbang"));
+    canvas_loadbangsubpatches(x, gensym("loadbang"));
 }
 /* JMZ:
  * initbang is emitted after the canvas is done, but before the parent canvas is done
diff --git a/src/g_canvas.h b/src/g_canvas.h
index 0206f3803..179eca2a2 100644
--- a/src/g_canvas.h
+++ b/src/g_canvas.h
@@ -39,23 +39,6 @@ in future releases.  The public (stable) API is in m_pd.h. */
 #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
 extern "C" {
 #endif
-
-/* 	redundant struct queue for maintaining a list of redundantly
-	allocated memory chunks to avoid double-entry bug. these are
-	instantiated inside canvas_new since the bug only affects new
-	canvases/abstractions rather than individual objects. the queue
-	is destructed in m_glob.c quit call (when pd exits) */
-/*
-typedef struct _redundant_mem
-{
-    //int rm_what;
-	t_canvas *rm_canvas;
-    struct _redundant_mem *rm_next;
-} t_redundant_mem;
-
-t_redundant_mem *rm_start;
-t_redundant_mem *rm_end;
-*/
   
 /* --------------------- geometry ---------------------------- */
 #define IOWIDTH 7       /* width of an inlet/outlet in pixels */
@@ -98,6 +81,14 @@ EXTERN_STRUCT _magicGlass;
 #define t_magicGlass struct _magicGlass
 // end jsarlo
 
+// undo stuff
+EXTERN_STRUCT _undo_action;
+#define t_undo_action struct _undo_action
+
+// preset hub stuff
+EXTERN_STRUCT _preset_hub;
+#define t_preset_hub struct _preset_hub
+
 typedef struct _selection
 {
     t_gobj *sel_what;
@@ -166,7 +157,7 @@ area of a window.
 
 */
 
-#include "g_undo.h"
+//#include "g_undo.h"
 
 struct _glist
 {  
@@ -228,11 +219,43 @@ struct _glist
 	//infinite undo goodies
 	t_undo_action *u_queue;
 	t_undo_action *u_last;
+
+	//global preset array pointer
+	t_preset_hub *gl_phub;
 };
 
 #define gl_gobj gl_obj.te_g
 #define gl_pd gl_gobj.g_pd
 
+/*-------------------universal preset stuff---------------------*/
+// for the universal preset_node ability (see g_editor.c doconnect/disconnect functions)
+// this is where all the classes capable of being controlled via preset should be defined
+
+// preset objects
+t_class *preset_hub_class;
+t_class *preset_node_class;
+
+// core gui
+t_class *gatom_class;
+t_class *message_class;
+
+// core text
+extern t_class *pdint_class;
+extern t_class *pdfloat_class;
+extern t_class *pdsymbol_class;
+
+// iemgui
+t_class *bng_class;
+t_class *hradio_class, *hradio_old_class;
+t_class *hslider_class;
+t_class *my_canvas_class;
+t_class *my_numbox_class;
+t_class *toggle_class;
+t_class *vradio_class, *vradio_old_class;
+t_class *vslider_class;
+t_class *vu_class;
+/*-----------------end universal preset stuff-------------------*/
+
 /* a data structure to describe a field in a pure datum */
 
 #define DT_FLOAT 0
@@ -654,7 +677,6 @@ EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl,
 EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, t_float val);
 EXTERN t_float fielddesc_cvtfromcoord(t_fielddesc *f, t_float coord);
 
-
 /* ----------------------- guiconnects, g_guiconnect.c --------- */
 EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
 EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
@@ -663,6 +685,78 @@ EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
 EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
 EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
 
+/* ---------- infinite undo/redo routines found in g_undo.c ------------ */
+
+EXTERN t_undo_action *canvas_undo_init(t_canvas *x);
+EXTERN t_undo_action *canvas_undo_add(t_canvas *x,
+	int type, const char *name, void *data);
+EXTERN void canvas_undo_undo(t_canvas *x);
+EXTERN void canvas_undo_redo(t_canvas *x);
+EXTERN void canvas_undo_rebranch(t_canvas *x);
+EXTERN void canvas_undo_check_canvas_pointers(t_canvas *x);
+EXTERN void canvas_undo_purge_abstraction_actions(t_canvas *x);
+EXTERN void canvas_undo_free(t_canvas *x);
+
+/* --------- 1. connect ---------- */
+
+EXTERN void *canvas_undo_set_connect(t_canvas *x,
+    int index1, int outno, int index2, int inno);
+EXTERN void canvas_undo_connect(t_canvas *x, void *z, int action);
+
+/* --------- 2. disconnect ------- */
+
+EXTERN void *canvas_undo_set_disconnect(t_canvas *x,
+    int index1, int outno, int index2, int inno);
+EXTERN void canvas_undo_disconnect(t_canvas *x, void *z, int action);
+
+/* --------- 3. cut -------------- */
+
+EXTERN void *canvas_undo_set_cut(t_canvas *x, int mode);
+EXTERN void canvas_undo_cut(t_canvas *x, void *z, int action);
+
+/* --------- 4. move ------------- */
+
+EXTERN void *canvas_undo_set_move(t_canvas *x, int selected);
+EXTERN void canvas_undo_move(t_canvas *x, void *z, int action);
+
+/* --------- 5. paste ------------ */
+
+EXTERN void *canvas_undo_set_paste(t_canvas *x, int offset);
+EXTERN void canvas_undo_paste(t_canvas *x, void *z, int action);
+
+/* --------- 6. apply ------------ */
+
+EXTERN void *canvas_undo_set_apply(t_canvas *x, int n);
+EXTERN void canvas_undo_apply(t_canvas *x, void *z, int action);
+
+/* --------- 7. arrange ---------- */
+
+EXTERN void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex);
+EXTERN void canvas_undo_arrange(t_canvas *x, void *z, int action);
+
+/* --------- 8. canvas apply ----- */
+
+EXTERN void *canvas_undo_set_canvas(t_canvas *x);
+EXTERN void canvas_undo_canvas_apply(t_canvas *x, void *z, int action);
+
+/* --------- 9. create ----------- */
+
+EXTERN void canvas_undo_create(t_canvas *x, void *z, int action);
+EXTERN void *canvas_undo_set_create(t_canvas *x);
+
+/* --------- 10. recreate -------- */
+
+EXTERN void canvas_undo_recreate(t_canvas *x, void *z, int action);
+EXTERN void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y, int old_pos);
+
+/* --------- 11. font ------------ */
+
+EXTERN void canvas_undo_font(t_canvas *x, void *z, int action);
+EXTERN void *canvas_undo_set_font(t_canvas *x, int font);
+
+/* ------------------------------- */
+
+
 #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
 }
 #endif
diff --git a/src/g_editor.c b/src/g_editor.c
index 70336415b..31e6a8536 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -576,6 +576,7 @@ void *canvas_undo_set_disconnect(t_canvas *x,
 void canvas_disconnect(t_canvas *x,
     t_float index1, t_float outno, t_float index2, t_float inno)
 {
+	//fprintf(stderr,"canvas_disconnect\n");
     t_linetraverser t;
     t_outconnect *oc;
     linetraverser_start(&t, x);
@@ -594,6 +595,14 @@ void canvas_disconnect(t_canvas *x,
 			}
             // end jsarlo
             obj_disconnect(t.tr_ob, t.tr_outno, t.tr_ob2, t.tr_inno);
+
+			// if we are dealing with a preset_node, make sure to also disconnect its invisible return node
+			// we trust here that the object has been already connected to a valid object so we blindly
+			// disconnect first outlet with the first inlet
+			if (pd_class(&t.tr_ob->ob_g.g_pd) == preset_node_class) {
+				//fprintf(stderr,"gotta disconnect hidden one too...\n");
+				obj_disconnect(t.tr_ob2, 0, t.tr_ob, 0);
+			}
             break;
         }
     }
@@ -2914,6 +2923,7 @@ int canvas_isconnected (t_canvas *x, t_text *ob1, int n1,
 
 void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
 {
+	//fprintf(stderr,"canvas_doconnect\n");
     int x11=0, y11=0, x12=0, y12=0;
     t_gobj *y1;
     int x21=0, y21=0, x22=0, y22=0;
@@ -2988,6 +2998,36 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
             }
             if (doit)
             {
+				// if the first object is preset_node, check if the object we are connecting to
+				// is supported. If not, disallow connection
+				if (pd_class(&y1->g_pd) == preset_node_class) {
+					if (pd_class(&y2->g_pd) != gatom_class &&
+						pd_class(&y2->g_pd) != bng_class &&
+						pd_class(&y2->g_pd) != hradio_class &&
+						pd_class(&y2->g_pd) != hradio_old_class &&
+						pd_class(&y2->g_pd) != hslider_class &&
+						pd_class(&y2->g_pd) != my_canvas_class &&
+						pd_class(&y2->g_pd) != my_numbox_class &&
+						pd_class(&y2->g_pd) != toggle_class &&
+						pd_class(&y2->g_pd) != vradio_class &&
+						pd_class(&y2->g_pd) != vradio_old_class &&
+						pd_class(&y2->g_pd) != vslider_class &&
+						pd_class(&y2->g_pd) != vu_class &&
+						pd_class(&y2->g_pd) != pdint_class &&
+						pd_class(&y2->g_pd) != pdfloat_class &&
+						pd_class(&y2->g_pd) != pdsymbol_class) {
+						error("preset node currently works only with gui objects, ints, floats, and symbols...\n");
+						return;
+					}
+				}
+
+				// now check if explicit user-made connection into preset_node if kind other than message
+				// messages may be used to change node's operation
+				if (pd_class(&y2->g_pd) == preset_node_class && pd_class(&y1->g_pd) != message_class) {
+					error("preset node only accepts messages as input to set its destination preset_hub...\n");
+					return;
+				}
+
                 int issignal = obj_issignaloutlet(ob1, closest1);
                 oc = obj_connect(ob1, closest1, ob2, closest2);
                 lx1 = x11 + (noutlet1 > 1 ?
@@ -3038,6 +3078,16 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
 				canvas_undo_add(x, 1, "connect", canvas_undo_set_connect(x, 
                         canvas_getindex(x, &ob1->ob_g), closest1,
                         canvas_getindex(x, &ob2->ob_g), closest2));
+
+				// add auto-connect back to preset_node object
+				// (by this time we know we are connecting only to legal objects who have at least one outlet)
+				if (pd_class(&y1->g_pd) == preset_node_class) {
+					//fprintf(stderr,"gotta do auto-connect back to preset_node\n");
+					if (!canvas_isconnected(x, ob2, 0, ob1, 0))
+						obj_connect(ob2, 0, ob1, 0);
+					//else
+					//	fprintf(stderr,"error: already connected (this happens when loading from file and is ok)\n");
+				}
             }
     	    else 
             // jsarlo
@@ -4505,6 +4555,7 @@ extern t_class *text_class;
 void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
     t_floatarg fwhoin, t_floatarg finno)
 {
+	//fprintf(stderr,"canvas_connect\n");
 	if (!x->gl_list) {
 		post("paste error: no objects to connect, probably incomplete clipboard copy from an external source (e.g. from a text editor)");
 		return;		
@@ -4534,15 +4585,25 @@ void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
         while (inno >= obj_ninlets(objsink))
             inlet_new(objsink, &objsink->ob_pd, 0, 0);
 
-    if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad;
-    if (glist_isvisible(x))
-    {
-        sys_vgui(".x%lx.c create line %d %d %d %d -width %s -fill %s -tags {l%lx all_cords}\n",
-            glist_getcanvas(x), 0, 0, 0, 0,
-            (obj_issignaloutlet(objsrc, outno) ? "$signal_cord_width" : "$msg_cord_width"),
-            (obj_issignaloutlet(objsrc, outno) ? "$signal_cord" : "$msg_cord"), oc);
-        canvas_fixlinesfor(x, objsrc);
-    }
+	if (!canvas_isconnected(x, objsrc, outno, objsink, inno)) {
+    	if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad;
+		// add auto-connect back to preset_node object
+		// (by this time we know we are connecting only to legal objects who have at least one outlet)
+		if (pd_class(&objsrc->ob_pd) == preset_node_class) {
+			//fprintf(stderr,"canvas_connect: gotta do auto-connect back to preset_node\n");
+			if (!canvas_isconnected(x, objsink, 0, objsrc, 0))
+				obj_connect(objsink, 0, objsrc, 0);
+		}
+		if (glist_isvisible(x) && (pd_class(&sink->g_pd) != preset_node_class || (pd_class(&sink->g_pd) == preset_node_class && pd_class(&src->g_pd) == message_class)))
+		{
+			//fprintf(stderr,"draw line\n");
+		    sys_vgui(".x%lx.c create line %d %d %d %d -width %s -fill %s -tags {l%lx all_cords}\n",
+		        glist_getcanvas(x), 0, 0, 0, 0,
+		        (obj_issignaloutlet(objsrc, outno) ? "$signal_cord_width" : "$msg_cord_width"),
+		        (obj_issignaloutlet(objsrc, outno) ? "$signal_cord" : "$msg_cord"), oc);
+		    canvas_fixlinesfor(x, objsrc);
+		}
+	}
     return;
 
 bad:
diff --git a/src/g_hdial.c b/src/g_hdial.c
index 6b9870708..f0d747d5f 100644
--- a/src/g_hdial.c
+++ b/src/g_hdial.c
@@ -34,7 +34,6 @@ void hradio_draw_select(t_hradio* x, t_glist* glist);
 /* ------------- hdl     gui-horicontal dial ---------------------- */
 
 t_widgetbehavior hradio_widgetbehavior;
-static t_class *hradio_class, *hradio_old_class;
 
 /* widget helper functions */
 
diff --git a/src/g_hslider.c b/src/g_hslider.c
index 37561b1ad..320a2e3f5 100644
--- a/src/g_hslider.c
+++ b/src/g_hslider.c
@@ -31,7 +31,6 @@ static void hslider_draw_select(t_hslider* x,t_glist* glist);
 /* ------------ hsl    gui-horicontal  slider ----------------------- */
 
 t_widgetbehavior hslider_widgetbehavior;
-static t_class *hslider_class;
 
 static double last;
 static int is_last_float = 0;
diff --git a/src/g_mycanvas.c b/src/g_mycanvas.c
index 5f3b8f53c..fe47c6abc 100644
--- a/src/g_mycanvas.c
+++ b/src/g_mycanvas.c
@@ -31,7 +31,6 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist);
 /* ---------- cnv  my gui-canvas for a window ---------------- */
 
 t_widgetbehavior my_canvas_widgetbehavior;
-static t_class *my_canvas_class;
 
 /* widget helper functions */
 
diff --git a/src/g_numbox.c b/src/g_numbox.c
index a229ea696..dd6b3a4fc 100644
--- a/src/g_numbox.c
+++ b/src/g_numbox.c
@@ -38,7 +38,6 @@ static void my_numbox_draw_update(t_gobj *client, t_glist *glist);
 /* ------------ nmx gui-my number box ----------------------- */
 
 t_widgetbehavior my_numbox_widgetbehavior;
-static t_class *my_numbox_class;
 
 /* widget helper functions */
 
diff --git a/src/g_text.c b/src/g_text.c
index 63cca65a6..047836016 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -15,10 +15,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
+#include "g_undo.h"
+#include "x_preset.h"
 
 t_class *text_class;
-static t_class *message_class;
-static t_class *gatom_class;
 static void text_vis(t_gobj *z, t_glist *glist, int vis);
 static void text_displace(t_gobj *z, t_glist *glist,
     int dx, int dy);
@@ -100,6 +100,12 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
     t_text *x;
     int argc;
     t_atom *argv;
+
+	// for hiding arguments
+	t_atom *vec;
+	int len, i, hidden;
+	t_binbuf *hide;
+
     newest = 0;
     canvas_setcurrent((t_canvas *)gl);
     canvas_getargs(&argc, &argv);
@@ -125,12 +131,34 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
 		//fprintf(stderr,"creating blank object\n");
 		x = (t_text *)pd_new(text_class);
     }
+	/* special case: an object, like preset_hub, hides its arguments beyond the first n, so
+	   we modify its binbuf here */
+	vec = binbuf_getvec(b);
+	len = binbuf_getnatom(b);
+	hidden = 0;
+	for (i = 0; i < len; i++) {
+		if (!strcmp("%hidden%", atom_getsymbol(&vec[i])->s_name)) {
+			//fprintf(stderr,"found hidden %d %s\n", i, atom_getsymbol(&vec[i])->s_name);
+			hidden = i;
+			break;
+		}
+	}
+	if (hidden) {
+		hide = binbuf_new();
+		binbuf_add(hide, hidden, vec);
+		binbuf_free(b);
+		b = hide;
+	}
+	/* done special case */
+
     x->te_binbuf = b;
+
     x->te_xpix = xpix;
     x->te_ypix = ypix;
     x->te_width = 0;
     x->te_type = T_OBJECT;
     glist_add(gl, &x->te_g);
+
     if (selected)
     {
             /* this is called if we've been created from the menu. */
@@ -407,7 +435,7 @@ typedef struct _message
     t_clock *m_clock;
 } t_message;
 
-static t_class *message_class, *messresponder_class;
+static t_class *messresponder_class;
 
 static void messresponder_bang(t_messresponder *x)
 {
@@ -1337,28 +1365,46 @@ static void text_delete(t_gobj *z, t_glist *glist)
 
 static void text_vis(t_gobj *z, t_glist *glist, int vis)
 {
+	//fprintf(stderr,"text_vis\n");
     t_text *x = (t_text *)z;
-    if (vis)
-    {
-        if (gobj_shouldvis(&x->te_g, glist))
-        {
-            t_rtext *y = glist_findrtext(glist, x);
-            if (x->te_type == T_ATOM)
-                glist_retext(glist, x);
-            text_drawborder(x, glist, rtext_gettag(y),
-                rtext_width(y), rtext_height(y), 1);
-            rtext_draw(y);
-        }
-    }
-    else
-    {
-        t_rtext *y = glist_findrtext(glist, x);
-        if (gobj_shouldvis(&x->te_g, glist))
-        {
-            text_eraseborder(x, glist, rtext_gettag(y));
-            rtext_erase(y);
-        }
-    }
+
+#ifdef PDL2ORK
+	//if we are in k12 mode and this is hub with level 1 (global) don't draw it and make its width/height 0
+	int exception = 0;
+	if (pd_class(&x->te_pd) == preset_hub_class && sys_k12_mode) {
+		fprintf(stderr,"text_vis reports preset_hub_class detected\n");
+		t_preset_hub *h = (t_preset_hub *)z;
+		if (h->ph_invis) {
+			exception = 1;
+			x->te_width = 0;
+		}
+	}
+	if (!exception) {
+#endif
+		if (vis)
+		{
+		    if (gobj_shouldvis(&x->te_g, glist))
+		    {
+		        t_rtext *y = glist_findrtext(glist, x);
+		        if (x->te_type == T_ATOM)
+		            glist_retext(glist, x);
+		        text_drawborder(x, glist, rtext_gettag(y),
+		            rtext_width(y), rtext_height(y), 1);
+		        rtext_draw(y);
+		    }
+		}
+		else
+		{
+		    t_rtext *y = glist_findrtext(glist, x);
+		    if (gobj_shouldvis(&x->te_g, glist))
+		    {
+		        text_eraseborder(x, glist, rtext_gettag(y));
+		        rtext_erase(y);
+		    }
+		}
+#ifdef PDL2ORK
+	}
+#endif
 }
 
 static int text_click(t_gobj *z, struct _glist *glist,
@@ -1841,6 +1887,7 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize, int pos)
 	char *c1, *c2;
 	int i1, i2;
 
+
     if (x->te_type == T_OBJECT)
     {
         t_binbuf *b = binbuf_new();
@@ -1851,16 +1898,18 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize, int pos)
         vec1 = binbuf_getvec(x->te_binbuf);
         natom2 = binbuf_getnatom(b);
         vec2 = binbuf_getvec(b);
-            /* special case: if  pd args change just pass the message on. */
-        if (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL
+            /* special case: if pd subpatch is valid and its args change, and its new name is valid, just pass the message on. */
+        if (x->te_pd == canvas_class && (natom1 >= 1 && natom2 >= 1 && vec1[0].a_type == A_SYMBOL
             && !strcmp(vec1[0].a_w.w_symbol->s_name, "pd") &&
              vec2[0].a_type == A_SYMBOL
-            && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
+            && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd") && vec2[1].a_type == A_SYMBOL))
         {
+			//fprintf(stderr,"setto canvas\n");
 			//first check if the contents have changed to see if there is any point of recreating the object
 			binbuf_gettext(x->te_binbuf, &c1, &i1);
 			binbuf_gettext(b, &c2, &i2);
 			if (strcmp(c1, c2)) {
+				//fprintf(stderr,"string differs\n");
 				canvas_undo_add(glist_getcanvas(glist), 10, "recreate",
 					(void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g, pos));
 		        typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1);
@@ -1872,6 +1921,7 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize, int pos)
         else  /* normally, just destroy the old one and make a new one. */
         {
 			//first check if the contents have changed to see if there is any point of recreating the object
+			//fprintf(stderr,"setto not canvas\n");
 			binbuf_gettext(x->te_binbuf, &c1, &i1);
 			binbuf_gettext(b, &c2, &i2);
 			if (strcmp(c1, c2)) {
diff --git a/src/g_toggle.c b/src/g_toggle.c
index 3db86241a..bf430bf8e 100644
--- a/src/g_toggle.c
+++ b/src/g_toggle.c
@@ -32,7 +32,6 @@ void toggle_draw_select(t_toggle* x, t_glist* glist);
 /* --------------- tgl     gui-toggle ------------------------- */
 
 t_widgetbehavior toggle_widgetbehavior;
-static t_class *toggle_class;
 
 /* widget helper functions */
 
diff --git a/src/g_undo.c b/src/g_undo.c
index 441960e53..b22f018db 100644
--- a/src/g_undo.c
+++ b/src/g_undo.c
@@ -1,12 +1,14 @@
 #include "m_pd.h"
 #include "g_canvas.h"
 #include <stdio.h>
+#include "g_undo.h"
 
 //used for canvas_objtext to differentiate between objects being created by user
 //vs. those (re)created by the undo/redo actions
 int we_are_undoing = 0;
 
 extern const char *canvas_undo_name;
+extern void glob_preset_node_list_seek_hub(void);
 
 t_undo_action *canvas_undo_init(t_canvas *x)
 {
@@ -75,6 +77,10 @@ void canvas_undo_undo(t_canvas *x)
 		char *undo_action = x->u_last->name;
 		char *redo_action = x->u_last->next->name;
 		we_are_undoing = 0;
+		// here we call updating of all unpaired hubs and nodes since their regular call
+		// will fail in case their position needed to be updated by undo/redo first to 
+		// reflect the old one
+		glob_preset_node_list_seek_hub();
 		if (glist_isvisible(x) && glist_istoplevel(x)) {
 			sys_vgui("pdtk_undomenu .x%lx %s %s\n", x, undo_action, redo_action);
 			sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
@@ -108,6 +114,10 @@ void canvas_undo_redo(t_canvas *x)
 		char *undo_action = x->u_last->name;
 		char *redo_action = (x->u_last->next ? x->u_last->next->name : "no");
 		we_are_undoing = 0;
+		// here we call updating of all unpaired hubs and nodes since their regular call
+		// will fail in case their position needed to be updated by undo/redo first to 
+		// reflect the old one
+		glob_preset_node_list_seek_hub();
 		if (glist_isvisible(x) && glist_istoplevel(x)) {
 			sys_vgui("pdtk_undomenu .x%lx %s %s\n", x, undo_action, redo_action);
 			sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
diff --git a/src/g_undo.h b/src/g_undo.h
index 48e62941c..414388e86 100644
--- a/src/g_undo.h
+++ b/src/g_undo.h
@@ -47,7 +47,7 @@ struct _undo_action
 	char *name;					/* name of current action */
 	struct _undo_action *prev;	/* previous undo action */
 	struct _undo_action *next;	/* next undo action */
-} t_undo_action;
+};
 
 #ifndef t_undo_action
 #define t_undo_action struct _undo_action
diff --git a/src/g_vdial.c b/src/g_vdial.c
index f460c8e13..c947a9863 100644
--- a/src/g_vdial.c
+++ b/src/g_vdial.c
@@ -31,7 +31,6 @@ void vradio_draw_select(t_vradio* x, t_glist* glist);
 /* ------------- vdl     gui-vertical radio button ---------------------- */
 
 t_widgetbehavior vradio_widgetbehavior;
-static t_class *vradio_class, *vradio_old_class;
 
 /* widget helper functions */
 
diff --git a/src/g_vslider.c b/src/g_vslider.c
index 8e9265cb1..b4e2c77c1 100644
--- a/src/g_vslider.c
+++ b/src/g_vslider.c
@@ -31,7 +31,6 @@ static void vslider_draw_select(t_vslider* x, t_glist* glist);
 /* ------------ vsl gui-vertical  slider ----------------------- */
 
 t_widgetbehavior vslider_widgetbehavior;
-static t_class *vslider_class;
 
 static double last;
 static int is_last_float = 0;
diff --git a/src/g_vumeter.c b/src/g_vumeter.c
index 8e76135ee..688012c03 100644
--- a/src/g_vumeter.c
+++ b/src/g_vumeter.c
@@ -32,7 +32,6 @@ void vu_check_height(t_vu *x, int h);
 /* ----- vu  gui-peak- & rms- vu-meter-display ---------- */
 
 t_widgetbehavior vu_widgetbehavior;
-static t_class *vu_class;
 
 /* widget helper functions */
 
diff --git a/src/m_conf.c b/src/m_conf.c
index 87b3a0317..195ed2c48 100644
--- a/src/m_conf.c
+++ b/src/m_conf.c
@@ -87,6 +87,7 @@ void conf_init(void)
     x_qlist_setup();
     x_gui_setup();
     x_list_setup();
+	x_preset_setup();
     d_arithmetic_setup();
     d_array_setup();
     d_ctl_setup();
diff --git a/src/m_pd.c b/src/m_pd.c
index 45c08bd90..b24225b61 100644
--- a/src/m_pd.c
+++ b/src/m_pd.c
@@ -25,75 +25,6 @@ t_pd *pd_new(t_class *c)
     if (!c) 
         bug ("pd_new: apparently called before setup routine");
 
-	/* 	here we make sure we do not create objects at the same memory address as before
-		to avoid double-entry bug that is invoked when this happens. why? no idea...
-		tcl/tk definitely sends only one command via socket, yet it is activated multiple
-		times inside c code. perhaps class_addmethod is never cleaned out (although this
-		makes no sense either as we use calloc which should zero everything out, yet even
-		that is not entirely guarranteed)
-
-		we do this by comparing the newly allocated address with preexisting list of
-		canvases that were created in the past.
-
-		if a duplicate is triggered, we deallocate memory and reallocate it assigning 
-		a random additional amount of memory and then resize allocation to the original
-		size
-
-		duplicate: -1 enable check state
-					0 all is ok (or we are not allocating canvas memory)
-					1 found a duplicate
-	*/
-
-	//int random_extra = 0;
-	//int random_offset = 1;
-/*
-	while (canvas_check_duplicate != 0) {
-
-		if (canvas_check_duplicate == -1) {
-			//fprintf(stderr,"alloc %d %d\n", canvas_check_duplicate, (int)c->c_size);
-			x = (t_pd *)t_getbytes(c->c_size);
-		} else if (canvas_check_duplicate == 1) {
-			//random_extra = rand () + random_offset;
-			//fprintf(stderr,"alloc %d %d %d\n", canvas_check_duplicate, (int)c->c_size, (int)c->c_size + random_extra);
-			//x = (t_pd *)t_getbytes(c->c_size + random_extra);
-			//fprintf(stderr,"duplicate\n");
-			y = x;
-			y = (t_pd *)t_resizebytes(x, c->c_size, 1);
-			x = (t_pd *)t_getbytes(c->c_size);
-			t_freebytes(y, sizeof(1));
-		}
-
-		canvas_check_duplicate = 0;
-		if (rm_start) {
-			t_redundant_mem *tmp = rm_start;
-			while (tmp->rm_next) {
-				//fprintf(stderr,"compare %lx %lx\n", (t_int)tmp->rm_canvas, (t_int)x);
-				if ((t_int)tmp->rm_canvas == (t_int)x) {
-					canvas_check_duplicate = 1;
-					break;
-				}
-				tmp = tmp->rm_next;
-			}
-			if (tmp && (t_int)tmp->rm_canvas == (t_int)x)
-				canvas_check_duplicate = 1;
-		}
-
-		//fprintf(stderr,"done alloc %d\n", canvas_check_duplicate);
-		//if (canvas_check_duplicate == 1) {
-		//	//fprintf(stderr,"duplicate\n");
-		//	if (!random_extra)
-		//		t_freebytes(x, sizeof(c->c_size));
-		//	else
-		//		t_freebytes(x, sizeof(c->c_size+random_extra));
-		//}
-		//
-		//if (!canvas_check_duplicate && random_extra) {
-		//	x = (t_pd *)t_resizebytes(x, c->c_size+random_extra, c->c_size);
-		//	break;
-		//}
-	}
-
-    if (!x) x = (t_pd *)t_getbytes(c->c_size);*/
 	x = (t_pd *)t_getbytes(c->c_size);
     *x = c;
     if (c->c_patchable)
diff --git a/src/m_pd.h b/src/m_pd.h
index d245c5c03..ff5158a16 100644
--- a/src/m_pd.h
+++ b/src/m_pd.h
@@ -11,7 +11,7 @@ extern "C" {
 #define PD_MAJOR_VERSION 0
 #define PD_MINOR_VERSION 42
 #define PD_BUGFIX_VERSION 6
-#define PD_TEST_VERSION "extended-l2ork-20120519"
+#define PD_TEST_VERSION "extended-l2ork-20120607"
 #define PDL2ORK
 
 /* old name for "MSW" flag -- we have to take it for the sake of many old
diff --git a/src/x_connective.c b/src/x_connective.c
index aeed72d01..6221997c9 100644
--- a/src/x_connective.c
+++ b/src/x_connective.c
@@ -11,7 +11,7 @@
 extern t_pd *newest;
 
 /* -------------------------- int ------------------------------ */
-static t_class *pdint_class;
+t_class *pdint_class;
 
 typedef struct _pdint
 {
@@ -48,7 +48,7 @@ void pdint_setup(void)
 }
 
 /* -------------------------- float ------------------------------ */
-static t_class *pdfloat_class;
+t_class *pdfloat_class;
 
 typedef struct _pdfloat
 {
@@ -95,7 +95,7 @@ void pdfloat_setup(void)
 }
 
 /* -------------------------- symbol ------------------------------ */
-static t_class *pdsymbol_class;
+t_class *pdsymbol_class;
 
 typedef struct _pdsymbol
 {
-- 
GitLab