diff --git a/src/g_editor.c b/src/g_editor.c
index 2b192e7e3eec48d2c5a0927b69c97e2f46390698..31c6e04fce441f20790dff33715c313b9f9e15ae 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -2591,6 +2591,7 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
         {
                 /* look for an outlet */
             int noutlet;
+			int ninlet;
             if (ob && (noutlet = obj_noutlets(ob)) && ypos >= y2-4)
             {
                 int width = x2 - x1;
@@ -2634,10 +2635,12 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
                             sys_vgui(".x%x.c itemconfigure %s -outline $select_nlet_color -width $highlight_width\n",
                                      x,
                                      canvas_cnct_outlet_tag);
-                            //sys_vgui(".x%x.c raise %s\n",
-                            //         x,
-                            //         canvas_cnct_outlet_tag);
+							
+                            sys_vgui(".x%x.c raise %s\n",
+                                     x,
+                                     canvas_cnct_outlet_tag);
 							outlet_issignal = obj_issignaloutlet(ob,closest);
+							//sys_vgui("pdtk_canvas_enteritem .x%x.c %d %d %s 0\n;", x, xpos, ypos, canvas_cnct_outlet_tag);
                         }
                         // jsarlo
 						if(x->gl_magic_glass) {
@@ -2652,6 +2655,46 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
                 else if (doit)
                     goto nooutletafterall;
             }
+                /* look for an inlet (these are colored differently since they are not connectable) */
+            else if (ob && (ninlet = obj_ninlets(ob)) && ypos <= y1+4)
+            {
+                int width = x2 - x1;
+                int nin1 = (ninlet > 1 ? ninlet - 1 : 1);
+                int closest = ((xpos-x1) * (nin1) + width/2)/width;
+                int hotspot = x1 +
+                    (width - IOWIDTH) * closest / (nin1);
+                if (closest < ninlet &&
+                    xpos >= (hotspot-1) && xpos <= hotspot + (IOWIDTH+1))
+                {
+           	        t_rtext *y = glist_findrtext(x, (t_text *)&ob->ob_g);
+
+                    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" : (inlet_issignal ? "$signal_cord" : "$msg_cord")),
+								(inlet_issignal ? "$signal_nlet" : "$msg_nlet"));
+                    }
+
+                    if (y)
+                    {
+						last_inlet_filter = gobj_filter_highlight_behavior(y);
+                        sprintf(canvas_cnct_inlet_tag, 
+                                "%si%d",
+                                rtext_gettag(y),
+                                closest);
+                        sys_vgui(".x%x.c itemconfigure %s -width $highlight_width\n",
+                                 x,
+                                 canvas_cnct_inlet_tag);
+						
+                        sys_vgui(".x%x.c raise %s\n",
+                                 x,
+                                 canvas_cnct_inlet_tag);
+						inlet_issignal = obj_issignalinlet(ob,closest);
+						//sys_vgui("pdtk_canvas_enteritem .x%x.c %d %d %s 0\n;", x, xpos, ypos, canvas_cnct_outlet_tag);
+					}
+				}
+			}
                 /* not in an outlet; select and move */
             else if (doit)
             {
@@ -2690,6 +2733,14 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
     	    else
             // jsarlo 
             {
+                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" : (inlet_issignal ? "$signal_cord" : "$msg_cord")),
+							(inlet_issignal ? "$signal_nlet" : "$msg_nlet"));
+                }
+
                 if (canvas_cnct_outlet_tag[0] != 0)
                 {
                     sys_vgui(".x%x.c itemconfigure %s -outline %s -fill %s -width 1\n",
@@ -2698,6 +2749,7 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
 							(outlet_issignal ? "$signal_nlet" : "$msg_nlet"));
                     canvas_cnct_outlet_tag[0] = 0;                  
                 }
+
 				if(x->gl_magic_glass) {              
                 	magicGlass_unbind(x->gl_magic_glass);
                 	magicGlass_hide(x->gl_magic_glass);
@@ -2980,10 +3032,11 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
                     sys_vgui(".x%x.c itemconfigure %s -outline $select_nlet_color -width $highlight_width\n",
                              x,
                              canvas_cnct_inlet_tag);
-                    //sys_vgui(".x%x.c raise %s\n",
-                    //         x,
-                    //         canvas_cnct_inlet_tag);
+                    sys_vgui(".x%x.c raise %s\n",
+                             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);
                 }
                 canvas_setcursor(x, CURSOR_EDITMODE_CONNECT);
             }
