diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index b30d7d5ba86c0d3bf9316298b12e5152fd2725b0..47b5ebfcd446dca1ebdeea6dff22508db1ee8c5b 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -155,10 +155,20 @@ t_canvasenvironment *canvas_getenv(t_canvas *x)
     return (x->gl_env);
 }
 
-int canvas_getdollarzero( void)
+extern t_class *messresponder_class;
+extern t_glist *messresponder_getglist(t_pd *x);
+
+int canvas_getdollarzero(t_pd *x)
 {
-    t_canvas *x = canvas_getcurrent();
-    t_canvasenvironment *env = (x ? canvas_getenv(x) : 0);
+    t_canvas *cnv;
+    /* binbuf_eval can send us a NULL target... */
+    if (x && pd_class(x) == messresponder_class)
+    {
+        cnv = messresponder_getglist(x);
+    }
+    else
+        cnv = canvas_getcurrent();
+    t_canvasenvironment *env = (cnv ? canvas_getenv(cnv) : 0);
     if (env)
         return (env->ce_dollarzero);
     else return (0);
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index 52c0f02c601476f0cc2c5f928ade08e6b76f5147..7c7fc16022f73d242a06c80c821e6952e01c4aa3 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -550,6 +550,7 @@ void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv)
 typedef struct _messresponder
 {
     t_pd mr_pd;
+    t_glist *mr_glist;
     t_outlet *mr_outlet;
 } t_messresponder;
 
@@ -561,7 +562,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)
 {
@@ -596,13 +597,17 @@ static void messresponder_anything(t_messresponder *x,
     outlet_anything(x->mr_outlet, s, argc, argv);
 }
 
+/* get the glist cached in a message responder */
+t_glist *messresponder_getglist(t_pd *x)
+{
+    return ((t_messresponder *)x)->mr_glist;
+}
+
 static void message_bang(t_message *x)
 {
     /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
         instance number for $0 */
-    canvas_setcurrent((t_canvas *)x->m_glist);
     binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 0, 0);
-    canvas_unsetcurrent((t_canvas *)x->m_glist);
 }
 
 static void message_float(t_message *x, t_float f)
@@ -611,9 +616,7 @@ static void message_float(t_message *x, t_float f)
     SETFLOAT(&at, f);
     /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
         instance number for $0 */
-    canvas_setcurrent((t_canvas *)x->m_glist);
     binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
-    canvas_unsetcurrent((t_canvas *)x->m_glist);
 }
 
 static void message_symbol(t_message *x, t_symbol *s)
@@ -622,9 +625,7 @@ static void message_symbol(t_message *x, t_symbol *s)
     SETSYMBOL(&at, s);
     /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
         instance number for $0 */
-    canvas_setcurrent((t_canvas *)x->m_glist);
     binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
-    canvas_unsetcurrent((t_canvas *)x->m_glist);
 }
 
 static void message_blob(t_message *x, t_blob *st)
@@ -633,9 +634,7 @@ static void message_blob(t_message *x, t_blob *st)
     SETBLOB(&at, st);
     /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
         instance number for $0 */
-    canvas_setcurrent((t_canvas *)x->m_glist);
     binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, 1, &at);
-    canvas_unsetcurrent((t_canvas *)x->m_glist);
 }
 
 static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
@@ -645,9 +644,7 @@ static void message_list(t_message *x, t_symbol *s, int argc, t_atom *argv)
     // but will this break anything?
     /*  we do canvas_setcurrent/unsetcurrent to substitute canvas
         instance number for $0 */
-    canvas_setcurrent((t_canvas *)x->m_glist);
     binbuf_eval(x->m_text.te_binbuf, &x->m_messresponder.mr_pd, argc, argv);
-    canvas_unsetcurrent(x->m_glist);
 }
 
 static void message_set(t_message *x, t_symbol *s, int argc, t_atom *argv)
@@ -779,6 +776,7 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
     t_message *x = (t_message *)pd_new(message_class);
     x->m_messresponder.mr_pd = messresponder_class;
     x->m_messresponder.mr_outlet = outlet_new(&x->m_text, &s_float);
+    x->m_messresponder.mr_glist = gl;
     x->m_text.te_width = 0;                             /* don't know it yet. */
     x->m_text.te_type = T_MESSAGE;
     x->m_text.te_iemgui = 0;
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index 1b96e33d3ac05fecf798498b3277e80ce47a104c..69922d50eedbd3cb9e1c903083534ce05d071869 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/src/m_binbuf.c
@@ -549,7 +549,7 @@ int binbuf_resize(t_binbuf *x, int newsize)
     return (new != 0);
 }
 
-int canvas_getdollarzero( void);
+int canvas_getdollarzero(t_pd *x);
 
 /* JMZ:
  * s points to the first character after the $
@@ -602,7 +602,8 @@ int binbuf_expanddollsym(char*s, char*buf,t_atom dollar0, int ac, t_atom *av,
 
 /* LATER remove the dependence on the current canvas for $0; should be another
 argument. */
-t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
+static t_symbol *binbuf_dorealizedollsym(t_pd *target, t_symbol *s, int ac,
+    t_atom *av, int tonew)
 {
     char buf[MAXPDSTRING];
     char buf2[MAXPDSTRING];
@@ -610,7 +611,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
     char*substr;
     int next=0, i=MAXPDSTRING;
     t_atom dollarnull;
-    SETFLOAT(&dollarnull, canvas_getdollarzero());
+    SETFLOAT(&dollarnull, canvas_getdollarzero(target));
     while(i--)buf2[i]=0;
 
 #if 1
@@ -637,7 +638,7 @@ t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
         * JMZ: i am not sure what this means, so i might have broken it
         * it seems like that if "tonew" is set and the $arg cannot be expanded
         * (or the dollarsym is in reality a A_DOLLAR)
-        * 0 is returned from binbuf_realizedollsym
+        * 0 is returned from binbuf_dorealizedollsym
         * this happens, when expanding in a message-box, but does not happen
         * when the A_DOLLSYM is the name of a subpatch
         */
@@ -664,6 +665,11 @@ done:
     return (gensym(buf2));
 }
 
