diff --git a/src/g_editor.c b/src/g_editor.c
index 3436937fa2dde9a517820772bcf548b861c0fb51..3d0bb10bacf9d0b7a9301918fd7af72cd7ffb3b0 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -247,7 +247,7 @@ int glist_isselected(t_glist *x, t_gobj *y)
     /* call this for unselected objects only */
 void glist_select(t_glist *x, t_gobj *y)
 {
-	fprintf(stderr,"glist_select\n");
+	//fprintf(stderr,"glist_select\n");
     if (x->gl_editor)
     {
 		if (c_selection && c_selection != x)
@@ -303,7 +303,7 @@ void glist_deselect(t_glist *x, t_gobj *y)
 				//fprintf(stderr, "e_textedfor == fuddy\n");
                 if (x->gl_editor->e_textdirty)
                 {
-					fprintf(stderr, "textdirty yes\n");
+					//fprintf(stderr, "textdirty yes\n");
                     z = fuddy;
                     canvas_stowconnections(glist_getcanvas(x));
                     glist_checkanddeselectall(x, y);
@@ -354,7 +354,7 @@ void glist_deselect(t_glist *x, t_gobj *y)
 
 void glist_noselect(t_glist *x)
 {
-	fprintf(stderr,"glist_noselect\n");
+	//fprintf(stderr,"glist_noselect\n");
     if (x->gl_editor)
     {
 		if (x->gl_editor->e_selection) {
@@ -614,7 +614,7 @@ typedef struct _undo_cut
 								/* at least one object is selected, we dynamically resize it later */
 } t_undo_cut;
 
-static void *canvas_undo_set_cut(t_canvas *x, int mode)
+void *canvas_undo_set_cut(t_canvas *x, int mode)
 {
     t_undo_cut *buf;
     t_gobj *y;
@@ -682,7 +682,7 @@ static void *canvas_undo_set_cut(t_canvas *x, int mode)
     return (buf);
 }
 
-static void canvas_undo_cut(t_canvas *x, void *z, int action)
+void canvas_undo_cut(t_canvas *x, void *z, int action)
 {
 	//fprintf(stderr, "canvas_undo_cut canvas=%d buf=%d action=%d\n", (int)x, (int)z, action);
     t_undo_cut *buf = z;
@@ -902,13 +902,23 @@ void canvas_undo_move(t_canvas *x, void *z, int action)
 
 typedef struct _undo_paste      
 {
-    int u_index;    /* index of first object pasted */  
+    int u_index;    		/* index of first object pasted */
+	int u_sel_index; 		/* index of object selected at the time the other object was pasted (for autopatching) */ 
+	t_binbuf *u_objectbuf;	/* here we store actual copied data */
 } t_undo_paste;
 
 void *canvas_undo_set_paste(t_canvas *x, int offset)
 {
     t_undo_paste *buf =  (t_undo_paste *)getbytes(sizeof(*buf));
-    buf->u_index = glist_getindex(x, 0) - offset;
+    buf->u_index = glist_getindex(x, 0) - offset; //do we need offset at all?
+	if (x->gl_editor->e_selection && !x->gl_editor->e_selection->sel_next) {
+		//if only one object is selected which will warrant autopatching
+		buf->u_sel_index = glist_getindex(x, x->gl_editor->e_selection->sel_what);
+		fprintf(stderr,"canvas_undo_set_paste selected object index %d\n", buf->u_sel_index);
+	} else {
+		buf->u_sel_index = -1;
+	}
+	buf->u_objectbuf = binbuf_duplicate(copy_binbuf);
     return (buf);
 }
 
@@ -926,15 +936,23 @@ void canvas_undo_paste(t_canvas *x, void *z, int action)
     else if (action == UNDO_REDO)
     {
         t_selection *sel;
-        canvas_dopaste(x, copy_binbuf);
+		glist_noselect(x);
+		//if the pasted object is supposed to be autopatched
+		//then select the object it should be autopatched to
+		if (buf->u_sel_index > -1)
+			glist_select(x, glist_nth(x, buf->u_sel_index));
+        canvas_dopaste(x, buf->u_objectbuf);
             /* if it was "duplicate" have to re-enact the displacement. */
         if (canvas_undo_name && canvas_undo_name[0] == 'd')
             //for (sel = x->gl_editor->e_selection; sel; sel = sel->sel_next)
             //    gobj_displace(sel->sel_what, x, 10, 10);
 			canvas_paste_xyoffset(x);
     }
-	else if (action == UNDO_FREE)
+	else if (action == UNDO_FREE) {
+        if (buf->u_objectbuf)
+            binbuf_free(buf->u_objectbuf);
         t_freebytes(buf, sizeof(*buf));
+	}
 }
 
     /* recursively check for abstractions to reload as result of a save. 
@@ -964,8 +982,9 @@ static void glist_doreload(t_glist *gl, t_symbol *name, t_symbol *dir,
                 canvas_vis(glist_getcanvas(gl), 1);
             glist_noselect(gl);
             glist_select(gl, g);
-            canvas_setundo(gl, canvas_undo_cut,
-                canvas_undo_set_cut(gl, UCUT_CLEAR), "clear");
+            //canvas_setundo(gl, canvas_undo_cut,
+            //    canvas_undo_set_cut(gl, UCUT_CLEAR), "clear");
+			canvas_undo_add(gl, 3, "clear", canvas_undo_set_cut(gl, UCUT_CLEAR));
             canvas_doclear(gl);
             canvas_undo(gl);
             glist_noselect(gl);
@@ -1454,6 +1473,8 @@ void canvas_canvas_setundo(t_canvas *x)
 
 /* --------- 9. create ----------- */
 
+extern t_pd *newest;
+
 typedef struct _undo_create      
 {
     int u_index;    			/* index of the created object object */
@@ -1471,7 +1492,7 @@ void *canvas_undo_set_create(t_canvas *x)
     t_undo_create *buf = (t_undo_create *)getbytes(sizeof(*buf));
     buf->u_index = glist_getindex(x, 0) - 1;
     int nnotsel= glist_selectionindex(x, 0, 0);
-	fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel);
+	//fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel);
 
     buf->u_objectbuf = binbuf_new();
 	if (x->gl_list) {
@@ -1479,7 +1500,7 @@ void *canvas_undo_set_create(t_canvas *x)
 		{
 		    //if (glist_isselected(x, y)) {
 			if (!y->g_next) {
-				fprintf(stderr,"undo_set_create: gobj_save\n");
+				//fprintf(stderr,"undo_set_create: gobj_save\n");
 		        gobj_save(y, buf->u_objectbuf);
 				break;
 			}
@@ -1492,10 +1513,10 @@ void *canvas_undo_set_create(t_canvas *x)
 			//int issel2 = glist_isselected(x, &t.tr_ob2->ob_g);
 			issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0);
 			issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0);
-			fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2);
+			//fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2);
 			if (issel1 != issel2)
 			{
-				fprintf(stderr,"undo_set_create store connection\n");
+				//fprintf(stderr,"undo_set_create store connection\n");
 			    binbuf_addv(buf->u_reconnectbuf, "ssiiii;",
 			        gensym("#X"), gensym("connect"),
 			        (issel1 ? nnotsel : 0)
@@ -1536,6 +1557,8 @@ void canvas_undo_create(t_canvas *x, void *z, int action)
         pd_bind(&x->gl_pd, gensym("#X"));
    		binbuf_eval(buf->u_reconnectbuf, 0, 0, 0);
     	pd_unbind(&x->gl_pd, gensym("#X"));
+        if (newest && pd_class(newest) == canvas_class)
+        	canvas_loadbang((t_canvas *)newest);
         y = glist_nth(x, buf->u_index);
         glist_select(x, y);
     }
@@ -1557,11 +1580,12 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y)
 	int issel1, issel2;
 
     t_undo_create *buf = (t_undo_create *)getbytes(sizeof(*buf));
-    buf->u_index = glist_getindex(x, y); // - 1; TODO: do we still need a -1 here???
+    buf->u_index = glist_getindex(x, y);
     int nnotsel= glist_selectionindex(x, 0, 0) - 1; // - 1 is a critical difference from the create
-	fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel);
+	//fprintf(stderr,"buf->u_index=%d nnotsel=%d\n", buf->u_index, nnotsel);
     buf->u_objectbuf = binbuf_new();
-	fprintf(stderr,"undo_set_create: gobj_save\n");
+	//y = glist_nth(x, buf->u_index);
+	//fprintf(stderr,"undo_set_create: gobj_save\n");
 	gobj_save(y, buf->u_objectbuf);
 
 	buf->u_reconnectbuf = binbuf_new();
@@ -1572,10 +1596,10 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y)
 		//int issel2 = glist_isselected(x, &t.tr_ob2->ob_g);
 		issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0);
 		issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0);
