diff --git a/pd/src/g_canvas.c b/pd/src/g_canvas.c
index dd92ecc0398026cb73304096a9f56d4ace92295f..d86b4bba66cd529d4ed80b8a13d22379fccb2efe 100644
--- a/pd/src/g_canvas.c
+++ b/pd/src/g_canvas.c
@@ -1778,6 +1778,31 @@ int canvas_open(t_canvas *x, const char *name, const char *ext,
 	return(result);
 }
 
+static void canvas_f(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
+{
+    static int warned;
+    t_gobj *g, *g2;
+    t_object *ob;
+    if (argc > 1 && !warned)
+    {
+        post("** ignoring width or font settings from future Pd version **");
+        warned = 1;
+    }
+    if (!x->gl_list)
+        return;
+    for (g = x->gl_list; g2 = g->g_next; g = g2)
+        ;
+    if (ob = pd_checkobject(&g->g_pd))
+    {
+        ob->te_width = atom_getfloatarg(0, argc, argv);
+        if (glist_isvisible(x))
+        {
+            gobj_vis(g, x, 0);
+            gobj_vis(g, x, 1);
+        }
+    }
+}
+
 void canvasgop_draw_move(t_canvas *x, int doit)
 {
 	//delete the earlier GOP window so that when dragging 
@@ -2131,6 +2156,9 @@ void g_canvas_setup(void)
     class_addmethod(canvas_class, (t_method)canvas_declare,
         gensym("declare"), A_GIMME, 0);
 
+/*--------------- future message to set formatting  -------------- */
+    class_addmethod(canvas_class, (t_method)canvas_f,
+        gensym("f"), A_GIMME, 0);
 /* -------------- setups from other files for canvas_class ---------------- */
     g_graph_setup();
     g_editor_setup();
diff --git a/pd/src/g_canvas.h b/pd/src/g_canvas.h
index 47781baac80bc3ff0ae97c99b92cbdaa3c76ba96..8c442374f5e05e0c2c641228ae17c3f567669760 100644
--- a/pd/src/g_canvas.h
+++ b/pd/src/g_canvas.h
@@ -124,6 +124,9 @@ typedef struct _editor
     t_magicGlass *gl_magic_glass;   /* magic glass object */
 	char canvas_cnct_inlet_tag[4096]; /* tags for currently highlighted nlets */
 	char canvas_cnct_outlet_tag[4096];
+    t_clock *e_clock;               /* clock to filter GUI move messages */
+    int e_xnew;                     /* xpos for next move event */
+    int e_ynew;                     /* ypos, similarly */
 } t_editor;
 
 #define MA_NONE    0    /* e_onmotion: do nothing on mouse motion */
@@ -132,6 +135,7 @@ typedef struct _editor
 #define MA_REGION  3    /* selection region */
 #define MA_PASSOUT 4    /* send on to e_grab */
 #define MA_DRAGTEXT 5   /* drag in text editor to alter selection */
+#define MA_RESIZE  6    /* drag to resize */
 
 /* editor structure for "garrays".  We don't bother to delete and regenerate
 this structure when the "garray" becomes invisible or visible, although we
@@ -384,6 +388,8 @@ struct _parentwidgetbehavior
 #define CURSOR_EDITMODE_NOTHING 4
 #define CURSOR_EDITMODE_CONNECT 5
 #define CURSOR_EDITMODE_DISCONNECT 6
+#define CURSOR_EDITMODE_RESIZE 7
+#define CURSOR_EDITMODE_RESIZE_BOTTOM_RIGHT 8
 EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);
 
 extern t_canvas *canvas_editing;    /* last canvas to start text edting */ 
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 0728564ba7ee4fc13db040b1b9c4fad52c901f26..ce3d0ab94bc86d87836d86ce14ba247c54a69b02 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -1966,7 +1966,9 @@ static char *cursorlist[] = {
     "$cursor_runmode_addpoint",
     "$cursor_editmode_nothing",
     "$cursor_editmode_connect",
-    "$cursor_editmode_disconnect"
+    "$cursor_editmode_disconnect",
+    "$cursor_editmode_resize",
+    "$cursor_editmode_resize_bottom_right"
 };
 
 void canvas_setcursor(t_canvas *x, unsigned int cursornum)
@@ -2835,8 +2837,36 @@ void canvas_doclick(t_canvas *x, int xpos, int ypos, int which,
                 /* look for an outlet we just clicked onto */
             int noutlet;
 			int ninlet;
-			// if object is valid, has outlets, and we are within the bottom area of an object
-            if (ob && (noutlet = obj_noutlets(ob)) && ypos >= y2-4)
+                /* resize?  only for "true" text boxes or canvases*/
+            if (!sys_k12_mode && ob && !x->gl_editor->e_textedfor &&
+                (ob->te_pd->c_wb == &text_widgetbehavior ||
+                    ob->ob_pd == canvas_class) &&
+                        xpos >= x2-4 && ypos < y2-4)
+            {
+                if (doit)
+                {
+                    if (!glist_isselected(x, y))
+                    {
+                        glist_noselect(x);
+                        glist_select(x, y);
+                    }
+                    x->gl_editor->e_onmotion = MA_RESIZE;
+                    x->gl_editor->e_xwas = x1;
+                    x->gl_editor->e_ywas = y1;
+                    x->gl_editor->e_xnew = xpos;
+                    x->gl_editor->e_ynew = ypos;
+					canvas_undo_add(x, 6, "resize", canvas_undo_set_apply(x, glist_getindex(x, y)));
+                }                                   
+                else {
+					if (ob->ob_pd != canvas_class || !((t_canvas *)ob)->gl_isgraph)
+						canvas_setcursor(x, CURSOR_EDITMODE_RESIZE);
+					else canvas_setcursor(x, CURSOR_EDITMODE_RESIZE_BOTTOM_RIGHT);
+					canvas_check_nlet_highlights(x);
+				}
+            }
+                /* look for an outlet */
+				// if object is valid, has outlets, and we are within the bottom area of an object
+            else if (ob && (noutlet = obj_noutlets(ob)) && ypos >= y2-4)
             {
                 int width = x2 - x1;
                 int nout1 = (noutlet > 1 ? noutlet - 1 : 1);
@@ -3990,9 +4020,11 @@ void canvas_mouseup(t_canvas *x,
         canvas_doconnect(x, xpos, ypos, which, 1);
     else if (x->gl_editor->e_onmotion == MA_REGION)
         canvas_doregion(x, xpos, ypos, 1);
-    else if (x->gl_editor->e_onmotion == MA_MOVE)
+    else if (x->gl_editor->e_onmotion == MA_MOVE ||
+        x->gl_editor->e_onmotion == MA_RESIZE)
     {
-            /* after motion, if there's only one item selected, activate it */
+            /* after motion or resizing, if there's only one text item
+                selected, activate the text */
         if (x->gl_editor->e_selection &&
             !(x->gl_editor->e_selection->sel_next))
         {
@@ -4330,6 +4362,8 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
             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_xnew = xpos;
+        x->gl_editor->e_ynew = ypos;
 		//sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
 		//sys_vgui("pdtk_check_scroll_on_motion .x%lx.c 20\n", x);  
     }
@@ -4358,6 +4392,44 @@ void canvas_motion(t_canvas *x, t_floatarg xpos, t_floatarg ypos,
             rtext_mouse(rt, xpos - x->gl_editor->e_xwas,
                 ypos - x->gl_editor->e_ywas, RTEXT_DRAG);
     }
+    else if (x->gl_editor->e_onmotion == MA_RESIZE)
+    {
+        int x11=0, y11=0, x12=0, y12=0; 
+        t_gobj *y1;
+        if (y1 = canvas_findhitbox(x,
+            x->gl_editor->e_xwas, x->gl_editor->e_ywas,
+                &x11, &y11, &x12, &y12))
+        {
+            int wantwidth = xpos - x11;
+            t_gotfn sizefn;
+            t_object *ob = pd_checkobject(&y1->g_pd);
+            if (ob && ob->te_pd->c_wb == &text_widgetbehavior ||
+                    (ob->ob_pd == canvas_class &&
+                        !((t_canvas *)ob)->gl_isgraph))
+            {
+                wantwidth = wantwidth / sys_fontwidth(glist_getfont(x));
+                if (wantwidth < 1)
+                    wantwidth = 1;
+                ob->te_width = wantwidth;
+                gobj_vis(y1, x, 0);
+                canvas_fixlinesfor(x, ob);
+                gobj_vis(y1, x, 1);
+				canvas_dirty(x, 1);
+            }
+            else if (ob && ob->ob_pd == canvas_class)
+            {
+                gobj_vis(y1, x, 0);
+                ((t_canvas *)ob)->gl_pixwidth += xpos - x->gl_editor->e_xnew;
+                ((t_canvas *)ob)->gl_pixheight += ypos - x->gl_editor->e_ynew;
+                x->gl_editor->e_xnew = xpos;
+                x->gl_editor->e_ynew = ypos;
+                canvas_fixlinesfor(x, ob);
+                gobj_vis(y1, x, 1);
+				canvas_dirty(x, 1);
+            }
+            else post("not resizable");
+        }
+    }
     else canvas_doclick(x, xpos, ypos, 0, mod, 0);
 	//if (toggle_moving == 1) {
 	//	sys_vgui("pdtk_update_xy_tooltip .x%lx %d %d\n", x, (int)xpos, (int)ypos);
diff --git a/pd/src/g_graph.c b/pd/src/g_graph.c
index a29c3f33a71bbcfc3ce80593e9075ff3e7ea8660..4134ce4138e8b09450aa0a7636048cd38978c620 100644
--- a/pd/src/g_graph.c
+++ b/pd/src/g_graph.c
@@ -1005,24 +1005,35 @@ void graph_checkgop_rect(t_gobj *z, t_glist *glist,
 
 	//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;
+	if (!x->gl_hidetext) {
+		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;
+	} else {
+		// failsafe where we cannot have a gop that is smaller than 1x1 pixels
+		// when the text is hidden
+		int in = obj_ninlets(pd_checkobject(&z->g_pd)) * IOWIDTH;
+		int out = obj_noutlets(pd_checkobject(&z->g_pd)) * IOWIDTH;
+		int minhsize = (in >= out ? in : out);
+		int minvsize = ((in > 0 ? 1 : 0) + (out > 0 ? 1 : 0)) * 2 + 6;
+		if (*xp2 < *xp1+minhsize) *xp2 = *xp1+minhsize;
+		if (*yp2 < *yp1+minvsize) *yp2 = *yp1+minvsize;
+	}
 }
 
     /* get the rectangle, enlarged to contain all the "contents" --
@@ -1080,9 +1091,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
 		//fprintf(stderr,"%d %d %d %d\n", x1, y1, x2, y2);
 
 		// check if the text is not hidden and if so use that as the limit of the gop's size
-		if (!x->gl_hidetext) {
-			graph_checkgop_rect(z, glist, &x1, &y1, &x2, &y2);
-		}
+		graph_checkgop_rect(z, glist, &x1, &y1, &x2, &y2);
 
 		/* fix visibility of edge items for garrays */
 		int has_garray = 0;
diff --git a/pd/src/g_rtext.c b/pd/src/g_rtext.c
index ebde12b90ee7b60c61e49f0269616369287831dc..9a8a443f38bd81232f2b0b18821f916bd7e82292 100644
--- a/pd/src/g_rtext.c
+++ b/pd/src/g_rtext.c
@@ -166,7 +166,7 @@ static int lastone(char *s, int c, int n)
         SEND_FIRST - draw the box  for the first time
         SEND_UPDATE - redraw the updated box
         otherwise - don't draw, just calculate.
-    Called with *widthp and *heightpas coordinates of
+    Called with *widthp and *heightp as coordinates of
     a test point, the routine reports the index of the character found
     there in *indexp.  *widthp and *heightp are set to the width and height
     of the entire text in pixels.
@@ -196,7 +196,7 @@ extern int sys_oldtclversion;
 static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
     int *indexp)
 {
-	//fprintf(stderr,"rtext_senditup %d %d\n", *widthp, *heightp);
+	//fprintf(stderr,"rtext_senditup <%s>\n", x->x_buf);
 	if (x) {
 		t_float dispx, dispy;
 		char smallbuf[200], *tempbuf;
@@ -204,9 +204,9 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
 		    pixwide, pixhigh, font, fontwidth, fontheight, findx, findy;
 		int reportedindex = 0;
 		t_canvas *canvas = glist_getcanvas(x->x_glist);
-
 		int widthspec_c = x->x_text->te_width; // width if any specified
 		int widthlimit_c = (widthspec_c ? widthspec_c : BOXWIDTH); // width limit in chars
+		//fprintf(stderr,"senditup widthlimit_c %d %d\n", widthspec_c, widthlimit_c);
 		int inindex_b = 0; // index location in the buffer
 		int inindex_c = 0; // index location in the u8 chars
 		int selstart_b = 0, selend_b = 0; // selection start and end
@@ -233,18 +233,20 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
 			int maxindex_b = u8_offset(x->x_buf + inindex_b, maxindex_c);
 		    int eatchar = 1;
 			int foundit_b  = firstone(x->x_buf + inindex_b, '\n', maxindex_b);
-
+			int foundit_c;
 			//following deals with \v replacement for \n in multiline comments
 			int foundit_bv  = firstone(x->x_buf + inindex_b, '\v', maxindex_b);
 			//fprintf(stderr,"%d %d <%s>\n", foundit_b, foundit_bv, x->x_buf);
 			if ((foundit_bv < foundit_b && foundit_bv != -1) || (foundit_b == -1 && foundit_bv != -1)) foundit_b = foundit_bv;
-
-			int foundit_c;
 			if (foundit_b < 0) //if we did not find an \n
 		    { 
+                /* too much text to fit in one line? */
 		        if (inchars_c > widthlimit_c)
 		        {
-					foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b);
+                    /* is there a space to break the line at?  OK if it's even
+                    one byte past the end since in this context we know there's
+                    more text */
+					foundit_b = lastone(x->x_buf + inindex_b, ' ', maxindex_b + 1);
 					if (foundit_b < 0)
 		            {
 						foundit_b = maxindex_b;
@@ -295,7 +297,7 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
 		if (nlines < 1) nlines = 1;
 		if (!widthspec_c)
 		{
-		    while (ncolumns < 3)
+		    while (ncolumns < (x->x_text->te_type == T_TEXT ? 1 : 3))
 		    {
 		        tempbuf[outchars_b++] = ' ';
 		        ncolumns++;
@@ -305,6 +307,21 @@ static void rtext_senditup(t_rtext *x, int action, int *widthp, int *heightp,
 		pixwide = ncolumns * fontwidth + (LMARGIN + RMARGIN);
 		pixhigh = nlines * fontheight + (TMARGIN + BMARGIN);
 
+	    if (action && x->x_text->te_width && x->x_text->te_type != T_ATOM)
+	    {
+	            /* if our width is specified but the "natural" width is the
+	            same as the specified width, set specified width to zero
+	            so future text editing will automatically change width.
+	            Except atoms whose content changes at runtime. */
+	        int widthwas = x->x_text->te_width, newwidth = 0, newheight = 0,
+	            newindex = 0;
+	        x->x_text->te_width = 0;
+	        rtext_senditup(x, 0, &newwidth, &newheight, &newindex);
+	        if (newwidth/fontwidth != widthwas)
+	            x->x_text->te_width = widthwas;
+	        else x->x_text->te_width = 0;
+			//fprintf(stderr,"senditup width %d %d %d\n", newwidth/fontwidth, widthwas, x->x_text->te_width);
+	    }
 		if (action == SEND_FIRST) {
 			//fprintf(stderr,"canvas=.x%lx %s\n", (t_int)canvas, tempbuf);
 		    sys_vgui("pdtk_text_new .x%lx.c {%s %s text} %f %f {%.*s} %d %s\n",
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index e68258deb5207c1b4032266465e9e3893aa5fe56..aa4879748479b8ea280f820e9abed4cc5e783569 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -625,7 +625,16 @@ static void message_free(t_message *x)
 
 void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 {
-	//fprintf(stderr,"canvas_msg\n");
+	/*fprintf(stderr,"canvas_msg\n");
+	int i = 0;
+	while(i < argc) {
+		if (argv[i].a_type == A_FLOAT)
+			fprintf(stderr," %f", atom_getfloatarg(i, argc, argv));
+		else
+			fprintf(stderr," %s", atom_getsymbolarg(i, argc, argv)->s_name);
+		i++;
+	}
+	fprintf(stderr,"\n");*/
     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);
@@ -1240,6 +1249,7 @@ static void text_getrect(t_gobj *z, t_glist *glist,
     {
         t_rtext *y = glist_findrtext(glist, x);
         width = rtext_width(y);
+		height = rtext_height(y) - (iscomment << 1);
 
 		//fprintf(stderr,"rtext_width=%d\n", width);
 
@@ -1555,7 +1565,6 @@ void text_save(t_gobj *z, t_binbuf *b)
 		//fprintf(stderr, "this must be it\n");
         binbuf_addbinbuf(b, x->te_binbuf);
 		//fprintf(stderr, "DONE this must be it\n");
-        binbuf_addv(b, ";");
     }
     else if (x->te_type == T_MESSAGE)
     {
@@ -1563,7 +1572,6 @@ void text_save(t_gobj *z, t_binbuf *b)
         binbuf_addv(b, "ssii", gensym("#X"), gensym("msg"),
             (int)x->te_xpix, (int)x->te_ypix);
         binbuf_addbinbuf(b, x->te_binbuf);
-        binbuf_addv(b, ";");
     }
     else if (x->te_type == T_ATOM)
     {
@@ -1580,7 +1588,6 @@ void text_save(t_gobj *z, t_binbuf *b)
             (double)((t_gatom *)x)->a_draghi,
             (double)((t_gatom *)x)->a_wherelabel,
             label, symfrom, symto);
-        binbuf_addv(b, ";");
     }           
     else    
     {
@@ -1609,8 +1616,10 @@ void text_save(t_gobj *z, t_binbuf *b)
         binbuf_addv(b, "ssii", gensym("#X"), gensym("text"),
             (int)x->te_xpix, (int)x->te_ypix);
         binbuf_addbinbuf(b, x->te_binbuf);
-        binbuf_addv(b, ";");
     }
+    if (x->te_width)
+        binbuf_addv(b, ",si", gensym("f"), (int)x->te_width);
+    binbuf_addv(b, ";");
 }
 
     /* this one is for everyone but "gatoms"; it's imposed in m_class.c */
@@ -1841,48 +1850,33 @@ void text_drawborder(t_text *x, t_glist *glist,
     }
     else if (x->te_type == T_MESSAGE)
     {
-        msg_draw_const = ((y2-y1)/4);
-        if (msg_draw_const > 10) msg_draw_const = 10; /* looks bad if too big */
         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 text}\n",
+            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 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,  
+                x1, y1,  x2+4, y1,  x2, y1+4,  x2, y2-4,  x2+4, y2,
                 x1, y2,  x1, y1,
-                    tag);	
-        }
+                    tag);
         else
-        {
             sys_vgui(".x%lx.c coords %sR\
  %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
                 glist_getcanvas(glist), tag,
-                x1, y1,  x2+msg_draw_const, y1,  x2, y1+msg_draw_const,
-                x2, y2-msg_draw_const, x2+msg_draw_const, y2,  x1, y2,  x1, y1);
-        }
+                x1, y1,  x2+4, y1,  x2, y1+4,  x2, y2-4,  x2+4, y2,
+                x1, y2,  x1, y1);
     }
     else if (x->te_type == T_ATOM)
     {
-        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 text}\n",
+            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 text}\n",
                 glist_getcanvas(glist),
-                     x1, y1,  x2-atom_draw_const, y1,  x2, y1+atom_draw_const,  
-                     x2, y2,  x1, y2,  x1, y1, 
+                x1, y1,  x2-4, y1,  x2, y1+4,  x2, y2,  x1, y2,  x1, y1,
                     tag);
-         }
-         else
-         {
+        else
             sys_vgui(".x%lx.c coords %sR\
  %d %d %d %d %d %d %d %d %d %d %d %d\n",
                 glist_getcanvas(glist), tag,
-                x1, y1,  x2-atom_draw_const, y1,  x2, y1+atom_draw_const,
-                x2, y2,  x1, y2,  x1, y1);
-         }
+                x1, y1,  x2-4, y1,  x2, y1+4,  x2, y2,  x1, y2,  x1, y1);
     }
 
 	/* draw inlets/outlets */    
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index 219505e1ff509e27971d0a1d681552d4288696a0..255e1a48e558efee7a7f9cff95ab495b9205eb5c 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/src/m_binbuf.c
@@ -174,6 +174,11 @@ void binbuf_text(t_binbuf *x, char *text, size_t size)
                 	textp[0]=='@'))) /* JMZ: $@ and $# expansion */
                         dollar = 1;
                 if (!slash) bufp++;