@@ -4723,6 +4776,68 @@ static void glist_setlastxy(t_glist *gl, int xval, int yval)
     canvas_last_glist_y = yval;
 }
 
+static void canvas_enterobj(t_canvas *x, t_symbol *item, t_floatarg xpos,
+    t_floatarg ypos, t_floatarg xletno)
+{
+    t_symbol *name = 0, *helpname, *dir;
+    int yoffset = 0, xoffset = 0;
+    if (item == gensym("inlet"))
+    {
+	yoffset = 1;
+        xoffset = xletno==0 ? 1 : -1;
+    }
+    else if (item == gensym("outlet"))
+    {
+	yoffset = -1;
+	xoffset = xletno== 0 ? 1 : -1;
+    }
+    int x1, y1, x2, y2;
+    t_gobj *g;
+    if (g = canvas_findhitbox(x, xpos+xoffset, ypos+yoffset,
+	&x1, &y1, &x2, &y2))
+    {
+        if (pd_class((t_pd *)g)==canvas_class ?
+	    canvas_isabstraction((t_canvas *)g) : 0)
+	{
+	    t_canvas *z = (t_canvas *)g;
+	    name = z->gl_name;
+	    helpname = z->gl_name;
+	    dir = canvas_getdir(z);
+	}
+	else
+	{
+	    name = g->g_pd->c_name;
+	    helpname = g->g_pd->c_helpname;
+	    dir = g->g_pd->c_externdir;
+	}
+        sys_vgui("pdtk_gettip .x%lx.c %s %d \
+	    [list %s] [list %s] [list %s]\n",
+	    x, item->s_name, (int)xletno,
+	    name->s_name, helpname->s_name, dir->s_name);
+    }
+}
+
+static void canvas_tip(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
+{
+    if (s == gensym("echo"))
+	return;
+    if (argv->a_type != A_FLOAT)
+        error("canvas_tip: bad argument");
+    else
+    {
+	    sys_vgui("pdtk_tip .x%lx.c 1", x);
+	    t_atom *at = argv;
+	    int i;
+	    for (i=0; i<argc; i++)
+	    {
+		if (at[i].a_type == A_FLOAT)
+		    sys_vgui(" %g", at[i].a_w.w_float);
+		else if (at[i].a_type == A_SYMBOL)
+		    sys_vgui(" %s", at[i].a_w.w_symbol->s_name);
+	    }
+	    sys_gui("\n");
+    }
+}
 
 void g_editor_setup(void)
 {
@@ -4737,6 +4852,12 @@ void g_editor_setup(void)
         A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)glist_noselect,
         gensym("noselect"), A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_enterobj, gensym("enter"),
+		A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_tip, gensym("tip"),
+	A_GIMME, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_tip, gensym("echo"),
+        A_GIMME, A_NULL);
 /* ------------------------ menu actions ---------------------------- */
     class_addmethod(canvas_class, (t_method)canvas_menuclose,
         gensym("menuclose"), A_DEFFLOAT, 0);