-		fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2);
+		//fprintf(stderr,"undo_set_create linetraverser %d %d\n", issel1, issel2);
 		if (issel1 != issel2)
 		{
-			fprintf(stderr,"undo_set_create store connection\n");
+			//fprintf(stderr,"undo_set_create store connection\n");
 		    binbuf_addv(buf->u_reconnectbuf, "ssiiii;",
 		        gensym("#X"), gensym("connect"),
 		        (issel1 ? nnotsel : 0)
@@ -1591,33 +1615,122 @@ void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y)
 
 void canvas_undo_recreate(t_canvas *x, void *z, int action)
 {
+	//fprintf(stderr,"canvas_undo_recreate\n");
+
     t_undo_create *buf = z;
-    t_gobj *y;
+    t_gobj *y = glist_nth(x, buf->u_index);
 
 	//fprintf(stderr,"canvas = %lx buf->u_index = %d\n", (t_int)x, buf->u_index);
 
     if (action == UNDO_UNDO || action == UNDO_REDO)
     {
-		/*TODO:	copy new state of the current object
-				then cut the existing object
-				then paste old object
-				then free old data buffer and make it point to the new buffer
-				then reorder the object so that it is placed in the same order as the old one
-
-        glist_noselect(x);
-        y = glist_nth(x, buf->u_index);
-
-		
+		// first copy new state of the current object
+		t_linetraverser t;
+		t_outconnect *oc;
+		int issel1, issel2;
+
+		t_undo_create *buf2 = (t_undo_create *)getbytes(sizeof(*buf));
+		buf2->u_index = glist_getindex(x, y);
+		int nnotsel= glist_selectionindex(x, 0, 0) - 1; // - 1 is a critical difference from the create
+		//fprintf(stderr,"buf2->u_index=%d nnotsel=%d\n", buf2->u_index, nnotsel);
+		buf2->u_objectbuf = binbuf_new();
+		//fprintf(stderr,"undo_set_recreate: gobj_save\n");
+		gobj_save(y, buf2->u_objectbuf);
+
+		buf2->u_reconnectbuf = binbuf_new();
+		linetraverser_start(&t, x);
+		while (oc = linetraverser_next(&t))
+		{
+			issel1 = ( &t.tr_ob->ob_g == y ? 1 : 0);
+			issel2 = ( &t.tr_ob2->ob_g == y ? 1 : 0);
+			//fprintf(stderr,"undo_set_recreate linetraverser %d %d\n", issel1, issel2);
+			if (issel1 != issel2)
+			{
+				//fprintf(stderr,"undo_set_recreate store connection\n");
+				binbuf_addv(buf2->u_reconnectbuf, "ssiiii;",
+				    gensym("#X"), gensym("connect"),
+				    (issel1 ? nnotsel : 0)
+				        + glist_selectionindex(x, &t.tr_ob->ob_g, issel1),
+				    t.tr_outno,
+				    (issel2 ? nnotsel : 0) +
+				        glist_selectionindex(x, &t.tr_ob2->ob_g, issel2),
+				    t.tr_inno);
+			}
+		}
 
+		// now then cut the existing object
+		glist_noselect(x);
         glist_select(x, y);
         canvas_doclear(x);
 
+		// then paste the old object
         pd_bind(&x->gl_pd, gensym("#X"));
    		binbuf_eval(buf->u_objectbuf, 0, 0, 0);
     	pd_unbind(&x->gl_pd, gensym("#X"));
         pd_bind(&x->gl_pd, gensym("#X"));
    		binbuf_eval(buf->u_reconnectbuf, 0, 0, 0);
     	pd_unbind(&x->gl_pd, gensym("#X"));
+
+		// free the old data
+		binbuf_free(buf->u_objectbuf);
+		binbuf_free(buf->u_reconnectbuf);
+        t_freebytes(buf, sizeof(*buf));
+
+		// readjust pointer
+		// (this should probably belong into g_undo.c, but since it is a unique case, we'll let it be for the time being)
+		x->u_last->data = (void *)buf2;
+		buf = buf2;
+
+		// reposition object to its original place
+		t_gobj *y_prev, *y_next;
+		//get the last object
+		y = glist_nth(x, glist_getindex(x, 0) - 1);
+		/*for (y = x->gl_list; y; y = y->g_next)
+			if (!y->g_next)
+				break;*/
+		// first check if we are in the same position already
+		if (glist_getindex(x, y) != buf->u_index) {
+			//fprintf(stderr,"not in the right place\n");
+			y_prev = glist_nth(x, buf->u_index-1);
+			y_next = glist_nth(x, buf->u_index);
+			//if the object is supposed to be first in the gl_list
+			if (buf->u_index == 0) {
+				if (y_prev && y_next) {
+					y_prev->g_next = y_next;
+				}
+				else if (y_prev && !y_next)
+					y_prev->g_next = NULL;
+				//now put the moved object at the beginning of the cue
+				y->g_next = glist_nth(x, 0);
+				x->gl_list = y;
+			}
+			//if the object is supposed to be at the current end of gl_list	
+			//can this ever happen???
+			/*else if (!glist_nth(x,buf->p_a[i])) {
+
+			}*/
+			//if the object is supposed to be in the middle of gl_list
+			else {
+				if (y_prev && y_next) {
+					y_prev->g_next = y_next;
+				}
+				else if (y_prev && !y_next) {
+					y_prev->g_next = NULL;
+				}
+				//now put the moved object in its right place
+				y_prev = glist_nth(x, buf->u_index-1);
+				y_next = glist_nth(x, buf->u_index);
+
+				y_prev->g_next = y;
+				y->g_next = y_next;
+			}
+		}
+
+		// send a loadbang
+        if (newest && pd_class(newest) == canvas_class)
+        	canvas_loadbang((t_canvas *)newest);
+
+		// select
         y = glist_nth(x, buf->u_index);
         glist_select(x, y);
     }
@@ -1797,7 +1910,7 @@ void canvas_vis(t_canvas *x, t_floatarg f)
     int flag = (f != 0);
     if (x != glist_getcanvas(x) && glist_isvisible(glist_getcanvas(x))) {
         bug("canvas_vis");
-		fprintf(stderr,"canvas_vis .x%lx .x%lx %f\n", (t_int)x, (t_int)glist_getcanvas(x), f);
+		//fprintf(stderr,"canvas_vis .x%lx .x%lx %f\n", (t_int)x, (t_int)glist_getcanvas(x), f);
 	}
     if (flag)
     {
@@ -3135,8 +3248,9 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
                 /* send the key to the box's editor */
             if (!x->gl_editor->e_textdirty)
             {
-                canvas_setundo(x, canvas_undo_cut,
-                    canvas_undo_set_cut(x, UCUT_TEXT), "typing");
+                //canvas_setundo(x, canvas_undo_cut,
+                //    canvas_undo_set_cut(x, UCUT_TEXT), "typing");
+				canvas_undo_add(x, 3, "typing", canvas_undo_set_cut(x, UCUT_TEXT));
             }
             rtext_key(x->gl_editor->e_textedfor,
                 (int)keynum, gotkeysym);
@@ -3151,8 +3265,9 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
                 canvas_clearline(x);
             else if (x->gl_editor->e_selection)
             {
-                canvas_setundo(x, canvas_undo_cut,
-                    canvas_undo_set_cut(x, UCUT_CLEAR), "clear");
+                //canvas_setundo(x, canvas_undo_cut,
+                //    canvas_undo_set_cut(x, UCUT_CLEAR), "clear");
+				canvas_undo_add(x, 3, "clear", canvas_undo_set_cut(x, UCUT_CLEAR));
                 canvas_doclear(x);
             }
         }
@@ -3533,7 +3648,7 @@ void canvas_finderror(void *error_object)
 
 void canvas_stowconnections(t_canvas *x)
 {
-	fprintf(stderr,"canvas_stowconnections\n");
+	//fprintf(stderr,"canvas_stowconnections\n");
     t_gobj *selhead = 0, *seltail = 0, *nonhead = 0, *nontail = 0, *y, *y2;
     t_linetraverser t;
     t_outconnect *oc;
@@ -3592,7 +3707,7 @@ void canvas_stowconnections(t_canvas *x)
 
 void canvas_restoreconnections(t_canvas *x)
 {
-	fprintf(stderr,"canvas_restoreconnections\n");
+	//fprintf(stderr,"canvas_restoreconnections\n");
     pd_bind(&x->gl_pd, gensym("#X"));
     binbuf_eval(x->gl_editor->e_connectbuf, 0, 0, 0);
     pd_unbind(&x->gl_pd, gensym("#X"));
@@ -3838,8 +3953,9 @@ static void canvas_cut(t_canvas *x)
 	/* else we are cutting objects */
     else if (x->gl_editor && x->gl_editor->e_selection)
     {
-        canvas_setundo(x, canvas_undo_cut,
-            canvas_undo_set_cut(x, UCUT_CUT), "cut");
+        //canvas_setundo(x, canvas_undo_cut,
+        //    canvas_undo_set_cut(x, UCUT_CUT), "cut");
+		canvas_undo_add(x, 3, "cut", canvas_undo_set_cut(x, UCUT_CUT));
         canvas_copy(x);
         canvas_doclear(x);
         paste_xyoffset = 0;
@@ -4002,7 +4118,6 @@ static void canvas_dopaste(t_canvas *x, t_binbuf *b)
  		canvas_displaceselection(x, delta_x, delta_y);
 		//reset canvas_undo_already_set_move
 		canvas_undo_already_set_move = 0;
-		//TODO: now we need to update the undo queue which does not reflect these autopatching changes
 	}
 	//if we are pasting into a new window and this is not copied from external buffer OR
 	//if we are copying from external buffer and the current canvas is not empty
@@ -4011,6 +4126,10 @@ static void canvas_dopaste(t_canvas *x, t_binbuf *b)
 		canvas_paste_atmouse(x);
 		//fprintf(stderr,"doing a paste\n");
 	}
+	//else let's provide courtesy offset
+	else if (!copyfromexternalbuffer) {
+		canvas_paste_xyoffset(x);
+	}
 
     canvas_dirty(x, 1);
 	/*if (!canvas_undo_name || canvas_undo_name[0] != 'd') {
@@ -4044,7 +4163,7 @@ static void canvas_paste(t_canvas *x)
     {
         //canvas_setundo(x, canvas_undo_paste, canvas_undo_set_paste(x),
         //    "paste");
-		canvas_undo_add(x, 5, "paste", (void *)canvas_undo_set_paste(x, 1));
+		canvas_undo_add(x, 5, "paste", (void *)canvas_undo_set_paste(x, 0));
         canvas_dopaste(x, copy_binbuf);
         //canvas_paste_xyoffset(x);
     }
diff --git a/src/g_text.c b/src/g_text.c
index 00adeb8ef12f69e48702d1732f8b11957e7132a8..13aa139c1ff988d454b4e1eac0dffe6b1149677e 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -34,6 +34,7 @@ extern void canvas_apply_setundo(t_canvas *x, t_gobj *y);
 extern void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf, const char *name);
 extern void *canvas_undo_set_create(t_canvas *x);
 extern void canvas_undo_create(t_canvas *x, void *z, int action);
+extern int we_are_undoing;
 
 /* ----------------- the "text" object.  ------------------ */
 
@@ -80,6 +81,9 @@ void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
             and objects though since there's no text in them at menu
             creation. */
             /* gobj_activate(&x->te_g, gl, 1); */
+		if (!we_are_undoing)
+			canvas_undo_add(glist_getcanvas(gl), 9, "create",
+				(void *)canvas_undo_set_create(glist_getcanvas(gl)));
         canvas_startmotion(glist_getcanvas(gl));
     }
 }
@@ -88,7 +92,6 @@ void glist_text(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 
 extern t_pd *newest;
 void canvas_getargs(int *argcp, t_atom **argvp);
-extern int we_are_undoing;
 
 static void canvas_objtext(t_glist *gl, int xpix, int ypix, int selected,
     t_binbuf *b)
@@ -216,7 +219,7 @@ void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
 
 void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 {
-	fprintf(stderr,"canvas_obj\n");
+	//fprintf(stderr,"canvas_obj\n");
     t_text *x;
     if (argc >= 2)
     {
@@ -236,22 +239,18 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
         pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
         canvas_objtext(gl, xpix, ypix, 1, b);
-		//t_undo_create *u_c = (t_undo_create *)glist_getcanvas(gl)->u_last->data;
         if (connectme) {
-			fprintf(stderr,"canvas_obj calls canvas_connect\n");
-			//u_c->indx = indx;
-			//u_c->nobj = nobj;
+			//fprintf(stderr,"canvas_obj calls canvas_connect\n");
             canvas_connect(gl, indx, 0, nobj, 0);
 		}
         else {
-			fprintf(stderr,"canvas_obj calls canvas_startmotion\n");
-			//u_c->indx = -1;
-			//u_c->nobj = -1;	
+			//fprintf(stderr,"canvas_obj calls canvas_startmotion\n");
 			canvas_startmotion(glist_getcanvas(gl));
 		}
 		//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
-		canvas_undo_add(glist_getcanvas(gl), 9, "create",
-			(void *)canvas_undo_set_create(glist_getcanvas(gl)));
+		if (!we_are_undoing)
+			canvas_undo_add(glist_getcanvas(gl), 9, "create",
+				(void *)canvas_undo_set_create(glist_getcanvas(gl)));
     }
 }
 
@@ -1801,12 +1800,16 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize)
              vec2[0].a_type == A_SYMBOL
             && !strcmp(vec2[0].a_w.w_symbol->s_name, "pd"))
         {
+			//TODO: add rename undo
             typedmess(&x->te_pd, gensym("rename"), natom2-1, vec2+1);
             binbuf_free(x->te_binbuf);
             x->te_binbuf = b;
         }
         else  /* normally, just destroy the old one and make a new one. */
         {
+			//fprintf(stderr,"text_setto calls canvas_undo_add\n");
+			canvas_undo_add(glist_getcanvas(glist), 10, "recreate",
+				(void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g));
             int xwas = x->te_xpix, ywas = x->te_ypix;
 			canvas_eraselinesfor(glist, x);
             glist_delete(glist, &x->te_g);
@@ -1815,10 +1818,6 @@ void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize)
             if (newest && pd_class(newest) == canvas_class)
                 canvas_loadbang((t_canvas *)newest);
             canvas_restoreconnections(glist_getcanvas(glist));