+                else if (lastslash)
+                {
+                    bufp++;
+                    slash = 0;
+                }
             }
             while (textp != etext && bufp != ebuf && 
                 (slash || (*textp != ' ' && *textp != '\n' && *textp != '\r'
@@ -349,7 +354,8 @@ done:
 }
 
 /* add a binbuf to another one for saving.  Semicolons and commas go to
-symbols ";", "'",; the symbol ";" goes to "\;", etc. */
+symbols ";", "'",; We assume here (probably incorrectly) that there's
+no symbol whose name is ";" - should we be escaping those?. */
 
 void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
 {
@@ -391,10 +397,10 @@ void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y)
         case A_SYMBOL:
 			//fprintf(stderr,"addbinbuf: symbol\n");
                 /* FIXME make this general */
-            if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
+            /*if (!strcmp(ap->a_w.w_symbol->s_name, ";"))
                 SETSYMBOL(ap, gensym(";"));
             else if (!strcmp(ap->a_w.w_symbol->s_name, ","))
-                SETSYMBOL(ap, gensym(","));
+                SETSYMBOL(ap, gensym(","));*/
             break;
         default:
             bug("binbuf_addbinbuf");
@@ -462,6 +468,23 @@ void binbuf_restore(t_binbuf *x, int argc, t_atom *argv)
                     SETDOLLAR(ap, dollar);
                 }
             }
