From 1c556bac125fb53c443f3274c1c7a5d82abf8441 Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@vt.edu>
Date: Wed, 30 Nov 2011 01:46:16 -0500
Subject: [PATCH] Fixed nasty bug where doubly-embedded pd canvases (not
 abstractions) did not redraw properly (affects all known versions of pd) plus
 additional clean-up and improvements on the gop redrawing/apply logic
 including ability to limit minimum size on gop-enabled objects without
 parents that also do not have hidetext enabled.

---
 src/g_canvas.c | 19 ++++++------
 src/g_editor.c | 45 ++++++++++++++++++++++-------
 src/g_graph.c  | 78 ++++++++++++++++++++++++++++++++++++++++----------
 src/g_rtext.c  |  7 +++--
 src/g_text.c   |  3 ++
 5 files changed, 116 insertions(+), 36 deletions(-)

diff --git a/src/g_canvas.c b/src/g_canvas.c
index 391429ec7..1b7fa0c77 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -1753,24 +1753,27 @@ void canvasgop_draw_move(t_canvas *x, int doit)
 	if (x->gl_havewindow) {
 	    canvas_redraw(x);
 	}
-	if (x->gl_owner && glist_isvisible(x->gl_owner))
-	{
+	//fprintf(stderr,"%d %d\n", (x->gl_owner ? 1:0), glist_isvisible(x->gl_owner));
+
+	if (x->gl_owner && glist_isvisible(x->gl_owner)) {
 		glist_noselect(x);
+		//vmess(&x->gl_owner->gl_obj.te_pd, gensym("menu-open"), "");
 	    gobj_vis(&x->gl_gobj, x->gl_owner, 0);
 	    gobj_vis(&x->gl_gobj, x->gl_owner, 1);
-		canvas_redraw(x->gl_owner);
+		//canvas_redraw(x->gl_owner);
 	}
 	
 	//update scrollbars when GOP potentially exceeds window size
 	t_canvas *canvas=(t_canvas *)glist_getcanvas(x);
 	
 	//if gop is being disabled go one level up
-	if (!x->gl_isgraph && x->gl_owner) {
+	if (!x->gl_isgraph && x->gl_owner && glist_isvisible(x->gl_owner)) {
 		canvas=canvas->gl_owner;
-		canvas_redraw(canvas);
+		//canvas_redraw(canvas);
 	}
 	sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)x);
-	sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)canvas);
+	if (x->gl_owner && glist_isvisible(x->gl_owner))
+		sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (t_int)x->gl_owner);
 }
 
 extern int gfxstub_haveproperties(void *key);
@@ -1805,8 +1808,8 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
 
 				// check if the text is not hidden
 				// if so make minimum width and height based retrieved from getrect
