diff --git a/pd/src/dialog_gui.tcl b/pd/src/dialog_gui.tcl
index c8c0ef60f0906f4be49390e99a6c7806053eff1d..f951f50ecd64fa9119ad1c35b9ef1b2213d890ae 100644
--- a/pd/src/dialog_gui.tcl
+++ b/pd/src/dialog_gui.tcl
@@ -110,7 +110,7 @@ proc ::dialog_gui::set_gui_preset {args} {
             set ::pd_colors(signal_cord)      #808095
             set ::pd_colors(signal_nlet)      $::pd_colors(signal_cord)
             set ::pd_colors(xlet_hover)       grey
-            set ::pd_colors(link)             #eb5f28
+            set ::pd_colors(link)             "#eb5f28"
             set ::pd_colors(selection)        #e87216
             set ::pd_colors(selection_rectangle) #e87216
             set ::pd_colors(highlighted_text) black
diff --git a/pd/src/dialog_prefs.tcl b/pd/src/dialog_prefs.tcl
index 5357ee63d0dadd60176e18f860a96eb1dcce35d2..cb838dbbe5f7a2de31f63c13a1752b1bf0e66da0 100644
--- a/pd/src/dialog_prefs.tcl
+++ b/pd/src/dialog_prefs.tcl
@@ -194,7 +194,7 @@ proc ::dialog_prefs::set_color {array key op} {
             all_cords&&control -stroke $c"]}
         selection {
             set commands [list "itemconfigure \
-                selected&&text -fill $c"]
+                selected&&text&&(!box&&!iemgui) -fill $c"]
             lappend commands "itemconfigure \
                 selected&&(border&&(!iemgui)) -fill $c"
             lappend commands "itemconfigure \
@@ -226,7 +226,10 @@ proc ::dialog_prefs::set_color {array key op} {
                 .search.navtext tag configure link -foreground $c
                 .search.f.advancedlabel configure -foreground $c
             }
-            return
+            if {[winfo exists .printout.frame.text]} {
+                .printout.frame.text tag configure link -foreground $c
+            }
+            # return
         }
         default {}
     }
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 918b33e7cdffc6f22a709a679cf0bc5b284831d5..6a5ce1c3c4a6c4739e9b536b5dcc4e1a66bcc6e1 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -5053,13 +5053,19 @@ static int glist_dofinderror(t_glist *gl, void *error_object)
     return (0);
 }
 
+extern t_class *messresponder_class;
 void canvas_finderror(void *error_object)
 {
     t_canvas *x;
+    void *error_gobj = error_object;
+    /* Since the messresponder_class isn't patchable,
+       we climb up to the parent message_class addy. */
+    if(((t_gobj *)error_object)->g_pd == messresponder_class)
+        error_gobj = error_object - sizeof(t_text);
         /* find all root canvases */
     for (x = canvas_list; x; x = x->gl_next)
     {
-        if (glist_dofinderror(x, error_object))
+        if (glist_dofinderror(x, error_gobj))
             return;
     }
     post("... sorry, I couldn't find the source of that error.");
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index c8f8c816f0d7fcf553b84933b9d1fb0f3389c8a2..de4a74331a47599cfc5fef2e809d27951d7bde01 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -530,7 +530,7 @@ typedef struct _message
     t_clock *m_clock;
 } t_message;
 
-static t_class *messresponder_class;
+t_class *messresponder_class;
 
 static void messresponder_bang(t_messresponder *x)
 {
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index 0789ad82353d928030962b5d452196192b8b35e3..d6e7f58c31903a461d573dfb40108e7c5c0e0a5c 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -21,6 +21,7 @@ void glob_key(void *dummy, t_symbol *s, int ac, t_atom *av);
 void glob_pastetext(void *dummy, t_symbol *s, int ac, t_atom *av);
 void glob_audiostatus(void *dummy);
 void glob_finderror(t_pd *dummy);
+void glob_findinstance(t_pd *dummy, t_symbol*s);
 void glob_audio_properties(t_pd *dummy, t_floatarg flongform);
 void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv);
 void glob_audio_setapi(t_pd *dummy, t_floatarg f);
@@ -105,6 +106,8 @@ void glob_init(void)
         gensym("audiostatus"), 0);
     class_addmethod(glob_pdobject, (t_method)glob_finderror,
         gensym("finderror"), 0);