diff --git a/src/g_text.c b/src/g_text.c
index fc96fa6836055b37f3d726008846c32c19b23980..e3d8181fe8e304af186b65301ee1942785c95081 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -1475,7 +1475,7 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
 			//fprintf(stderr,"glist_drawiofor o firsttime\n");
             issignal = obj_issignaloutlet(ob,i);
             sys_vgui(".x%lx.c create rectangle %d %d %d %d \
-                      -fill %s -outline %s -tags %so%d\n",
+                      -fill %s -outline %s -tags {%so%d outlet}\n",
                 glist_getcanvas(glist), onset, y2 - 2, onset + IOWIDTH, y2,
                 (issignal ? "$signal_nlet" : "$msg_nlet"),
                 (issignal ? "$signal_cord" : "$msg_cord"),
@@ -1505,7 +1505,7 @@ void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
 			//fprintf(stderr,"glist_drawiofor i firsttime\n");
             issignal = obj_issignalinlet(ob,i);
             sys_vgui(".x%lx.c create rectangle %d %d %d %d \
-                      -fill %s -outline %s -tags %si%d\n",
+                      -fill %s -outline %s -tags {%si%d inlet}\n",
                 glist_getcanvas(glist), onset, y1, onset + IOWIDTH, y1 + EXTRAPIX,
                 (issignal ? "$signal_nlet" : "$msg_nlet"),
                 (issignal ? "$signal_cord" : "$msg_cord"),
@@ -1545,7 +1545,7 @@ void glist_drawiofor_withtag(t_glist *glist, t_object *ob, int firsttime,
 			//fprintf(stderr,"drawiofor_withtag o firsttime\n");
             issignal = obj_issignaloutlet(ob,i);
             sys_vgui(".x%lx.c create rectangle %d %d %d %d \
-                      -fill %s -outline %s -tags %so%d\n",
+                      -fill %s -outline %s -tags {%so%d outlet}\n",
                 glist_getcanvas(glist), onset, y2 - 2, onset + IOWIDTH, y2,
                 (issignal ? "$signal_nlet" : "$msg_nlet"),
                 (issignal ? "$signal_cord" : "$msg_cord"),
@@ -1570,7 +1570,7 @@ void glist_drawiofor_withtag(t_glist *glist, t_object *ob, int firsttime,
 			//fprintf(stderr,"drawiofor_withtag i firsttime\n");
             issignal = obj_issignalinlet(ob,i);
             sys_vgui(".x%lx.c create rectangle %d %d %d %d \
-                      -fill %s -outline %s -tags %si%d\n",
+                      -fill %s -outline %s -tags {%si%d inlet}\n",
                 glist_getcanvas(glist), onset, y1, onset + IOWIDTH, y1 + EXTRAPIX,
                 (issignal ? "$signal_nlet" : "$msg_nlet"),
                 (issignal ? "$signal_cord" : "$msg_cord"),
diff --git a/src/pd.tk b/src/pd.tk
index 1cd202b64feae5caea40369b752798d51b95a928..f6a8daeac3286d79014edd76b52f5b832ee84814 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -334,6 +334,14 @@ set global_clipboard 0
 set last_clipboard 0
 set global_selection 0
 
+#TOOLTIPS PATCH
+#TODO: make a separate tcl file for tooltips and put
+#afterid in its scope    
+variable afterid 0
+variable duplicate_tags -1
+variable current_window 0
+variable nlet_color 0
+
 # x:y location tooltip during dragging
 set tooltip [toplevel .tooltip -bd 1 -bg black]
 wm attributes $tooltip -topmost 1
@@ -1405,6 +1413,7 @@ 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 command -label {Edit mode} -accelerator [accel_munge "Ctrl+e"] \
     -state disabled
 
@@ -2252,10 +2261,12 @@ 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 "Edit mode" \
         -indicatoron false -selectcolor black \
         -command [concat menu_editmode $name] \
-        -accelerator [accel_munge "Ctrl+e"]
+        -accelerator [accel_munge "Ctrl+e"] -variable ::editmode($name)
 
 	if { $editable == 1 } {
     	$name.m.edit entryconfigure "Edit mode" -background "#7dd37d"
@@ -2498,6 +2509,15 @@ proc pdtk_canvas_new {name width height geometry editable} {
     bind $name.c <KeyRelease> {pdtk_canvas_sendkey %W 0 %K %A 0 1}
     bind $name.c <Motion> {pdtk_canvas_motion %W %x %y 0}
     bind $name.c <Control-Motion> {pdtk_canvas_motion %W %x %y 2}
+
+    # canvas bindings ---------------------------------------------------------
+    # just for tooltips right now
+    $name.c bind inlet <Enter> "pdtk_canvas_enteritem %W %x %y inlet %#"
+    $name.c bind outlet <Enter> "pdtk_canvas_enteritem %W %x %y outlet %#"
+    $name.c bind text <Enter> "pdtk_canvas_enteritem %W %x %y text %#"
+    $name.c bind inlet <Leave> "pdtk_canvas_leaveitem %W inlet"
+    $name.c bind outlet <Leave> "pdtk_canvas_leaveitem %W outlet"
+    $name.c bind text <Leave> "pdtk_canvas_leaveitem %W text"
 	
     if {$pd_nt == 2} {
         bind $name.c <Option-Motion> {pdtk_canvas_motion %W %x %y 4}
@@ -7063,3 +7083,186 @@ if { [info tclversion] >= 8.5 && $pd_nt == 0 } {
 	}
 }
 
+ 
+proc pdtk_canvas_enteritem_gettags {tkcanvas x y item} {
+	variable nlet_color
+    if {[winfo exists $tkcanvas]} {
+        set mytoplevel [winfo toplevel $tkcanvas]
+        set id [$tkcanvas find withtag current]
+        set tags [$tkcanvas gettags $id]
+        set xletno -1 
+		set object text
+		if { [string match *o* $item] } { set object outlet }
+		if { [string match *i* $item] } { set object inlet }
+        foreach tag $tags {
+			if { ![regexp "\.x.*\.t.*\[io\](\[0-9\]+)$" $tag -- xletno] } {
+			    # iemgui tag
+			    regexp ".*OUT(\[0-9\]+)$" $tag -- xletno
+		        regexp ".*IN(\[0-9\]+)$" $tag -- xletno
+			}
+		}
+
+		set nlet_color [$tkcanvas itemcget [lindex $tags 0] -outline]
+
+        pd [concat $mytoplevel enter $object \
+            [$tkcanvas canvasx $x] [$tkcanvas canvasy $y] $xletno \;]
+    }
+}
+
+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} {
+	    #if {$item eq "inlet" ||
+	    #    $item eq "outlet"} {
+        #        $tkcanvas itemconfigure $item -activewidth 5 
+	    #}
+
+	    set duplicate_tags $item
+		if {$current_window eq $tkcanvas} {
+			after cancel $afterid
+		}
+		set current_window $tkcanvas
+		set afterid [after 250 pdtk_canvas_enteritem_gettags \
+			$tkcanvas $x $y $item]
+	}
+}
+
+# move activewidth to toggle on editmode?
+proc pdtk_canvas_leaveitem {w item} {
+    variable afterid
+    variable current_window
+	variable duplicate_tags
+    #if {$::autotips_button == 0} {return}
+    after cancel $afterid
+	set afterid 0
+    if {[lsearch -exact [$w gettags $w.tipwindow] "sticky"] == -1} {
+        #if {$item eq "inlet" ||
+	    #$item eq "outlet"} {
+        #    $w itemconfigure $item -activewidth 0
+        #}
+		if {[winfo exists $w.tiplabel]} {
+            set afterid [after 50 "pdtk_tip $w 0 0"]
+            set current_window $w
+		}
+    }
+	set duplicate_tags -1;
+}
+
+proc pdtk_tip {w fromc show args} {
+	variable select_color
+	variable nlet_color
+    set exists [winfo exists $w.tiplabel]
+    if {$show == 0} {
+        catch {destroy $w.tiplabel}
+        catch {$w delete $w.tipwindow}
+    } 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"
+			}
+            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 anchor "nw"
+        }
+        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"
+	}
+    }
+}
+
+# move the tip if the user happens to mouse over it
+proc pdtk_tip_mouseover {w} {
+    set msg [$w.tiplabel cget -text]
+    set sticky [expr [lsearch -exact [$w gettags $w.tipwindow] \
+	"sticky"] != -1]
+    pdtk_tip $w $sticky 1 $msg 
+}
+
+proc pdtk_gettip { w item xletno name helpname dir } {
+    if {$dir eq {}} {
+	set dir $::sys_libdir/doc/5.reference
+    }
+    # trim off trailing ".pd" for abstractions
+    regexp {^(.*)(?:\.pd)} $name -- name
+    # use $varxlet to see if an object has a 
+    # variable xlet (marked in the docs as
+    # "INLET_N" or "OUTLET_N") 
+    set varxlet {}
+    set metatag description
+    if {$item eq "inlet" ||
+	$item eq "outlet"} {
+	set varxlet [join [list $item "n"] "_"]
+        set metatag [join [list $item $xletno] "_"]
+	set msg "[string toupper [string map {_ " "} $metatag] 0 0] of $name"
+    } elseif {$item eq "text"} {
+	set metatag "description"
+        set msg $name
+    }
+    set filefound 0
+    if {![catch {set fp [open [file join $dir \
+	    "$name-help.pd"]]}] ||
+        ![catch {set fp [open [file join $dir \
+	"$helpname-help.pd"]]}] } {
+        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"]
+	}
+    }
+    # make Pd's comma atoms look pretty
+    regsub -all { \\,} $msg {,} msg
+    regsub -all {\n\\,} $msg ",\n" msg
+    pdtk_tip $w 0 1 $msg
+}
+