-			glist_select(
-			fprintf(stderr,"text_setto calls canvas_undo_add\n");
-			canvas_undo_add(glist_getcanvas(glist), 10, "recreate",
-				(void *)canvas_undo_set_recreate(glist_getcanvas(glist), &x->te_g));
         }
             /* if we made a new "pd" or changed a window name,
                 update window list */
diff --git a/src/g_undo.c b/src/g_undo.c
index 6bdc342a9060dc5e3c256d8155bd27cf459301a8..a1929ad66d017b6398ebf7c2ebb6e9722038472b 100644
--- a/src/g_undo.c
+++ b/src/g_undo.c
@@ -22,7 +22,7 @@ t_undo_action *canvas_undo_init(t_canvas *x)
 		x->u_last = a;
 		a->prev = NULL;
 		a->name = "no";
-        //sys_vgui("pdtk_undomenu .x%lx no no\n", (t_int)a->x);
+        sys_vgui("pdtk_undomenu .x%lx no no\n", (t_int)a->x);
 	}
 	else {
 		if (x->u_last->next) {
@@ -33,7 +33,7 @@ t_undo_action *canvas_undo_init(t_canvas *x)
 		a->prev = x->u_last;
 		x->u_last = a;
 	} 
-	fprintf(stderr,"canvas_undo_init\n");
+	//fprintf(stderr,"canvas_undo_init\n");
 	return(a);
 }
 