+    class_addmethod(glob_pdobject, (t_method)glob_findinstance,
+          gensym("findinstance"), A_SYMBOL, 0);
     class_addmethod(glob_pdobject, (t_method)glob_audio_properties,
         gensym("audio-properties"), A_DEFFLOAT, 0);
     class_addmethod(glob_pdobject, (t_method)glob_audio_dialog,
diff --git a/pd/src/pd.tk b/pd/src/pd.tk
index d94b93299a9dac9c03b3a8b6dd60fd5569fb226f..7826b450bb65ad3b9a85ee546d7efd0959736556 100644
--- a/pd/src/pd.tk
+++ b/pd/src/pd.tk
@@ -944,6 +944,35 @@ proc pdtk_post {stuff} {
 	.printout.frame.text configure -state disabled
 }
 
+proc pderror_select_by_id {objectid} {
+    if [llength $objectid] {
+        pdsend "pd findinstance $objectid"
+    }
+}
+
+# stopgap for ::pdwindow::logpost
+proc pdtk_posterror {objectid loglevel errormsg} {
+    set t .printout.frame.text
+    $t configure -state normal
+    # if we have an object id, make a friendly link...
+    if {$objectid ne ""} {
+        $t insert end "error" [list obj$objectid link]
+        $t tag bind obj$objectid <1> "pderror_select_by_id $objectid; break"
+        $t tag bind obj$objectid <Enter> "$t configure -cursor hand2"
+        $t tag bind obj$objectid <Leave> "$t configure -cursor xterm"
+        $t tag configure link -foreground "$::pd_colors(link)" \
+            -underline on
+    } else {
+        $t insert end "error"
+    }
+    $t insert end ": "
+    $t insert end $errormsg
+
+    after cancel .printout.frame.text yview end-2char
+    after idle .printout.frame.text yview end-2char
+	.printout.frame.text configure -state disabled
+}
+
 proc pdtk_standardkeybindings {id} {
     global pd_nt ctrl_key
     bind $id <$ctrl_key-Key> {pdtk_canvas_ctrlkey %W %K 0}
diff --git a/pd/src/s_print.c b/pd/src/s_print.c
index de58e5f0a298fbca9fac99fabfdadd6d4955f9dc..ac03e42b18be4282cbc0672863aaf58d670e7464 100644
--- a/pd/src/s_print.c
+++ b/pd/src/s_print.c
@@ -13,6 +13,58 @@
 t_printhook sys_printhook;
 int sys_printtostderr;
 
+/* escape characters for tcl/tk */
+static char* strnescape(char *dest, const char *src, size_t len)
+{
+    int ptin = 0;
+    unsigned ptout = 0;
+    for(; ptout < len; ptin++, ptout++)
+    {
+        int c = src[ptin];
+        if (c == '\\' || c == '{' || c == '}')
+            dest[ptout++] = '\\';
+            dest[ptout] = src[ptin];
+            if (c==0) break;
+    }
+
+    if(ptout < len)
+        dest[ptout]=0;
+    else
+        dest[len-1]=0;
+
+    return dest;
+}
+
+static char* strnpointerid(char *dest, const void *pointer, size_t len)
+{
+    *dest=0;
+    if (pointer)
+        snprintf(dest, len, ".x%lx", (unsigned long)pointer);
+    return dest;
+}
+
+static void doerror(const void *object, const char *s)
+{
+    char upbuf[MAXPDSTRING];
+    upbuf[MAXPDSTRING-1]=0;
+
+    // what about sys_printhook_error ?
+    if (sys_printhook)
+    {
+        snprintf(upbuf, MAXPDSTRING-1, "error: %s", s);
+        (*sys_printhook)(upbuf);
+    }
+    else if (sys_printtostderr)
+        fprintf(stderr, "error: %s", s);
+    else
+    {
+        char obuf[MAXPDSTRING];
+        sys_vgui("pdtk_posterror {%s} 1 {%s}\n",
+            strnpointerid(obuf, object, MAXPDSTRING),
+            strnescape(upbuf, s, MAXPDSTRING));
+    }
+}
+
 static void dopost(const char *s)
 {
     if (sys_printhook)
@@ -102,12 +154,13 @@ void error(const char *fmt, ...)
     va_list ap;
     t_int arg[8];
     int i;
-    dopost("error: ");
+
     va_start(ap, fmt);
     vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
     va_end(ap);
     strcat(buf, "\n");
-    dopost(buf);
+
+    doerror(NULL, buf);
 }
 
 void verbose(int level, const char *fmt, ...)
@@ -143,12 +196,14 @@ void pd_error(void *object, const char *fmt, ...)
     t_int arg[8];
     int i;
     static int saidit;
-    dopost("error: ");
+
     va_start(ap, fmt);
     vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
     va_end(ap);
     strcat(buf, "\n");
-    dopost(buf);
+
+    doerror(object, buf);
+
     error_object = object;
     if (!saidit)
     {
@@ -169,6 +224,19 @@ void glob_finderror(t_pd *dummy)
     }
 }
 
+void glob_findinstance(t_pd *dummy, t_symbol*s)
+{
+    // revert s to (potential) pointer to object
+    long obj = 0;
+    if (sscanf(s->s_name, ".x%lx", &obj))
+    {
+        if (obj)
+        {
+            canvas_finderror((void *)obj);
+        }
+    }
+}
+
 void bug(const char *fmt, ...)
 {
     char buf[MAXPDSTRING];
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index 51db0117336235678857e4aded58b3161932f287..ff12b689a45a985e6c043689dd2466089f7028ec 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -358,6 +358,13 @@ static void sel1_proxy_symbol(t_sel1_proxy *x, t_symbol *s)
     SETSYMBOL(&p->x_atom, s);
 }
 
+static void sel1_proxy_anything(t_sel1_proxy *x, t_symbol *s, int argc,
+    t_atom *argv)
+{
+    t_sel1 *parent = (t_sel1 *)x->parent;
+    pd_error(parent, "select: no method for %s", s->s_name);
+}
+
 static void sel1_float(t_sel1 *x, t_float f)
 {
     if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float)
@@ -495,6 +502,7 @@ void select_setup(void)
         0, 0, sizeof(t_sel1_proxy), 0, 0);
     class_addfloat(sel1_proxy_class, (t_method)sel1_proxy_float);
     class_addsymbol(sel1_proxy_class, (t_method)sel1_proxy_symbol);
+    class_addanything(sel1_proxy_class, (t_method)sel1_proxy_anything);
     sel1_class = class_new(gensym("select"), 0, 0,
         sizeof(t_sel1), 0, 0);
     class_addfloat(sel1_class, sel1_float);