diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index a6c521471285330ad7601358092bc004a505b058..fadc9f7e20e6583979c9dd089d6e0de588272b1e 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -357,6 +357,15 @@ void canvasgop__motionhook(t_scalehandle *sh,t_floatarg f1, t_floatarg f2);
     tells us which.) */
 t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv)
 {
+    /* DEBUG
+    int d;
+    for (d=0; d < argc; d++)
+    {
+        if (argv[d].a_type == A_FLOAT)
+            fprintf(stderr, " %g ", argv[d].a_w.w_float);
+        else fprintf(stderr, " %s ", argv[d].a_w.w_symbol->s_name);
+    }
+    fprintf(stderr,"\n");*/
     t_canvas *x = (t_canvas *)pd_new(canvas_class);
     t_canvas *owner = canvas_getcurrent();
     t_symbol *s = &s_;
@@ -1047,6 +1056,7 @@ void canvas_objfor(t_glist *gl, t_text *x, int argc, t_atom *argv);
 void canvas_restore(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
 {
     t_pd *z;
+    //fprintf(stderr,"canvas_restore %lx\n", x);
     /* for [group] we add an inlet to the svg attr proxy */
     if (argc > 2 && argv[2].a_w.w_symbol == gensym("group"))
     {
@@ -1868,10 +1878,12 @@ int canvas_open(t_canvas *x, const char *name, const char *ext,
     return(result);
 }
 
+extern t_symbol *last_typedmess; // see g_readwrite.c for the explanation of this ugly hack
+
 static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
 {
     static int warned;
-    //fprintf(stderr,"canvas_f .x%lx\n", (t_int)x);
+    //fprintf(stderr,"canvas_f %lx %d current=%lx %s\n", (t_int)x, argc, canvas_getcurrent(), last_typedmess != NULL ? last_typedmess->s_name : "none");
     t_canvas *xp = x; //parent window for a special case dealing with subpatches
     t_gobj *g, *g2;
     t_object *ob;
@@ -1880,10 +1892,12 @@ static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         post("** ignoring width or font settings from future Pd version **");
         warned = 1;
     }
-    if (!x->gl_list) {
+    // if we are either an empty canvas or are a part of a restore message of a subpatch
+    if (!x->gl_list || !strcmp(last_typedmess->s_name, "restore")) {
         if (x->gl_owner && !x->gl_isgraph) {
-            // this means that we are a canvas that was just created
-            // and that our width applies to our appearance on our parent
+            // this means that we are a canvas that was just created or have just
+            // fnished restoring and that our width applies to our appearance on
+            // our parent
             xp = x->gl_owner;
             for (g = xp->gl_list; g != (t_gobj *)x; g = g->g_next) {
                 //fprintf(stderr,".x%lx .x%lx\n", (t_int)g, (t_int)x);
@@ -1894,6 +1908,7 @@ static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
     } else {
     for (g = x->gl_list; g2 = g->g_next; g = g2)
         ;
+        //fprintf(stderr,"same canvas .x%lx .x%lx\n", (t_int)g, (t_int)x);
     }
     //fprintf(stderr,"is canvas_class? %d\n", (pd_class(&g->g_pd) == canvas_class ? 1:0));
     if ((ob = pd_checkobject(&g->g_pd)) || pd_class(&g->g_pd) == canvas_class)
@@ -1904,6 +1919,7 @@ static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         {
             gobj_vis(g, xp, 0);
             gobj_vis(g, xp, 1);
+            gobj_select(g, xp, 1);
         }
     }
 }
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 4fab6b9919e40efac452b52a3011dfeec99cad3d..1a81ba19ec2ac2519ad58c835eb85b64e1eaf939 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -4767,6 +4767,7 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
     if (av[1].a_type == A_SYMBOL)
     {
         gotkeysym = av[1].a_w.w_symbol;
+        //fprintf(stderr,"gotkeysym=%s\n", gotkeysym->s_name);
     }
     else if (av[1].a_type == A_FLOAT)
     {
@@ -4854,14 +4855,11 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
             || !strcmp(gotkeysym->s_name, "Down")
             || !strcmp(gotkeysym->s_name, "Left")
             || !strcmp(gotkeysym->s_name, "Right")
-            || !strcmp(gotkeysym->s_name, "CtrlLeft")
-            || !strcmp(gotkeysym->s_name, "CtrlRight")
-            || !strcmp(gotkeysym->s_name, "ShiftLeft")
-            || !strcmp(gotkeysym->s_name, "ShiftRight")
-            || !strcmp(gotkeysym->s_name, "CtrlShiftLeft")
-            || !strcmp(gotkeysym->s_name, "CtrlShiftRight")
             || !strcmp(gotkeysym->s_name, "Home")
-            || !strcmp(gotkeysym->s_name, "End")))
+            || !strcmp(gotkeysym->s_name, "End")
+            || !strncmp("Ctrl", gotkeysym->s_name, 4)
+            || !strncmp("CtrlShift", gotkeysym->s_name, 9)
+            || !strncmp("Shift", gotkeysym->s_name, 5)))
         {
                 /* send the key to the box's editor */
             /*if (!x->gl_editor->e_textdirty)
diff --git a/pd/src/g_readwrite.c b/pd/src/g_readwrite.c
index c02fddfc364ec9505bdbd1acd5467b70a387bede..c0c8be9ad7001a94fc40cfd94e7125ff46ce30c3 100644
--- a/pd/src/g_readwrite.c
+++ b/pd/src/g_readwrite.c
@@ -615,6 +615,7 @@ static void canvas_saveto(t_canvas *x, t_binbuf *b)
     if (x->gl_owner && !x->gl_env)
     {
         /* have to go to original binbuf to find out how we were named. */
+        //fprintf(stderr,"saving subpatch\n");
         t_binbuf *bz = binbuf_new();
         t_symbol *patchsym;
         binbuf_addbinbuf(bz, x->gl_obj.ob_binbuf);
@@ -627,6 +628,7 @@ static void canvas_saveto(t_canvas *x, t_binbuf *b)
             (int)(x->gl_screeny2 - x->gl_screeny1),
             (patchsym != &s_ ? patchsym: gensym("(subpatch)")),
             x->gl_mapped);
+        t_text *xt = (t_text *)x;
     }
         /* root or abstraction */
     else 
diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c
index c93747ce1ad7bef3bf61ef5217e4ee7c4b62e80e..6b72a1f6150ecabe402773791b7aef16072e8912 100644
--- a/pd/src/g_rtext.c
+++ b/pd/src/g_rtext.c
@@ -512,11 +512,15 @@ void rtext_select(t_rtext *x, int state)
 
 void rtext_activate(t_rtext *x, int state)
 {
+    //fprintf(stderr,"rtext_activate\n");
     int w = 0, h = 0, indx;
     t_glist *glist = x->x_glist;
     t_canvas *canvas = glist_getcanvas(glist);
     //if (state && x->x_active) printf("duplicate rtext_activate\n");
-    if (state == x->x_active) return; // avoid excess calls
+    // the following prevents from selecting all when inside an
+    // object that is already being text for... please *test*
+    // "fixes" before committing them
+    //if (state == x->x_active) return; // avoid excess calls
     if (state)
     {
         sys_vgui(".x%lx.c focus %s\n", canvas, x->x_tag);
@@ -549,6 +553,7 @@ static int rtext_compare_special_chars(const char c)
 
 void rtext_key(t_rtext *x, int keynum, t_symbol *keysym)
 {
+    //fprintf(stderr,"rtext_key %d %s\n", keynum, keysym->s_name);
     int w = 0, h = 0, indx, i, newsize, ndel;
     if (keynum)
     {
@@ -697,6 +702,20 @@ be printable in whatever 8-bit character set we find ourselves. */
         x->x_selend = x->x_selstart;
         last_sel = 0;
     }
+    else if (!strcmp(keysym->s_name, "ShiftHome"))
+    {
+        if (x->x_selstart)
+        {
+            if (last_sel == 2)
+                x->x_selend = x->x_selstart;
+            u8_dec(x->x_buf, &x->x_selstart);
+            last_sel = 1;
+        }
+        while (x->x_selstart > 0 && x->x_buf[x->x_selstart] != '\n')
+            u8_dec(x->x_buf, &x->x_selstart);
+        //x->x_selend = x->x_selstart;
+        //last_sel = 1;
+    }
     else if (!strcmp(keysym->s_name, "End"))
     {
         while (x->x_selend < x->x_bufsize &&
@@ -707,6 +726,20 @@ be printable in whatever 8-bit character set we find ourselves. */
         x->x_selstart = x->x_selend;
         last_sel = 0;
     }
+    else if (!strcmp(keysym->s_name, "ShiftEnd"))
+    {
+        if (last_sel == 1)
+            x->x_selstart = x->x_selend;
+        while (x->x_selend < x->x_bufsize &&
+            x->x_buf[x->x_selend] != '\n')
+            u8_inc(x->x_buf, &x->x_selend);
+        if (x->x_selend < x->x_bufsize)
+        {
+            u8_inc(x->x_buf, &x->x_selend);
+        }
+        //x->x_selstart = x->x_selend;
+        last_sel = 2;
+    }
     else if (!strcmp(keysym->s_name, "CtrlLeft"))
     {
         /* first find first non-space char going back */
diff --git a/pd/src/m_class.c b/pd/src/m_class.c
index 7d1c4779e513a84837b8541c6de6120689f98427..5678a92e3761d9e7eb1dc5c5cf7b6236477d6860 100644
--- a/pd/src/m_class.c
+++ b/pd/src/m_class.c
@@ -660,7 +660,7 @@ t_symbol  s__X =        {"#X", 0, 0};
 t_symbol  s_x =         {"x", 0, 0};
 t_symbol  s_y =         {"y", 0, 0};
 t_symbol  s_ =          {"", 0, 0};
-t_symbol  s_blob =    {"blob", 0, 0}; /* MP 20061223 blob type */
+t_symbol  s_blob =      {"blob", 0, 0}; /* MP 20061223 blob type */
 
 static t_symbol *symlist[] = { &s_pointer, &s_float, &s_symbol, &s_bang,
     &s_list, &s_anything, &s_signal, &s__N, &s__X, &s_x, &s_y, &s_, &s_blob}; /* MP 20061223 added s_blob */
@@ -713,6 +713,12 @@ typedef t_pd *(*t_fun6)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, t_int
 /* needed for proper error reporting */
 extern t_pd *pd_mess_from_responder(t_pd *x);
 
+// hackish way to figure out what was the last command we invoked so that commands
+// that follow it (via commas, like the new width ability), can understand whom
+// they belong to. This is a problem with subpatches whose values get assigned to
+// their last created object, as opposed themselves
+t_symbol *last_typedmess;
+
 void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
 {
     t_class *c = *x;
@@ -724,7 +730,7 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
     int narg = 0;
     t_pd *bonzo;
     
-    //fprintf(stderr,"\nstart %s %d\n", s->s_name, c->c_nmethod);
+    //fprintf(stderr,"pd_typedmess: %s %d\n", s->s_name, c->c_nmethod);
 
         /* check for messages that are handled by fixed slots in the class
         structure.  We don't catch "pointer" though so that sending "pointer"
@@ -735,17 +741,17 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
         else if (argv->a_type == A_FLOAT)
             (*c->c_floatmethod)(x, argv->a_w.w_float);
         else goto badarg;
-        return;
+        goto lastmess;
     }
     if (s == &s_bang)
     {
         (*c->c_bangmethod)(x);
-        return;
+        goto lastmess;
     }
     if (s == &s_list)
     {
         (*c->c_listmethod)(x, s, argc, argv);
-        return;
+        goto lastmess;
     }
     if (s == &s_symbol)
     {
@@ -753,14 +759,14 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
             (*c->c_symbolmethod)(x, argv->a_w.w_symbol);
         else
             (*c->c_symbolmethod)(x, &s_);
-        return;
+        goto lastmess;
     }
     if (s == &s_blob) /* MP 20061226 blob type */
     {
         /*post("pd_typedmess argc = %d\n", argc);*//* MP 20061226 debug */
         if (argc == 1) (*c->c_blobmethod)(x, argv->a_w.w_blob);
         else goto badarg;
-        return;
+        goto lastmess;
     }
     for (i = c->c_nmethod, m = c->c_methods; i--; m++)
     {
@@ -774,7 +780,7 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
                 if (x == &pd_objectmaker)
                     newest = (*((t_newgimme)(m->me_fun)))(s, argc, argv);
                 else (*((t_messgimme)(m->me_fun)))(x, s, argc, argv);
-                return;
+                goto lastmess;
             }
             if (argc > MAXPDARG) argc = MAXPDARG;
             if (x != &pd_objectmaker) *(ap++) = (t_int)x, narg++;
@@ -874,11 +880,11 @@ void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
             }
             if (x == &pd_objectmaker)
                 newest = bonzo;
-            return;
+            goto lastmess;
         }
     }
     (*c->c_anymethod)(x, s, argc, argv);
-    return;
+    goto lastmess;
 badarg:
     /* if x is a messresponder class, tweak it to point to the
        message that contains it (so it can be selected when 'Find
@@ -886,6 +892,9 @@ badarg:
     x = pd_mess_from_responder(x);
     pd_error(x, "Bad arguments for message '%s' to object '%s'",
         s->s_name, c->c_name->s_name);
+lastmess:
+    last_typedmess = s;    
+    return;
 }
 
     /* convenience routine giving a stdarg interface to typedmess().  Only
diff --git a/pd/src/pd.tk b/pd/src/pd.tk
index f3a9daae5c309c2e04120831d78c2b6b3e02887a..48748edaa0284a29b24a7a1d17e2021ae8e6af77 100644
--- a/pd/src/pd.tk
+++ b/pd/src/pd.tk
@@ -4646,41 +4646,28 @@ proc pdtk_canvas_sendkey {name state key iso shift focus serial} {
 
 	#puts stderr "shift=$shift ctrl=$ctrl key=$key"
 
-	#if {[string match Home $key] && $ctrl} {
-	#	set key "CtrlHome"
-	#	set state 1
-	#}
-
-	#if {[string match End $key] && $ctrl} {
-	#	set key "CtrlEnd"
-	#	set state 1
-	#}
-
-	if {[string match Left $key]} {
-		if {$ctrl == 1 && $shift == 0} {
-			set key "CtrlLeft"
-			set state 1
-		}
-		if {$ctrl == 0 && $shift == 1} {
-			set key "ShiftLeft"
-		}
-		if {$ctrl == 1 && $shift == 1} {
-			set key "CtrlShiftLeft"
-			set state 1
-		}
-	}
-
-	if {[string match Right $key]} {
-		if {$ctrl == 1 && $shift == 0} {
-			set key "CtrlRight"
-			set state 1
-		}
-		if {$ctrl == 0 && $shift == 1} {
-			set key "ShiftRight"
-		}
-		if {$ctrl == 1 && $shift == 1} {
-			set key "CtrlShiftRight"
-			set state 1
+	switch -- $key {
+		Left -
+		Right -
+		Up -
+		Down -
+		Home -
+		End -
+		Next -
+		Prior {
+			if {$ctrl == 1 && $shift == 0} {
+				set key "Ctrl$key"
+				set state 1
+			}
+			if {$ctrl == 0 && $shift == 1} {
+				set key "Shift$key"
+				#set state 1 (this results in a double press)
+			}
+			if {$ctrl == 1 && $shift == 1} {
+				set key "CtrlShift$key"
+				set state 1
+			}
+			#puts stderr "outcome=$key"
 		}
 	}