+            else if (strchr(argv->a_w.w_symbol->s_name, '\\'))
+            {
+                char buf[MAXPDSTRING], *sp1, *sp2;
+                int slashed = 0;
+                for (sp1 = buf, sp2 = argv->a_w.w_symbol->s_name;
+                    *sp2 && sp1 < buf + (MAXPDSTRING-1);
+                        sp2++)
+                {
+                    if (slashed)
+                        *sp1++ = *sp2;
+                    else if (*sp2 == '\\')
+                        slashed = 1;
+                    else *sp1++ = *sp2, slashed = 0;
+                }
+                *sp1 = 0;
+                SETSYMBOL(ap, gensym(buf));
+            }
             else *ap = *argv;
             argv++;
         }
@@ -504,6 +527,15 @@ t_atom *binbuf_getvec(t_binbuf *x)
     return (x->b_vec);
 }
 
+int binbuf_resize(t_binbuf *x, int newsize)
+{
+    t_atom *new = t_resizebytes(x->b_vec,
+        x->b_n * sizeof(*x->b_vec), newsize * sizeof(*x->b_vec));
+    if (new)
+        x->b_vec = new, x->b_n = newsize;
+    return (new != 0);
+}
+
 int canvas_getdollarzero( void);
 
 /* JMZ:
@@ -873,7 +905,7 @@ broken:
 
 static int binbuf_doopen(char *s, int mode)
 {
-    char namebuf[FILENAME_MAX];
+    char namebuf[MAXPDSTRING];
 #ifdef MSW
     mode |= O_BINARY;
 #endif
@@ -883,7 +915,7 @@ static int binbuf_doopen(char *s, int mode)
 
 static FILE *binbuf_dofopen(char *s, char *mode)
 {
-    char namebuf[FILENAME_MAX];
+    char namebuf[MAXPDSTRING];
     sys_bashfilename(s, namebuf);
     return (fopen(namebuf, mode));
 }
@@ -894,7 +926,7 @@ int binbuf_read(t_binbuf *b, char *filename, char *dirname, int crflag)
     int fd;
     int readret;
     char *buf;
-    char namebuf[FILENAME_MAX];
+    char namebuf[MAXPDSTRING];
     
     namebuf[0] = 0;
     if (*dirname)
@@ -947,9 +979,9 @@ int binbuf_read_via_canvas(t_binbuf *b, char *filename, t_canvas *canvas,
     int crflag)
 {
     int filedesc;
-    char buf[FILENAME_MAX], *bufptr;
+    char buf[MAXPDSTRING], *bufptr;
     if ((filedesc = canvas_open(canvas, filename, "",
-        buf, &bufptr, FILENAME_MAX, 0)) < 0)
+        buf, &bufptr, MAXPDSTRING, 0)) < 0)
     {
         error("%s: can't open", filename);
         return (1);
@@ -965,9 +997,9 @@ int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
     int crflag)
 {
     int filedesc;
-    char buf[FILENAME_MAX], *bufptr;
+    char buf[MAXPDSTRING], *bufptr;
     if ((filedesc = open_via_path(
-        dirname, filename, "", buf, &bufptr, FILENAME_MAX, 0)) < 0)
+        dirname, filename, "", buf, &bufptr, MAXPDSTRING, 0)) < 0)
     {
         error("%s: can't open", filename);
         return (1);
@@ -986,7 +1018,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd);
 int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
 {
     FILE *f = 0;
-    char sbuf[WBUFSIZE], fbuf[FILENAME_MAX], *bp = sbuf, *ep = sbuf + WBUFSIZE;
+    char sbuf[WBUFSIZE], fbuf[MAXPDSTRING], *bp = sbuf, *ep = sbuf + WBUFSIZE;
     t_atom *ap;
     int indx, deleteit = 0;
     int ncolumn = 0;
@@ -1053,6 +1085,14 @@ int binbuf_write(t_binbuf *x, char *filename, char *dir, int crflag)
         sys_unixerror(fbuf);
         goto fail;
     }
+
+
+    if (fflush(f) != 0) 
+    {
+        sys_unixerror(fbuf);
+        goto fail;
+    }
+
     if (deleteit)
         binbuf_free(x);
     fclose(f);
@@ -1128,7 +1168,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
                 {
                     if (stackdepth >= MAXSTACK)
                     {
-                        post("too many embedded patches");
+                        error("stack depth exceeded: too many embedded patches");
                         return (newb);
                     }
                     stack[stackdepth] = nobj;
@@ -1592,10 +1632,14 @@ void binbuf_evalfile(t_symbol *name, t_symbol *dir)
     glob_setfilename(0, name, dir);
     if (binbuf_read(b, name->s_name, dir->s_name, 0))
     {
-        perror(name->s_name);
+        error("%s: read failed", name->s_name);
     }
     else
     {
+            /* save bindings of symbols #N, #A (and restore afterward) */
+        t_pd *bounda = gensym("#A")->s_thing, *boundn = s__N.s_thing;
+        gensym("#A")->s_thing = 0;
+        s__N.s_thing = &pd_canvasmaker;
         if (import)
         {
             t_binbuf *newb = binbuf_convert(b, 1);
@@ -1603,13 +1647,15 @@ void binbuf_evalfile(t_symbol *name, t_symbol *dir)
             b = newb;
         }
         binbuf_eval(b, 0, 0, 0);