-				if (x->gl_hidetext == 0 && x->gl_owner) {
-					gobj_getrect((t_gobj*)x, x->gl_owner, &x1, &y1, &x2, &y2);
+				if (!x->gl_hidetext) {
+					gobj_getrect((t_gobj*)x, (x->gl_owner ? x->gl_owner : x), &x1, &y1, &x2, &y2);
 					if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
 					if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
 				}
diff --git a/src/g_editor.c b/src/g_editor.c
index 201827101..c3f48c596 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -1778,16 +1778,8 @@ void canvas_properties(t_glist *x)
 static void canvas_donecanvasdialog(t_glist *x,
     t_symbol *s, int argc, t_atom *argv)
 {
-	/* parent windows are treated differently than applies to individual objects */
-	if (glist_getcanvas(x) != x && !canvas_isabstraction(x)) {
-		canvas_apply_setundo(glist_getcanvas(x), (t_gobj *)x);
-	}
-	else {
-		canvas_canvas_setundo(x);
-		//fprintf(stderr,"canvas_apply_undo\n");
-	}
-
-    t_float xperpix, yperpix, x1, y1, x2, y2, xpix, ypix, xmargin, ymargin; 
+    t_float xperpix, yperpix, x1, y1, x2, y2, xpix, ypix, xmargin, ymargin;
+	int rx1=0, ry1=0, rx2=0, ry2=0; //for getrect
     int graphme, redraw = 0;
 
     xperpix = atom_getfloatarg(0, argc, argv);
@@ -1803,6 +1795,18 @@ static void canvas_donecanvasdialog(t_glist *x,
     xmargin = atom_getfloatarg(9, argc, argv);
     ymargin = atom_getfloatarg(10, argc, argv);
 
+	/* parent windows are treated differently than applies to individual objects */
+	if (glist_getcanvas(x) != x && !canvas_isabstraction(x)) {
+		canvas_apply_setundo(glist_getcanvas(x), (t_gobj *)x);
+	}
+	else /*if (x1!=x->gl_x1 || x2!=x->gl_x2 || y1!=x->gl_y1 || y2!=x->gl_y2 ||
+			graphme!=(x->gl_isgraph+2*x->gl_hidetext) || x->gl_pixwidth!=xpix ||
+			x->gl_pixheight!=ypix || x->gl_xmargin!=xmargin || x->gl_ymargin!=ymargin) {*/
+	{	
+		canvas_canvas_setundo(x);
+		//fprintf(stderr,"canvas_apply_undo\n");
+	}
+
     x->gl_pixwidth = xpix;
     x->gl_pixheight = ypix;
     x->gl_xmargin = xmargin;
@@ -1848,9 +1852,27 @@ static void canvas_donecanvasdialog(t_glist *x,
             x->gl_y2 = x->gl_y1 + yperpix;
         }
     }
+
         /* LATER avoid doing 2 redraws here (possibly one inside setgraph) */
     canvas_setgraph(x, graphme, 0);
     canvas_dirty(x, 1);
+
+	// make sure gop is never smaller than its text
+	// if one wants smaller gop window, make sure to disable text
+	if (x->gl_isgraph && !x->gl_hidetext) {
+		//fprintf(stderr, "check size\n");
+		gobj_getrect((t_gobj*)x, (x->gl_owner ? x->gl_owner : x), &rx1, &ry1, &rx2, &ry2);
+		//fprintf(stderr,"%d %d %d %d\n", rx1, rx2, ry1, ry2);
+		if (rx2-rx1 > x->gl_pixwidth) {
+			x->gl_pixwidth = rx2-rx1;
+			//fprintf(stderr,"change width\n");
+		}
+		if (ry2-ry1 > x->gl_pixheight) {
+			x->gl_pixheight = ry2-ry1;
+			//fprintf(stderr,"change height\n");
+		}
+	}
+
     if (x->gl_havewindow) {
 		//fprintf(stderr,"donecanvasdialog canvas_redraw\n");
         canvas_redraw(x);
@@ -4063,7 +4085,8 @@ void canvas_editmode(t_canvas *x, t_floatarg fyesplease)
 	}
     x->gl_edit = !x->gl_edit;
     if (x->gl_edit && glist_isvisible(x) && glist_istoplevel(x)){
-		if (x->gl_goprect)	canvas_draw_gop_resize_hooks(x);								// dpsaha@vt.edu add the resize blobs on GOP
+		//dpsaha@vt.edu add the resize blobs on GOP
+		if (x->gl_goprect)	canvas_draw_gop_resize_hooks(x);
 		canvas_setcursor(x, CURSOR_EDITMODE_NOTHING);
 	}
     else
diff --git a/src/g_graph.c b/src/g_graph.c
index f48b0f114..23fccfd76 100644
--- a/src/g_graph.c
+++ b/src/g_graph.c
@@ -211,9 +211,12 @@ void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
 
 t_canvas *glist_getcanvas(t_glist *x)
 {
+	//fprintf(stderr,"gobj_shouldvis\n");
     while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph &&
-        gobj_shouldvis(&x->gl_gobj, x->gl_owner))
+        gobj_shouldvis(&x->gl_gobj, x->gl_owner)) {
             x = x->gl_owner;
+			//fprintf(stderr,"+\n");
+	}
     return((t_canvas *)x);
 }
 