+t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av, int tonew)
+{
+    return binbuf_dorealizedollsym(0, s, ac, av, tonew);
+}
+
 #define SMALLMSG 5
 #define HUGEMSG 1000
 #ifdef MSW
@@ -681,12 +687,28 @@ done:
 #define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom)))
 #endif
 
+t_pd *pd_mess_from_responder(t_pd *x);
+static void binbuf_error(t_pd *x, const char *fmt, ...)
+{
+    char buf[MAXPDSTRING];
+    va_list ap;
+    va_start(ap, fmt);
+    vsnprintf(buf, MAXPDSTRING-1, fmt, ap);
+    va_end(ap);
+    if (x)
+        pd_error(pd_mess_from_responder(x), buf);
+    else
+        error(buf);
+}
+
 void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
 {
     t_atom smallstack[SMALLMSG], *mstack, *msp;
     t_atom *at = x->b_vec;
     int ac = x->b_n;
     int nargs, maxnargs = 0;
+    /* initial target for referencing $0 in msg boxes after a semicolon */
+    t_pd * init_target = target;
 
     //first we need to check if the list of arguments has $@
     //fprintf(stderr,"=========\nbinbuf_eval argc:%d ac:%d\n", argc, (int)ac);
@@ -769,13 +791,18 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
                 /* would it make sense to consider $@ here? */
                 if (at->a_w.w_index <= 0 || at->a_w.w_index > argc)
                 {
-                    error("$%d: not enough arguments supplied",
-                            at->a_w.w_index);
+                    binbuf_error(init_target,
+                        "$%d: %s",
+                        at->a_w.w_index,
+                        (at->a_w.w_index == 0 ?
+                            "symbol needed as message destination" :
+                            "not enough arguments supplied"));
                     goto cleanup; 
                 }
                 else if (argv[at->a_w.w_index-1].a_type != A_SYMBOL)
                 {
-                    error("$%d: symbol needed as message destination",
+                    binbuf_error(init_target,
+                        "$%d: symbol needed as message destination",
                         at->a_w.w_index);
                     goto cleanup; 
                 }
@@ -783,10 +810,11 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
             }
             else if (at->a_type == A_DOLLSYM)
             {
-                if (!(s = binbuf_realizedollsym(at->a_w.w_symbol,
+                if (!(s = binbuf_dorealizedollsym(init_target, at->a_w.w_symbol,
                     argc, argv, 0)))
                 {
-                    error("$%s: not enough arguments supplied",
+                    binbuf_error(init_target,
+                        "$%s: not enough arguments supplied",
                         at->a_w.w_symbol->s_name);
                     goto cleanup;
                 }
@@ -794,7 +822,8 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
             else s = atom_getsymbol(at);
             if (!(target = s->s_thing))
             {
-                error("%s: no such object", s->s_name);
+                binbuf_error(init_target,
+                "%s: no such object", s->s_name);
             cleanup:
                 do at++, ac--;
                 while (ac && at->a_type != A_SEMI);
@@ -865,25 +894,27 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv)
                 else if (at->a_w.w_index > 0 && at->a_w.w_index <= argc)
                     *msp = argv[at->a_w.w_index-1];
                 else if (at->a_w.w_index == 0)
-                    SETFLOAT(msp, canvas_getdollarzero());
+                    SETFLOAT(msp, canvas_getdollarzero(init_target));
                 else
                 {
                     if (target == &pd_objectmaker)
                         SETFLOAT(msp, 0);
                     else
                     {
-                        error("$%d: argument number out of range",
+                        binbuf_error(init_target,
+                            "$%d: argument number out of range",
                             at->a_w.w_index);
                         SETFLOAT(msp, 0);
                     }
                 }
                 break;
             case A_DOLLSYM:
-                s9 = binbuf_realizedollsym(at->a_w.w_symbol, argc, argv,
-                    target == &pd_objectmaker);
+                s9 = binbuf_dorealizedollsym(init_target, at->a_w.w_symbol,
+                    argc, argv, target == &pd_objectmaker);
                 if (!s9)
                 {
-                    error("%s: argument number out of range",
+                    binbuf_error(init_target,
+                        "%s: argument number out of range",
                         at->a_w.w_symbol->s_name);
                     SETSYMBOL(msp, at->a_w.w_symbol);
                 }
diff --git a/pd/src/x_text.c b/pd/src/x_text.c
index f8e1a9b3fdab096dde5125b32348190e1eb11b80..4c2f99f63aff4b13a9dd7178e328605edd5343ef 100644
--- a/pd/src/x_text.c
+++ b/pd/src/x_text.c
@@ -1355,7 +1355,7 @@ static void text_sequence_doit(t_text_sequence *x, int argc, t_atom *argv)
     if (i >= n)
         i = 0x7fffffff;
     x->x_onset = i;
-        /* generate output list, realizing dolar sign atoms.  Allocate one
+        /* generate output list, realizing dollar sign atoms.  Allocate one
         extra atom in case we want to prepend a symbol later */
     ATOMS_ALLOCA(outvec, nfield+1);
     for (i = 0, ap = vec+onset; i < nfield; i++, ap++)