+        gensym("#A")->s_thing = bounda;
+        s__N.s_thing = boundn;
     }
     glob_setfilename(0, &s_, &s_);
     binbuf_free(b);
     canvas_resume_dsp(dspstate);
 }
 
-void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
+t_pd *glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
 {
     t_pd *x = 0;
         /* even though binbuf_evalfile appears to take care of dspstate,
@@ -1618,9 +1664,17 @@ void glob_evalfile(t_pd *ignore, t_symbol *name, t_symbol *dir)
         is still necessary -- probably not. */
 
     int dspstate = canvas_suspend_dsp();
+    t_pd *boundx = s__X.s_thing;
+        s__X.s_thing = 0;       /* don't save #X; we'll need to leave it bound
+                                for the caller to grab it. */
     binbuf_evalfile(name, dir);
-    while ((x != s__X.s_thing) && (x = s__X.s_thing))
+    while ((x != s__X.s_thing) && s__X.s_thing) 
+    {
+        x = s__X.s_thing;
         vmess(x, gensym("pop"), "i", 1);
+	}
     pd_doloadbang();
     canvas_resume_dsp(dspstate);
+	s__X.s_thing = boundx;
+	return x;
 }
diff --git a/pd/src/pd.tk b/pd/src/pd.tk
index b3f624a73ea93e82c376bc7d5b0fe04294b7a7a2..ae3dcd5b96e1d9ecb6326b9c53e4fffd2bca826c 100644
--- a/pd/src/pd.tk
+++ b/pd/src/pd.tk
@@ -204,6 +204,8 @@ if { $tcl_platform(platform) == "windows" }  {
     set cursor_editmode_nothing "hand2"
     set cursor_editmode_connect "circle"
     set cursor_editmode_disconnect "X_cursor"
+	set cursor_editmode_resize "sb_h_double_arrow"
+	set cursor_editmode_resize_bottom_right "bottom_right_corner"
 	# set file types that open/save recognize
 	set filetypes {
 		{{Pd Files}         {.pd}  }
@@ -230,6 +232,8 @@ if { $tcl_platform(platform) == "windows" }  {
     set cursor_editmode_nothing "hand2"
     set cursor_editmode_connect "circle"
     set cursor_editmode_disconnect "X_cursor"
+	set cursor_editmode_resize "sb_h_double_arrow"
+	set cursor_editmode_resize_bottom_right "bottom_right_corner"
 	# set file types that open/save recognize
 	set filetypes {
 		{{Pd Files}                {.pd}  }
@@ -262,6 +266,8 @@ if { $tcl_platform(platform) == "windows" }  {
     set cursor_editmode_nothing "hand2"
     set cursor_editmode_connect "target"
     set cursor_editmode_disconnect "X_cursor"
+	set cursor_editmode_resize "sb_h_double_arrow"
+	set cursor_editmode_resize_bottom_right "bottom_right_corner"
 	# set file types that open/save recognize
 	set filetypes {
 		{{pd files}         {.pd}  }