@@ -734,7 +737,8 @@ int garray_getname(t_garray *x, t_symbol **namep);
 static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
 {
     t_glist *x = (t_glist *)gr;
-    char tag[50];
+	//fprintf(stderr,"graph_vis gr=.x%lx parent_glist=.x%lx glist_getcanvas(x->gl_owner)=.x%lx vis=%d\n", (t_int)gr, (t_int)parent_glist, (t_int)glist_getcanvas(x->gl_owner), vis);  
+	char tag[50];
     t_gobj *g;
     int x1, y1, x2, y2;
         /* ordinary subpatches: just act like a text object */
@@ -744,9 +748,20 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
         return;
     }
 
-    if (vis && canvas_showtext(x))
+	// weird exception
+	//int exception = 0;
+	//t_canvas* tgt = glist_getcanvas(x->gl_owner);
+	//if (parent_glist->gl_owner && !parent_glist->gl_mapped &&
+	//		parent_glist->gl_owner->gl_mapped) {
+	//	tgt = parent_glist;
+	//	exception = 1;
+	//}
+	//fprintf(stderr,"tgt=.x%lx %d\n", (t_int)tgt, exception);
+
+    if (vis && canvas_showtext(x) && gobj_shouldvis(gr, parent_glist))
         rtext_draw(glist_findrtext(parent_glist, &x->gl_obj));
     graph_getrect(gr, parent_glist, &x1, &y1, &x2, &y2);
+	//fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2);
     if (!vis)
         rtext_erase(glist_findrtext(parent_glist, &x->gl_obj));
 
