From 1b41296a78d8da2758088c9f808a5100dd5c1bea Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@monsoon-hp.(none)>
Date: Thu, 1 Mar 2012 23:18:51 -0500
Subject: [PATCH] fixed automatic resizing of the gop when changing font sizes,
 complete overhaul of the tooltip engine. TODO: add proper nlet tags to iemgui
 objects...

---
 src/g_canvas.c |  17 +---
 src/g_editor.c |  40 +++++++-
 src/g_graph.c  |  59 +++++++-----
 src/g_text.c   |  12 +--
 src/pd.tk      | 247 ++++++++++++++++++++++++++++++++++---------------
 5 files changed, 253 insertions(+), 122 deletions(-)

diff --git a/src/g_canvas.c b/src/g_canvas.c
index 699e40032..5a5970812 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -1783,6 +1783,8 @@ void canvasgop_draw_move(t_canvas *x, int doit)
 
 extern int gfxstub_haveproperties(void *key);
 extern void canvas_canvas_setundo(t_canvas *x);
+extern void graph_checkgop_rect(t_gobj *z, t_glist *glist,
+    int *xp1, int *yp1, int *xp2, int *yp2);
 
 void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_floatarg yyy)
 {
@@ -1821,22 +1823,9 @@ void canvasgop__clickhook(t_scalehandle *sh, t_floatarg f, t_floatarg xxx, t_flo
 						if (x2-x1 > x->gl_pixwidth) x->gl_pixwidth = x2-x1;
 						if (y2-y1 > x->gl_pixheight) x->gl_pixheight = y2-y1;
 					} else {
-						// 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 THIS SHOULD BE LATER MERGED WITH GRPAH_GETRECT
-						int fw = sys_fontwidth(x->gl_font);
-						int fh = sys_fontheight(x->gl_font);
-						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;
+						graph_checkgop_rect((t_gobj*)x, 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;
-						//fprintf(stderr,"graph_getrect->text_getrect %d=%d %d=%d\n", fw, x2, fh, y2);
 					}
 				}
 
diff --git a/src/g_editor.c b/src/g_editor.c
index 31c6e04fc..3ca75e963 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -48,6 +48,7 @@ static int inlet_issignal = 0;
 static int last_inlet_filter = 0;
 static int last_outlet_filter = 0;
 static int copyfromexternalbuffer = 0;
+static int tooltips = 0;
 static int screenx1;            /* screen coordinates when doing copyfromexternalbuffer */
 static int screeny1;
 static int screenx2;
@@ -2728,6 +2729,7 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
 					//sys_vgui("pdtk_update_xy_tooltip .x%lx %d %d\n", x, (int)xpos, (int)ypos);
 					//sys_vgui("pdtk_toggle_xy_tooltip .x%lx %d\n", x, 1);
                     x->gl_editor->e_onmotion = MA_MOVE;
+					sys_vgui("pdtk_tip .x%x.c 0 0\n;", x);
                 }
             }
     	    else
@@ -2839,6 +2841,14 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
             return;
         }
     }
+    if (canvas_cnct_inlet_tag[0] != 0)
+    {
+		sys_vgui(".x%x.c itemconfigure %s -outline %s -fill %s -width 1\n",
+       			x, canvas_cnct_inlet_tag,
+				(last_inlet_filter ? "black" : (outlet_issignal ? "$signal_cord" : "$msg_cord")),
+				(inlet_issignal ? "$signal_nlet" : "$msg_nlet"));
+        canvas_cnct_inlet_tag[0] = 0;                  
+    }
     // jsarlo
     if (canvas_cnct_outlet_tag[0] != 0)
     {
@@ -3036,7 +3046,7 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
                              x,
                              canvas_cnct_inlet_tag);
 					inlet_issignal = obj_issignalinlet(ob2, closest2);
-					//sys_vgui("pdtk_canvas_enteritem .x%x.c %d %d %s 0\n;", x, xpos, ypos, canvas_cnct_outlet_tag);
+					sys_vgui("pdtk_canvas_enteritem .x%x.c %d %d %s -1\n;", x, xpos, ypos, canvas_cnct_outlet_tag);
                 }
                 canvas_setcursor(x, CURSOR_EDITMODE_CONNECT);
             }