@@ -51,15 +51,15 @@ t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name, void *da
 
 void canvas_undo_undo(t_canvas *x)
 {
-	fprintf(stderr,"canvas_undo_undo\n");
 	if (x->u_queue && x->u_last != x->u_queue) {
-		fprintf(stderr,"do it\n");
 		we_are_undoing = 1;
+		fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type);
 		glist_noselect(x);
         switch(x->u_last->type)
         {
 		    case 1:	canvas_undo_connect(x, x->u_last->data, UNDO_UNDO); break; 		//connect
 		    case 2:	canvas_undo_disconnect(x, x->u_last->data, UNDO_UNDO); break; 	//disconnect
+		    case 3:	canvas_undo_cut(x, x->u_last->data, UNDO_UNDO); break; 			//cut
 		    case 4:	canvas_undo_move(x, x->u_last->data, UNDO_UNDO); break;			//move
 		    case 5:	canvas_undo_paste(x, x->u_last->data, UNDO_UNDO); break;		//paste
 		    case 9:	canvas_undo_create(x, x->u_last->data, UNDO_UNDO); break;		//create
@@ -80,16 +80,16 @@ void canvas_undo_undo(t_canvas *x)
 
 void canvas_undo_redo(t_canvas *x)
 {
-	fprintf(stderr,"canvas_undo_redo\n");
 	if (x->u_queue && x->u_last->next) {
-		fprintf(stderr,"do it\n");
 		we_are_undoing = 1;
 		x->u_last = x->u_last->next;
+		fprintf(stderr,"canvas_undo_undo %d\n", x->u_last->type);
 		glist_noselect(x);
         switch(x->u_last->type)
         {
 		    case 1:	canvas_undo_connect(x, x->u_last->data, UNDO_REDO); break; 		//connect
 		    case 2:	canvas_undo_disconnect(x, x->u_last->data, UNDO_REDO); break; 	//disconnect
+		    case 3:	canvas_undo_cut(x, x->u_last->data, UNDO_REDO); break; 			//cut
 		    case 4:	canvas_undo_move(x, x->u_last->data, UNDO_REDO); break;			//move
 		    case 5:	canvas_undo_paste(x, x->u_last->data, UNDO_REDO); break;		//paste
 		    case 9:	canvas_undo_create(x, x->u_last->data, UNDO_REDO); break;		//create
@@ -118,6 +118,7 @@ void canvas_undo_rebranch(t_canvas *x)
 		    {
 				case 1:	canvas_undo_connect(x, a->data, UNDO_FREE); break; 		//connect
 				case 2:	canvas_undo_disconnect(x, a->data, UNDO_FREE); break; 	//disconnect
+				case 3:	canvas_undo_cut(x, a->data, UNDO_FREE); break; 			//cut
 				case 4:	canvas_undo_move(x, a->data, UNDO_FREE); break;			//move
 				case 5:	canvas_undo_paste(x, a->data, UNDO_FREE); break;		//paste
 				case 9:	canvas_undo_create(x, a->data, UNDO_FREE); break;		//create
@@ -143,11 +144,11 @@ void canvas_undo_purge_abstraction_actions(t_canvas *x)
 
 void canvas_undo_free(t_canvas *x)
 {
-	fprintf(stderr,"canvas_undo_free");
+	//fprintf(stderr,"canvas_undo_free");
 	if (x->u_queue) {
 		t_undo_action *a;
 		for(a = x->u_queue; a; a = a->next) {
-			fprintf(stderr,".");
+			//fprintf(stderr,".");
 		    switch(a->type)
 		    {
 				case 1:	canvas_undo_connect(x, a->data, UNDO_FREE); break; 		//connect
@@ -162,6 +163,6 @@ void canvas_undo_free(t_canvas *x)
 			freebytes(a, sizeof(*a));
 		}
 	}
-	fprintf(stderr,"done!\n");
+	//fprintf(stderr,"done!\n");
 }
 
diff --git a/src/g_undo.h b/src/g_undo.h
index 8186c5b78d7e5cde3d30fc88ccf5b2a9e8c17ec2..13a135275cc13fd09e2fce742891854346df5338 100644
--- a/src/g_undo.h
+++ b/src/g_undo.h
@@ -26,16 +26,18 @@ by an undo) all undo actions (except for its deletion in the parent window shoul
 be purged since abstraction's state will now default to its original (saved) state.
 
 Types of undo data:
-0 - init data (start of the queue)
-1 - connect
-2 - disconnect
-3 - cut, clear & typing into objects
-4 - motion, inclding "tidy up" and stretching
-5 - paste & duplicate
-6 - apply
-7 - arrange (to front/back)
-8 - canvas apply
-9 - create
+0  - init data (start of the queue)
+1  - connect
+2  - disconnect
+3  - cut, clear & typing into objects
+4  - motion, inclding "tidy up" and stretching
+5  - paste & duplicate
+6  - apply
+7  - arrange (to front/back)
+8  - canvas apply
+9  - create
+10 - recreate
+11 - rename (TODO)
 */
 
 struct _undo_action
@@ -74,6 +76,11 @@ EXTERN void *canvas_undo_set_disconnect(t_canvas *x,
     int index1, int outno, int index2, int inno);
 EXTERN void canvas_undo_disconnect(t_canvas *x, void *z, int action);
 
+/* --------- 3. cut -------------- */
+
+EXTERN void *canvas_undo_set_cut(t_canvas *x, int mode);
+EXTERN void canvas_undo_cut(t_canvas *x, void *z, int action);
+
 /* --------- 4. move ------------- */
 
 EXTERN void *canvas_undo_set_move(t_canvas *x, int selected);
@@ -92,7 +99,7 @@ EXTERN void *canvas_undo_set_create(t_canvas *x);
 /* --------- 10. recreate -------- */
 
 EXTERN void canvas_undo_recreate(t_canvas *x, void *z, int action);
-EXTERN void *canvas_undo_set_recreate(t_canvas *x);
+EXTERN void *canvas_undo_set_recreate(t_canvas *x, t_gobj *y);
 
 /* ------------------------------- */
 
diff --git a/src/pd.tk b/src/pd.tk
index 2be7b968ff83868b037c2e1037c5b220ec6b75ee..d8d15b574013594989c6d8500b431fe5b1331d15 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -801,9 +801,9 @@ if {$pd_nt == 2} {
 }
 set pd_opendir $untitled_directory
 set pd_savedir $untitled_directory
-set pd_undoaction no
-set pd_redoaction no
-set pd_undocanvas no
+#set pd_undoaction no
+#set pd_redoaction no
+#set pd_undocanvas no
 
 ################ utility functions #########################
 
@@ -1573,19 +1573,21 @@ proc menu_really_close {name} {
 }
 
 proc menu_undo {name} {
-    global pd_undoaction
-    global pd_redoaction
-    global pd_undocanvas
-    if {$name == $pd_undocanvas && $pd_undoaction != "no"} {
+	#puts stderr "menu_undo $name\n"
+    #global pd_undoaction
+    #global pd_redoaction
+    #global pd_undocanvas
+    if {$::undo($name) != "no"} {
         pd [concat $name undo \;]
     }
 }
 
 proc menu_redo {name} {
-    global pd_undoaction
-    global pd_redoaction
-    global pd_undocanvas
-    if {$name == $pd_undocanvas && $pd_redoaction != "no"} {
+	#puts stderr "menu_redo $name\n"
+    #global pd_undoaction
+    #global pd_redoaction
+    #global pd_undocanvas
+    if {$::redo($name) != "no"} {
         pd [concat $name redo \;]
     }
 }
@@ -1766,11 +1768,11 @@ proc menu_mycnv {name accel} {
 # correct edit menu, enabling or disabling undo/redo/cut/copy/paste
 proc menu_fixeditmenu {name} {
 	catch {
-		# pdtk_post "fixeditmenu $name\n"
+		#puts stderr "fixeditmenu $name\n"
 
-		global pd_undoaction
-		global pd_redoaction
-		global pd_undocanvas
+		#global pd_undoaction
+		#global pd_redoaction
+		#global pd_undocanvas
 
 		global global_selection
 		global global_clipboard
@@ -1800,15 +1802,15 @@ proc menu_fixeditmenu {name} {
 		}
 
 		# puts stderr [concat menu_fixeditmenu $name $pd_undocanvas $pd_undoaction]
-		if {$name == $pd_undocanvas && $pd_undoaction != "no"} {
+		if {$::undo($name) != "no"} {
 		    $name.m.edit entryconfigure "Undo*" -state normal \
-		        -label [concat "Undo " $pd_undoaction]
+		        -label [concat "Undo " $::undo($name)]
 		} else {
 		    $name.m.edit entryconfigure "Undo*" -state disabled -label "Undo"
 		}
-		if {$name == $pd_undocanvas && $pd_redoaction != "no"} {
+		if {$::redo($name) != "no"} {
 		    $name.m.edit entryconfigure "Redo*" -state normal\
-		        -label [concat "Redo " $pd_redoaction]
+		        -label [concat "Redo " $::redo($name)]
 		} else {
 		    $name.m.edit entryconfigure "Redo*" -state disabled
 		}
@@ -1829,13 +1831,15 @@ proc menu_fixeditmenu {name} {
 
 # message from Pd to update the currently available undo/redo action
 proc pdtk_undomenu {name undoaction redoaction} {
-    global pd_undoaction
-    global pd_redoaction
-    global pd_undocanvas
+    #global pd_undoaction
+    #global pd_redoaction
+    #global pd_undocanvas
     #    puts stderr [concat pdtk_undomenu $name $undoaction $redoaction]
-    set pd_undocanvas $name
-    set pd_undoaction $undoaction
-    set pd_redoaction $redoaction
+    #set pd_undocanvas $name
+    #set pd_undoaction $undoaction
+    #set pd_redoaction $redoaction
+	set ::undo($name) $undoaction
+	set ::redo($name) $redoaction
     if {$name != "nobody"} {
         #    unpleasant way of avoiding a more unpleasant bug situation --atl 2002.11.25
         menu_fixeditmenu $name
@@ -1977,8 +1981,14 @@ proc pdtk_canvas_new {name width height geometry editable} {
 	if {![info exists ::yscrollable($name)]} {
 		set ::yscrollable($name) 0
 	}
-	if {![info exists ::update_tick($name)]} {
-		set ::update_tick($name) 0
+	#if {![info exists ::update_tick($name)]} {
+	#	set ::update_tick($name) 0
+	#}
+	if {![info exists ::undo($name)]} {
+		set ::undo($name) no
+	}
+	if {![info exists ::redo($name)]} {
+		set ::redo($name) no
 	}
 
 	if {$::menu($name) == 1} {
@@ -3015,7 +3025,7 @@ proc pdtk_canvas_getscroll {name} {
 			set ::yscrollable($parentname) 0
 		}
 	}
-	set ::update_tick([winfo parent $name]) 1
+	#set ::update_tick([winfo parent $name]) 1
     pdtk_canvas_checkgeometry [canvastosym $name]
 }