@@ -761,18 +776,20 @@ static void graph_vis(t_gobj *gr, t_glist *parent_glist, int vis)
         just show the bounding rectangle */
     if (x->gl_havewindow)
     {
-        if (vis)
-        {
-            sys_vgui(".x%lx.c create polygon\
- %d %d %d %d %d %d %d %d %d %d -tags %s -fill #c0c0c0\n",
-                glist_getcanvas(x->gl_owner),
-                x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
-        }
-        else
-        {
-            sys_vgui(".x%lx.c delete %s\n",
-                glist_getcanvas(x->gl_owner), tag);
-        }
+	    if (vis && gobj_shouldvis(gr, parent_glist))
+	    {
+	        sys_vgui("catch {.x%lx.c create polygon\
+ %d %d %d %d %d %d %d %d %d %d -tags %s -fill #c0c0c0}\n",
+	            glist_getcanvas(x->gl_owner),
+				//parent_glist,
+	            x1, y1, x1, y2, x2, y2, x2, y1, x1, y1, tag);
+	    }
+	    else if (gobj_shouldvis(gr, parent_glist))
+	    {
+	        sys_vgui("catch {.x%lx.c delete %s}\n",
+	            glist_getcanvas(x->gl_owner), tag);
+				//parent_glist, tag);
+	    }
         return;
     }
         /* otherwise draw (or erase) us as a graph inside another glist. */
@@ -938,6 +955,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
 {
 	//fprintf(stderr,"graph_getrect\n");
     int x1 = 0x7fffffff, y1 = 0x7fffffff, x2 = -0x7fffffff, y2 = -0x7fffffff;
+    int tx1 = 0x7fffffff, ty1 = 0x7fffffff, tx2 = -0x7fffffff, ty2 = -0x7fffffff;
     t_glist *x = (t_glist *)z;
     if (x->gl_isgraph)
     {
@@ -947,6 +965,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
         int x21, y21, x22, y22;
 
         graph_graphrect(z, glist, &x1, &y1, &x2, &y2);
+		//fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2);
 
         if (canvas_showtext(x))
         {
@@ -955,6 +974,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
                 x2 = x22;
             if (y22 > y2) 
                 y2 = y22;
+			//fprintf(stderr,"canvas_showtext %d %d %d %d\n", x1, y1, x2, y2);
         }
         if (!x->gl_goprect)
         {
@@ -979,6 +999,34 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
             }
             x->gl_havewindow = hadwindow;
         }
+
+		//fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2);
+
+		// check if the text is not hidden and if so use that as the limit of the gop's size
+		if (!x->gl_hidetext) {
+			text_widgetbehavior.w_getrectfn(z, glist, &x21, &y21, &x22, &y22);
+		    if (x22 > x2) 
+		        x2 = x22;
+		    if (y22 > y2) 
+		        y2 = y22;
+			// WARNING: ugly hack trying to replicate rtext_senditup if we have no parent
+			// later consider instead of hardwiring values pulling these more intelligently from
+			// a common place
+			int fw = sys_fontwidth(x->gl_font);
+			int fh = sys_fontheight(x->gl_font);
+			//fprintf(stderr," fw=%d /=%d mod=%d \n", fw, fw/60, fw%60);
+			//fprintf(stderr,"name=%s\n",x->gl_name->s_name);
+			int tcols = strlen(x->gl_name->s_name) - 3;
+			int th = fh + fh * (tcols/60) + 4;
+			if (tcols > 60) tcols = 60;
+			int tw = fw * tcols + 4;
+			if (tw + x1 > x2)
+				x2 = tw + x1;
+			if (th + y1 > y2)
+				y2 = th + y1;
+			//fprintf(stderr,"graph_getrect->text_getrect %d=%d %d=%d\n", fw, x2, fh, y2);
+		}
+
 		/* fix visibility of edge items for garrays */
 		int has_garray = 0;
         for (g = x->gl_list; g; g = g->g_next) {
diff --git a/src/g_rtext.c b/src/g_rtext.c
index a8efb11d2..82bdce63a 100644
--- a/src/g_rtext.c
+++ b/src/g_rtext.c
@@ -157,6 +157,7 @@ extern int sys_oldtclversion;
 static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
     int *indexp)
 {
+	//fprintf(stderr,"rtext_senditup\n");
 	if (x) {
 		t_float dispx, dispy;
 		char smallbuf[200], *tempbuf;
@@ -244,13 +245,15 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
 		pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
 		pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
 
-		if (action == SEND_FIRST)
+		if (action == SEND_FIRST) {
+			//fprintf(stderr,"canvas=.x%lx %s\n", (t_int)canvas, tempbuf);
 		    sys_vgui("pdtk_text_new .x%lx.c %s %f %f {%.*s} %d %s\n",
 		        canvas, x->x_tag,
 		        dispx + LMARGIN, dispy + TMARGIN,
 		        outchars, tempbuf, sys_hostfontsize(font),
 		        (glist_isselected(x->x_glist,
 		            &x->x_glist->gl_gobj)? "$select_color" : "$text_color"));
+		}
 		else if (action == SEND_UPDATE)
 		{
 			/*fprintf(stderr, "SEND_UPDATE canvas_class=%d isgraph=%d goprect=%d\n",
@@ -355,7 +358,7 @@ void rtext_retext(t_rtext *x)
 /* find the rtext that goes with a text item */
 t_rtext *glist_findrtext(t_glist *gl, t_text *who)
 {
-    t_rtext *x;
+    t_rtext *x=NULL;
     if (!gl->gl_editor)
         canvas_create_editor(gl);
 	if (gl->gl_editor->e_rtext)
diff --git a/src/g_text.c b/src/g_text.c
index b04daff19..649c58fd8 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -1041,6 +1041,7 @@ static void gatom_properties(t_gobj *z, t_glist *owner)
 static void text_getrect(t_gobj *z, t_glist *glist,
     int *xp1, int *yp1, int *xp2, int *yp2)
 {
+	//fprintf(stderr,"text_getrect %d %d\n", (glist->gl_editor ? 1 : 0), (glist->gl_editor->e_rtext ? 1:0));
     t_text *x = (t_text *)z;
     int width, height, iscomment = (x->te_type == T_TEXT);
     t_float x1, y1, x2, y2;
@@ -1075,6 +1076,8 @@ static void text_getrect(t_gobj *z, t_glist *glist,
         t_rtext *y = glist_findrtext(glist, x);
         width = rtext_width(y);
 
+		//fprintf(stderr,"width=%d\n", width);
+
 		/*  now find if we have more inlets or outlets than
 			what can comfortably fit and adjust accordingly
 			NB: textless GOPs are unaffected and are treated
-- 
GitLab