@@ -3050,7 +3060,9 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
         sys_vgui(".x%x.c itemconfigure %s -outline %s -fill %s -width 1\n",
                	x, canvas_cnct_inlet_tag,
 				(last_inlet_filter ? "black" : (outlet_issignal ? "$signal_cord" : "$msg_cord")),
-				(inlet_issignal ? "$signal_nlet" : "$msg_nlet"));               
+				(inlet_issignal ? "$signal_nlet" : "$msg_nlet"));
+		sys_vgui("pdtk_canvas_leaveitem .x%x.c %s\n;", x, canvas_cnct_outlet_tag);
+		canvas_cnct_inlet_tag[0] = 0;              
     }
 	if(x->gl_magic_glass) {
     	magicGlass_unbind(x->gl_magic_glass);
@@ -3455,7 +3467,7 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
         canvas_displaceselection(x, 
             xpos - x->gl_editor->e_xwas, ypos - x->gl_editor->e_ywas);
         x->gl_editor->e_xwas = xpos;
-        x->gl_editor->e_ywas = ypos;    
+        x->gl_editor->e_ywas = ypos;   
     }
     else if (x->gl_editor->e_onmotion == MA_REGION)
         canvas_doregion(x, xpos, ypos, 0);
@@ -3496,7 +3508,7 @@ void canvas_startmotion(t_canvas *x)
     if (xval == 0 && yval == 0) return;
     x->gl_editor->e_onmotion = MA_MOVE;
     x->gl_editor->e_xwas = xval;
-    x->gl_editor->e_ywas = yval; 
+    x->gl_editor->e_ywas = yval;
 }
 
 /* ----------------------------- window stuff ----------------------- */
@@ -4711,6 +4723,22 @@ void canvas_magicglass(t_canvas *x, t_floatarg fyesplease)
 }
 // end jsarlo
 
+void canvas_tooltips(t_canvas *x, t_floatarg fyesplease)
+{
+    int yesplease = fyesplease;
+    if (yesplease && tooltips)
+    	return;
+    if (!tooltips) {
+		canvas_editmode(x, 1.);
+        tooltips = 1;
+    }
+    else {
+        tooltips = 0;
+    }
+	sys_vgui("pdtk_canvas_tooltips .x%lx %d\n",
+        x, tooltips);
+}
+
     /* called by canvas_font below */
 static void canvas_dofont(t_canvas *x, t_floatarg font, t_floatarg xresize,
     t_floatarg yresize)
@@ -4779,6 +4807,8 @@ static void glist_setlastxy(t_glist *gl, int xval, int yval)
 static void canvas_enterobj(t_canvas *x, t_symbol *item, t_floatarg xpos,
     t_floatarg ypos, t_floatarg xletno)
 {
+	if (x->gl_editor->e_onmotion == MA_MOVE) { return; }
+	//fprintf(stderr,"canvas_enterobj\n");
     t_symbol *name = 0, *helpname, *dir;
     int yoffset = 0, xoffset = 0;
     if (item == gensym("inlet"))
@@ -4887,6 +4917,8 @@ void g_editor_setup(void)
     class_addmethod(canvas_class, (t_method)canvas_magicglass,
         gensym("magicglass"), A_DEFFLOAT, A_NULL);
     //end jsarlo
+    class_addmethod(canvas_class, (t_method)canvas_tooltips,
+        gensym("tooltips"), A_DEFFLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_print,
         gensym("print"), A_SYMBOL, A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_menufont,
diff --git a/src/g_graph.c b/src/g_graph.c
index ec0a605ee..fd11c0a3a 100644
--- a/src/g_graph.c
+++ b/src/g_graph.c
@@ -22,6 +22,8 @@ static void graph_graphrect(t_gobj *z, t_glist *glist,
     int *xp1, int *yp1, int *xp2, int *yp2);
 static void graph_getrect(t_gobj *z, t_glist *glist,
     int *xp1, int *yp1, int *xp2, int *yp2);
+void graph_checkgop_rect(t_gobj *z, t_glist *glist,
+    int *xp1, int *yp1, int *xp2, int *yp2);
 
 /* -------------------- maintaining the list -------------------- */
 
@@ -716,6 +718,14 @@ void glist_redraw(t_glist *x)
             if (x->gl_goprect)
             {
                 //post("draw it");
+				/* update gop rect size on toplevel in case font has
+				changed and we are showing text */
+				if (!x->gl_hidetext) {
+					int x1, y1, x2, y2;
+					graph_getrect((t_gobj *)x, 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;
+				}
                 canvas_drawredrect(x, 1);
             }
         }
@@ -951,6 +961,33 @@ static void graph_graphrect(t_gobj *z, t_glist *glist,
     *yp2 = y2;
 }
 
+	/* check if the gop size needs to change due to gop's text
+	in case hidetext is not enabled */
+void graph_checkgop_rect(t_gobj *z, t_glist *glist,
+    int *xp1, int *yp1, int *xp2, int *yp2) {
+
+	//fprintf(stderr,"graph_checkgop_rect\n");
+	t_glist *x = (t_glist *)z;
+	int x21, y21, x22, y22;
+	text_widgetbehavior.w_getrectfn(z, glist, &x21, &y21, &x22, &y22);
+    if (x22 > *xp2)
+        *xp2 = x22;
+    if (y22 > *yp2) 
+        *yp2 = y22;
+	int fw = sys_fontwidth(x->gl_font);
+	int fh = sys_fontheight(x->gl_font);
+	// WARNING: ugly hack trying to replicate rtext_senditup if we have no parent
+	// later consider fixing hardwired values
+	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 + *xp1 > *xp2)
+		*xp2 = tw + *xp1;
+	if (th + *yp1 > *yp2)
+		*yp2 = th + *yp1;
+}
+
     /* get the rectangle, enlarged to contain all the "contents" --
     meaning their formal bounds rectangles. */
 static void graph_getrect(t_gobj *z, t_glist *glist,
@@ -1007,27 +1044,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
 
 		// 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);
+			graph_checkgop_rect(z, glist, &x1, &y1, &x2, &y2);
 		}
 
 		/* fix visibility of edge items for garrays */
diff --git a/src/g_text.c b/src/g_text.c
index e3d8181fe..c413fda09 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -1637,7 +1637,7 @@ void text_drawborder(t_text *x, t_glist *glist,
         if (firsttime)
 		{
             sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d \
-                      -dash %s -outline %s -fill %s -tags %sR\n", 
+                      -dash %s -outline %s -fill %s -tags {%sR text}\n", 
                 glist_getcanvas(glist),
                      x1, y1,  x2, y1,  x2, y2,  x1, y2,  x1, y1,  
                      pattern, outline, fill, tag);
@@ -1661,7 +1661,7 @@ void text_drawborder(t_text *x, t_glist *glist,
 		{
             sys_vgui(".x%lx.c create polygon \
                      %d %d %d %d %d %d %d %d %d %d %d %d %d %d \
-                     -outline $box_outline -fill $msg_box_fill -tags %sR\n",
+                     -outline $box_outline -fill $msg_box_fill -tags {%sR text}\n",
                 glist_getcanvas(glist),
                      x1, y1,  x2+msg_draw_const, y1,  x2, y1+msg_draw_const,  
                      x2, y2-msg_draw_const,  x2+msg_draw_const, y2,  
@@ -1683,7 +1683,7 @@ void text_drawborder(t_text *x, t_glist *glist,
         if (firsttime)
 		{
             sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d %d %d \
-                     -outline $box_outline -fill $atom_box_fill -tags %sR\n",
+                     -outline $box_outline -fill $atom_box_fill -tags {%sR text}\n",
                 glist_getcanvas(glist),
                      x1, y1,  x2-atom_draw_const, y1,  x2, y1+atom_draw_const,  
                      x2, y2,  x1, y2,  x1, y1, 
@@ -1736,7 +1736,7 @@ void text_drawborder_withtag(t_text *x, t_glist *glist,
         if (firsttime)
 		{
             sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d \
-                      -dash %s -outline %s -fill %s -tags %sR\n", 
+                      -dash %s -outline %s -fill %s -tags {%sR text}\n", 
                 glist_getcanvas(glist),
                      x1, y1,  x2, y1,  x2, y2,  x1, y2,  x1, y1,  
                      pattern, outline, fill, tag);
@@ -1749,7 +1749,7 @@ void text_drawborder_withtag(t_text *x, t_glist *glist,
         if (firsttime)
             sys_vgui(".x%lx.c create polygon \
                      %d %d %d %d %d %d %d %d %d %d %d %d %d %d \
-                     -outline $box_outline -fill $msg_box_fill -tags %sR\n",
+                     -outline $box_outline -fill $msg_box_fill -tags {%sR text}\n",
                 glist_getcanvas(glist),
                      x1, y1,  x2+msg_draw_const, y1,  x2, y1+msg_draw_const,  
                      x2, y2-msg_draw_const,  x2+msg_draw_const, y2,  
@@ -1761,7 +1761,7 @@ void text_drawborder_withtag(t_text *x, t_glist *glist,
         atom_draw_const = ((y2-y1)/3);
         if (firsttime)
             sys_vgui(".x%lx.c create polygon %d %d %d %d %d %d %d %d %d %d %d %d \
-                     -outline $box_outline -fill $atom_box_fill -tags %sR\n",
+                     -outline $box_outline -fill $atom_box_fill -tags {%sR text}\n",
                 glist_getcanvas(glist),
                      x1, y1,  x2-atom_draw_const, y1,  x2, y1+atom_draw_const,  
                      x2, y2,  x1, y2,  x1, y1, 
diff --git a/src/pd.tk b/src/pd.tk
index f6a8daeac..68b9627d7 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -341,6 +341,7 @@ variable afterid 0
 variable duplicate_tags -1
 variable current_window 0
 variable nlet_color 0
+variable autotips 0
 
 # x:y location tooltip during dragging
 set tooltip [toplevel .tooltip -bd 1 -bg black]
@@ -1401,9 +1402,9 @@ if {$pd_nt == 2} { # no key command for Mac OS X
 .mbar.edit add separator
 
 .mbar.edit add command -label "Toggle console" \
-	-accelerator [accel_munge "Shift+Ctrl+r"] -command menu_toggle_console
+	-accelerator [accel_munge "Ctrl+R"] -command menu_toggle_console
 .mbar.edit add command -label "Clear console" \
-    -accelerator [accel_munge "Shift+Ctrl+l"] -command menu_clear_console
+    -accelerator [accel_munge "Ctrl+L"] -command menu_clear_console
 .mbar.edit add separator
 # this should apply to .printout.frame.text
 .mbar.edit add command -label {Find...} -accelerator [accel_munge "Ctrl+f"] \
@@ -1413,7 +1414,10 @@ if {$pd_nt == 2} { # no key command for Mac OS X
     -state disabled
 .mbar.edit add command -label {Find last error}
 .mbar.edit add separator
-.mbar.edit add checkbutton -label [_ "Autotips"] -variable ::autotips_button
+.mbar.edit add checkbutton -label "Autotips" \
+        -indicatoron false -selectcolor black \
+        -accelerator [accel_munge "Ctrl+E"] \
+    	-state disabled
 .mbar.edit add command -label {Edit mode} -accelerator [accel_munge "Ctrl+e"] \
     -state disabled
 
@@ -1703,6 +1707,10 @@ proc menu_editmode {name} {
     pd [concat $name editmode 0 \;]
 }
 
+proc menu_tooltips {name} {
+	pd [concat $name tooltips 0 \;]
+}
+
 proc menu_object {name accel} {
 	pd [concat $name dirty 1 \;]
     pd [concat $name obj $accel \;]
@@ -2236,11 +2244,11 @@ proc pdtk_canvas_new {name width height geometry editable} {
 ## end jsarlo
 
     $name.m.edit add command -label "Toggle console" \
-        -accelerator [accel_munge "Shift+Ctrl+r"] \
+        -accelerator [accel_munge "Ctrl+R"] \
         -command [concat .controls.switches.console invoke]
 
     $name.m.edit add command -label "Clear console" \
-        -accelerator [accel_munge "Shift+Ctrl+l"] \
+        -accelerator [accel_munge "Ctrl+L"] \
         -command [concat menu_clear_console]
 
     $name.m.edit add separator
@@ -2261,12 +2269,15 @@ proc pdtk_canvas_new {name width height geometry editable} {
     # instead of "red = #BC3C60" we take "grey85", so there is no difference,
     # if widget is selected or not.
 
-	$name.m.edit add checkbutton -label [_ "Autotips"] -variable ::autotips_button
+    $name.m.edit add checkbutton -label "Autotips" \
+        -indicatoron false -selectcolor black \
+        -command [concat menu_tooltips $name] \
+        -accelerator [accel_munge "Ctrl+E"]
 
     $name.m.edit add checkbutton -label "Edit mode" \
         -indicatoron false -selectcolor black \
         -command [concat menu_editmode $name] \
-        -accelerator [accel_munge "Ctrl+e"] -variable ::editmode($name)
+        -accelerator [accel_munge "Ctrl+e"]
 
 	if { $editable == 1 } {
     	$name.m.edit entryconfigure "Edit mode" -background "#7dd37d"
@@ -3226,6 +3237,7 @@ proc pdtk_canvas_ctrlkey {name key shift} {
         if {$key == "q" || $key == "Q"} {menu_really_quit}
         if {$key == "l" || $key == "L"} {menu_clear_console}
         if {$key == "r" || $key == "R"} {menu_toggle_console}
+		if {$key == "E"} {menu_tooltips $topname}
 		if {!$ignore} {
 	        if {$key == "w" || $key == "W"} {menu_really_close $topname}
 	        if {$key == "s" || $key == "S"} {menu_saveas $topname}
@@ -3266,7 +3278,7 @@ proc pdtk_canvas_ctrlkey {name key shift} {
 		if {!$ignore} {
         	if {$key == "w" || $key == "W"} {menu_close $topname}
 	        if {$key == "s" || $key == "S"} {menu_save $topname}
-        	if {$key == "e" || $key == "E"} {menu_editmode $topname}
+        	if {$key == "e"} {menu_editmode $topname}
         	#if {$key == "d" || $key == "D"} {menu_duplicate $topname}
         	if {$key == "d" || $key == "D"} {pdtk_canvas_edit_menu_actions $topname Duplicate}
 			if {$key == "r" || $key == "R"} {menu_magicglass $topname}
@@ -5140,6 +5152,20 @@ proc pdtk_canvas_editval {name value} {
 		}
 	#}                                             
 }
+
+proc pdtk_canvas_tooltips {name value} {
+	variable autotips
+	#global colors
+	#if {[winfo exists $name]} {
+		if { $value } {
+		    $name.m.edit entryconfigure "Autotips" -indicatoron false -background "#7dd37d"
+			set autotips 1
+		} else {                          
+		    $name.m.edit entryconfigure "Autotips" -indicatoron false -background {}
+			set autotips 0
+		}
+	#}                                             
+}
 #####################iemlib#######################
 
 proc pdtk_canvas_magicglassval {name value} {
@@ -5213,7 +5239,8 @@ proc pdtk_text_new {canvasname myname x y text font color} {
     }
 
     $canvasname create text $x $y -font $typeface \
-        -tags $myname -text $text -fill $color -anchor nw 
+        -tags $myname -text $text -fill $color -anchor nw
+	$canvasname addtag text withtag $myname
 	#$canvasname bind $myname <Home> [concat $canvasname icursor $myname 0]
 	#$canvasname bind $myname <End> [concat $canvasname icursor $myname end]
 	if {$pd_nt == 2} { # emacs bindings for Mac OS X
@@ -7084,8 +7111,9 @@ if { [info tclversion] >= 8.5 && $pd_nt == 0 } {
 }
 
  
-proc pdtk_canvas_enteritem_gettags {tkcanvas x y item} {
+proc pdtk_canvas_enteritem_gettags {tkcanvas x y item enterid} {
 	variable nlet_color
+	variable select_color
     if {[winfo exists $tkcanvas]} {
         set mytoplevel [winfo toplevel $tkcanvas]
         set id [$tkcanvas find withtag current]
@@ -7102,7 +7130,11 @@ proc pdtk_canvas_enteritem_gettags {tkcanvas x y item} {
 			}
 		}
 
-		set nlet_color [$tkcanvas itemcget [lindex $tags 0] -outline]
+		if { $object ne "text" } {
+			set nlet_color [$tkcanvas itemcget [lindex $tags 0] -outline]
+		} else {
+			set nlet_color $select_color
+		}
 
         pd [concat $mytoplevel enter $object \
             [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $xletno \;]
@@ -7113,20 +7145,21 @@ proc pdtk_canvas_enteritem {tkcanvas x y item enterid} {
     variable afterid
     variable duplicate_tags
     variable current_window
-    #if {$::autotips_button == 0} {return}
-    if {$item != $duplicate_tags} {
+	variable autotips
+    if {$autotips == 0} {return}
+    if {$enterid != $duplicate_tags || $enterid == -1} {
 	    #if {$item eq "inlet" ||
 	    #    $item eq "outlet"} {
         #        $tkcanvas itemconfigure $item -activewidth 5 
 	    #}
 
-	    set duplicate_tags $item
+	    set duplicate_tags $enterid
 		if {$current_window eq $tkcanvas} {
 			after cancel $afterid
 		}
 		set current_window $tkcanvas
 		set afterid [after 250 pdtk_canvas_enteritem_gettags \
-			$tkcanvas $x $y $item]
+			$tkcanvas $x $y $item $enterid]
 	}
 }
 
@@ -7135,7 +7168,8 @@ proc pdtk_canvas_leaveitem {w item} {
     variable afterid
     variable current_window
 	variable duplicate_tags
-    #if {$::autotips_button == 0} {return}
+	variable autotips
+    if {$autotips == 0} {return}
     after cancel $afterid
 	set afterid 0
     if {[lsearch -exact [$w gettags $w.tipwindow] "sticky"] == -1} {
@@ -7145,6 +7179,7 @@ proc pdtk_canvas_leaveitem {w item} {
         #}
 		if {[winfo exists $w.tiplabel]} {
             set afterid [after 50 "pdtk_tip $w 0 0"]
+			#pdtk_tip $w 0 0
             set current_window $w
 		}
     }
@@ -7154,51 +7189,109 @@ proc pdtk_canvas_leaveitem {w item} {
 proc pdtk_tip {w fromc show args} {
 	variable select_color
 	variable nlet_color
-    set exists [winfo exists $w.tiplabel]
+	set exists [winfo exists $w.tiplabel]
     if {$show == 0} {
         catch {destroy $w.tiplabel}
         catch {$w delete $w.tipwindow}
+		catch {$w delete tiparrow}
     } else {
-	if {$exists} {
-	    $w.tiplabel configure -text [join $args]
-	    $w dtag $w.tipwindow "sticky"
-	    if {$fromc == 1} {
-		$w addtag "sticky" withtag $w.tipwindow
-	    }  
-	} else {
-			if { $nlet_color ne $select_color } {
-				set fg "#ffffff"
-			} else {
-				set fg "#000000"
-			}
+		if { $nlet_color == 0 } { set nlet_color $select_color }
+		if { $nlet_color ne $select_color } {
+			set fg "#ffffff"
+		} else {
+			set fg "#000000"
+		}
+		if {$exists} {    	
+			$w.tiplabel configure -text [join $args] -fg $fg -bg $nlet_color
+        	$w itemconfigure tiparrow -fill $nlet_color
+	    	$w dtag $w.tipwindow "sticky"
+	    	if {$fromc == 1} {
+				$w addtag "sticky" withtag $w.tipwindow
+	    	}  
+		} else {
             label $w.tiplabel -text [join $args] -bd 1 \
 	        -wraplength [winfo width $w] -bg $nlet_color -fg $fg -bd 1 \
 	        -padx 2 -pady 2 -relief flat
-	} 
-        set yreal [expr [$w canvasy 0] * -1 + \
-	    [winfo pointery $w]-[winfo rooty $w]]
-        set yoffset 0
-        if {$yreal < [expr [winfo height $w] - \
-	    [winfo reqheight $w.tiplabel]] - 5} {
-	    set yoffset [winfo height $w]
-            set anchor "sw"
-        } else {
+		}
+        set xreal [expr [$w canvasx 0] * -1 + [winfo pointerx $w]-[winfo rootx $w]]
+        set yreal [expr [$w canvasy 0] * -1 + [winfo pointery $w]-[winfo rooty $w]]
+
+		# first figure out default behavior for above/below
+		if { [string match "\{Inlet*" $args] } {
+        	set yoffset 0
 	    	set anchor "nw"
+			set top_bottom [expr -30 - [winfo reqheight $w.tiplabel]]
+			set yreal_offset -5
+        } else {
+			set yoffset [winfo height $w]
+        	set anchor "sw"
+			set top_bottom [expr 30 + [winfo reqheight $w.tiplabel]]
+			set yreal_offset 5
         }
-        set x [$w canvasx 0]
-        set y [expr [$w canvasy 0] + $yoffset]
-	set tags $w.tipwindow
-	if {$fromc == 1} {
-	    lappend tags "sticky"
-	} 
-	if {$exists} {
-	    $w coords $w.tipwindow $x $y
-	    $w itemconfigure $w.tipwindow -anchor $anchor
-	} else {
-            $w create window $x $y -window $w.tiplabel -anchor $anchor \
-	        -tags $tags
-	    $w bind $w.tipwindow <Enter> "pdtk_tip_mouseover $w"
-	}
+		set x [expr $xreal + rand()*10] 
+		set y [expr $yreal + $top_bottom]
+
+		# now check if there is enough room to do the default above/below (if not redo behavior)
+		if { $top_bottom < 0 && $y < [expr [$w canvasy 0] + $yoffset] } {
+			set yoffset [winfo height $w]
+        	set anchor "sw"
+			set top_bottom [expr 30 + [winfo reqheight $w.tiplabel]]
+			set yreal_offset 5
+		}
+		if { $top_bottom > 0 && $y > [expr [$w canvasy 0] + $yoffset] } {
+        	set yoffset 0
+	    	set anchor "nw"
+			set top_bottom [expr -30 - [winfo reqheight $w.tiplabel]]
+			set yreal_offset -5
+		}
+		set x [expr $xreal + rand()*10] 
+		set y [expr $yreal + $top_bottom]
+
+		# if we still cannot fit things, let's now stick them as close to the side we selected last
+		if { $top_bottom < 0 && $y < [expr [$w canvasy 0] + $yoffset] } { set y [expr [$w canvasy 0] + $yoffset] }
+		if { $top_bottom > 0 && $y > [expr [$w canvasy 0] + $yoffset] } { set y [expr [$w canvasy 0] + $yoffset] }
+
+		# now check the width
+		set right 0
+		set xarrow [expr $x + 5]
+
+		if { [expr $x + [winfo reqwidth $w.tiplabel]] > [expr [$w canvasx 0] + [winfo reqwidth $w]] } {
+			set tmp1 [expr $x - (($x + [winfo reqwidth $w.tiplabel]) - ([$w canvasx 0] + [winfo reqwidth $w]))]
+			set x $tmp1
+			set right 1
+		}
+		if { $x < [$w canvasx 0] } {
+			set x [$w canvasx 0]
+		}
+
+		#now do the arrow
+		if { $right } {
+			if { $xarrow > [expr [$w canvasx 0] + [winfo reqwidth $w]] } {
+				set xarrow [expr [$w canvasx 0] + [winfo reqwidth $w] - 12]
+			}
+		}
+
+		if { $top_bottom < 0 } {
+			set yarrow [expr $y + [winfo reqheight $w.tiplabel]]
+		} else {
+			set yarrow [expr $y - [winfo reqheight $w.tiplabel]]
+		}
+
+		$w create polygon 0 0 0 0 0 0 -fill $nlet_color -width 4 -tags tiparrow
+		$w coords tiparrow $xreal [expr $yreal+$yreal_offset] $xarrow $yarrow [expr $xarrow+7] $yarrow
+
+		set tags $w.tipwindow
+		if {$fromc == 1} {
+			lappend tags "sticky"
+		} 
+		if {$exists} {
+			$w coords $w.tipwindow $x $y
+			$w itemconfigure $w.tipwindow -anchor $anchor
+		} else {
+		       	$w create window $x $y -window $w.tiplabel -anchor $anchor \
+			    -tags $tags
+			$w bind $w.tipwindow <Enter> "pdtk_tip_mouseover $w"
+		}
     }
 }
 
@@ -7212,7 +7305,7 @@ proc pdtk_tip_mouseover {w} {
 
 proc pdtk_gettip { w item xletno name helpname dir } {
     if {$dir eq {}} {
-	set dir $::sys_libdir/doc/5.reference
+		set dir $::sys_libdir/doc/5.reference
     }
     # trim off trailing ".pd" for abstractions
     regexp {^(.*)(?:\.pd)} $name -- name
@@ -7223,11 +7316,11 @@ proc pdtk_gettip { w item xletno name helpname dir } {
     set metatag description
     if {$item eq "inlet" ||
 	$item eq "outlet"} {
-	set varxlet [join [list $item "n"] "_"]
+		set varxlet [join [list $item "n"] "_"]
         set metatag [join [list $item $xletno] "_"]
-	set msg "[string toupper [string map {_ " "} $metatag] 0 0] of $name"
+		set msg "[string toupper [string map {_ " "} $metatag] 0 0] of $name"
     } elseif {$item eq "text"} {
-	set metatag "description"
+		set metatag "description"
         set msg $name
     }
     set filefound 0
@@ -7238,27 +7331,27 @@ proc pdtk_gettip { w item xletno name helpname dir } {
         set filefound 1
     }
     if {$filefound} {
-	set filecontents [read $fp]
-	close $fp
-	# leave in pd's linebreaks-- serendipitously it
-	# makes the tipwindow more compact/easier to read
-	regsub -all {[{}]} $filecontents "" filecontents
-	# turn escaped semicolons into linebreaks
-	regsub -all {[\n\s]\\;[\n\s]} $filecontents "\n" filecontents
-	set match {}
-	# if $varxlet ne {} then the $item is an inlet or outlet
-	if { $varxlet ne {}  &&
-	    [regexp -nocase \
-	    "#X text \[0-9\]+ \[0-9\]+ $varxlet (\[^;\]+)" \
-	    $filecontents] } {
-	    set match "(variable inlet)"
-	}
-        regexp -nocase \
-	    "#X text \[0-9\]+ \[0-9\]+ $metatag (\[^;\]+)" \
-	    $filecontents -- match
-	if { $match ne {} } {
-	    set msg [string trim "$msg: $match"]
-	}
+		set filecontents [read $fp]
+		close $fp
+		# leave in pd's linebreaks-- serendipitously it
+		# makes the tipwindow more compact/easier to read
+		regsub -all {[{}]} $filecontents "" filecontents
+		# turn escaped semicolons into linebreaks
+		regsub -all {[\n\s]\\;[\n\s]} $filecontents "\n" filecontents
+		set match {}
+		# if $varxlet ne {} then the $item is an inlet or outlet
+		if { $varxlet ne {}  &&
+		    [regexp -nocase \
+		    "#X text \[0-9\]+ \[0-9\]+ $varxlet (\[^;\]+)" \
+		    $filecontents] } {
+		    set match "(variable inlet)"
+		}
+    	    regexp -nocase \
+		    "#X text \[0-9\]+ \[0-9\]+ $metatag (\[^;\]+)" \
+		    $filecontents -- match
+		if { $match ne {} } {
+		    set msg [string trim "$msg: $match"]
+		}
     }
     # make Pd's comma atoms look pretty
     regsub -all { \\,} $msg {,} msg
-- 
GitLab