diff --git a/src/g_editor.c b/src/g_editor.c
index 0c5addde9b5806daedc9ee560de592b9b8bca035..f4e5733ef0c4a9f6c98126661e4054723ebcc778 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -1401,13 +1401,6 @@ void canvas_canvas_setundo(t_canvas *x)
 
 /* --------- 8. create ----------- */
 
-typedef struct _undo_create      
-{
-    int u_index;    /* index of the created object object */
-    t_binbuf *u_objectbuf;      /* the object cleared or typed into */
-    t_binbuf *u_reconnectbuf;   /* connections into and out of object */
-} t_undo_create;
-
 void *canvas_undo_set_create(t_canvas *x)
 {
     t_gobj *y, *last;
@@ -1429,7 +1422,7 @@ void *canvas_undo_set_create(t_canvas *x)
 	}
     buf->u_reconnectbuf = binbuf_new();
     linetraverser_start(&t, x);
-	if (linetraverser_next(&t)) {
+	//if (linetraverser_next(&t)) {
 		while (oc = linetraverser_next(&t))
 		{
 		    int issel1 = glist_isselected(x, &t.tr_ob->ob_g);
@@ -1446,7 +1439,7 @@ void *canvas_undo_set_create(t_canvas *x)
 		            t.tr_inno);
 		    }
 		}
-	}
+	//}
     return (buf);
 }
 
@@ -4335,9 +4328,9 @@ void g_editor_setup(void)
         gensym("selectall"), A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_reselect,
         gensym("reselect"), A_NULL);
-    class_addmethod(canvas_class, (t_method)canvas_undo,
+    class_addmethod(canvas_class, (t_method)canvas_undo_undo,
         gensym("undo"), A_NULL);
-    class_addmethod(canvas_class, (t_method)canvas_redo,
+    class_addmethod(canvas_class, (t_method)canvas_undo_redo,
         gensym("redo"), A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_tidy,
         gensym("tidy"), A_NULL);
diff --git a/src/g_text.c b/src/g_text.c
index 649c58fd874b4bdfc161bd87494d229afbc9181a..9660d8db5f0c2f15c11e35b99c717c1bbdaea257 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -205,7 +205,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)
     {
@@ -228,7 +228,8 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		canvas_undo_add(glist_getcanvas(gl), 8, "create");
     }
 }
 
@@ -237,7 +238,7 @@ void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 /* iemlib */
 void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
 {
-	//fprintf(stderr,"canvas_iemguis\n");
+	fprintf(stderr,"canvas_iemguis\n");
     t_atom at;
     t_binbuf *b = binbuf_new();
     //int xpix, ypix;
@@ -270,7 +271,8 @@ void canvas_iemguis(t_glist *gl, t_symbol *guiobjname)
     //glist_getnextxy(gl, &xpix, &ypix);
     //canvas_objtext(gl, xpix, ypix, 1, b);
     else canvas_startmotion(glist_getcanvas(gl));
-	canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+	//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+	canvas_undo_add(glist_getcanvas(gl), 8, "create");
 }
 
 void canvas_bng(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
@@ -509,6 +511,7 @@ 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");
     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);
@@ -541,7 +544,8 @@ void canvas_msg(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		canvas_undo_add(glist_getcanvas(gl), 8, "create");
     }
 }
 
@@ -928,7 +932,7 @@ static void gatom_vis(t_gobj *z, t_glist *glist, int vis)
 void canvas_atom(t_glist *gl, t_atomtype type,
     t_symbol *s, int argc, t_atom *argv)
 {
-	//fprintf(stderr,"canvas_atom\n");
+	fprintf(stderr,"canvas_atom\n");
     t_gatom *x = (t_gatom *)pd_new(gatom_class);
     t_atom at;
     x->a_text.te_width = 0;                        /* don't know it yet. */
@@ -1001,7 +1005,8 @@ void canvas_atom(t_glist *gl, t_atomtype type,
         if (connectme)
             canvas_connect(gl, indx, 0, nobj, 0);
         else canvas_startmotion(glist_getcanvas(gl));
-		canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		//canvas_setundo(glist_getcanvas(gl), canvas_undo_create, canvas_undo_set_create(gl), "create");
+		canvas_undo_add(glist_getcanvas(gl), 8, "create");
     }
 }
 
diff --git a/src/g_undo.c b/src/g_undo.c
index a634a6b55020942c0c2009608af04820ffa8d400..076caa79fe880af4468521da81e5dc9b02fea3d6 100644
--- a/src/g_undo.c
+++ b/src/g_undo.c
@@ -6,38 +6,99 @@ t_undo_action *canvas_undo_init(t_canvas *x)
 {
 	t_undo_action *a = (t_undo_action *)getbytes(sizeof(*a));
 
+	a->type = 0;
+	a->x = x;
+	a->next = NULL;
+
 	if (!x->u_queue) {
 		//this is the first init
-		a->type = 0;
-		a->x = x;
-		a->prev = NULL;
-		a->next = NULL;
 		x->u_queue = a;
 		x->u_last = a;
+		a->prev = NULL;
+		a->name = "no";
+        sys_vgui("pdtk_undomenu nobody no no\n");
 	}
+	else {
+		if (x->u_last->next) {
+			//we need to rebranch first then add the new action
+			canvas_undo_rebranch(x->u_last);
+		}
+		x->u_last->next = a;
+		a->prev = x->u_last;
+		x->u_last = a;
+	} 
 	fprintf(stderr,"canvas_undo_init\n");
 	return(a);
 }
 
-t_undo_action *canvas_undo_add(t_canvas *x)
+t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name)
 {
-	t_undo_action *a;
+	fprintf(stderr,"canvas_undo_add\n");
+	t_undo_action *a = canvas_undo_init(x);
+	
+	//TODO: parse out type and fill accordingly
+	if (type == 8) { //create
+		t_undo_create *data = (t_undo_create *)canvas_undo_set_create(x);
+		a->type = 8;
+		a->data = (void *)data;
+	}
+	a->name = name;
+    sys_vgui("pdtk_undomenu .x%lx %s no\n", x, a->name);
 	return(a);
 }
 
 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");
+		glist_noselect(x);
+		if (x->u_last->type == 8) { //create
+			canvas_undo_create(x, x->u_last->data, UNDO_UNDO);
+		}
+		x->u_last = x->u_last->prev;
+		char *undo_action = x->u_last->name;
+		char *redo_action = x->u_last->next->name;
+		if (glist_isvisible(x) && glist_istoplevel(x)) {
+			sys_vgui("pdtk_undomenu .x%lx %s %s\n", x, undo_action, redo_action);
+			sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", 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");
+		x->u_last = x->u_last->next;
+		glist_noselect(x);
+		if (x->u_last->type == 8) { //create
+			canvas_undo_create(x, x->u_last->data, UNDO_REDO);
+		}
+		char *undo_action = x->u_last->name;
+		char *redo_action = (x->u_last->next ? x->u_last->next->name : "no");
+		if (glist_isvisible(x) && glist_istoplevel(x)) {
+			sys_vgui("pdtk_undomenu .x%lx %s %s\n", x, undo_action, redo_action);
+			sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
+		}
+	}
 }
 
 void canvas_undo_rebranch(t_undo_action *u)
 {
-
+	fprintf(stderr,"canvas_undo_rebranch");
+	if (u->next) {
+		t_undo_action *a;
+		for(a = u->next; a; a = a->next) {
+			fprintf(stderr,".");
+			if (a->type == 8) { //create
+				canvas_undo_create(a->x, a->data, UNDO_FREE);
+			}
+			freebytes(a, sizeof(*a));
+		}
+	}
+	fprintf(stderr,"done!\n");
 }
 
 void canvas_undo_check_canvas_pointers(t_canvas *x)
@@ -52,13 +113,17 @@ void canvas_undo_purge_abstraction_actions(t_canvas *x)
 
 void canvas_undo_free(t_canvas *x)
 {
-	fprintf(stderr,"canvas_undo_free\n");
+	fprintf(stderr,"canvas_undo_free");
 	if (x->u_queue) {
 		t_undo_action *a;
 		for(a = x->u_queue; a; a = a->next) {
-			fprintf(stderr,"freeing t_undo_action queue member\n");
+			fprintf(stderr,".");
+			if (a->type == 8) { //create
+				canvas_undo_create(a->x, a->data, UNDO_FREE);
+			}
 			freebytes(a, sizeof(*a));
 		}
 	}
+	fprintf(stderr,"done!\n");
 }
 
diff --git a/src/g_undo.h b/src/g_undo.h
index 0606c8f466be13f03e4e819980782f811b109975..0b6ceb4a63dec17c18a1189c4c6413e367feb065 100644
--- a/src/g_undo.h
+++ b/src/g_undo.h
@@ -42,6 +42,7 @@ struct _undo_action
 	t_canvas *x;				/* canvas undo is associated with */
 	int type;					/* defines what kind of data container it is */
 	void *data;					/* each action will have a different data container */
+	char *name;					/* name of current action */
 	struct _undo_action *prev;	/* previous undo action */
 	struct _undo_action *next;	/* next undo action */
 } t_undo_action;
@@ -51,7 +52,7 @@ struct _undo_action
 #endif
 
 EXTERN t_undo_action *canvas_undo_init(t_canvas *x);
-EXTERN t_undo_action *canvas_undo_add(t_canvas *x);
+EXTERN t_undo_action *canvas_undo_add(t_canvas *x, int type, const char *name);
 EXTERN void canvas_undo_undo(t_canvas *x);
 EXTERN void canvas_undo_redo(t_canvas *x);
 EXTERN void canvas_undo_rebranch(t_undo_action *u);
@@ -59,4 +60,18 @@ EXTERN void canvas_undo_check_canvas_pointers(t_canvas *x);
 EXTERN void canvas_undo_purge_abstraction_actions(t_canvas *x);
 EXTERN void canvas_undo_free(t_canvas *x);
 
+/* --------- 8. create ----------- */
+
+typedef struct _undo_create      
+{
+    int u_index;    			/* index of the created object object */
+    t_binbuf *u_objectbuf;      /* the object cleared or typed into */
+    t_binbuf *u_reconnectbuf;   /* connections into and out of object */
+} t_undo_create;
+
+extern void canvas_undo_create(t_canvas *x, void *z, int action);
+extern void *canvas_undo_set_create(t_canvas *x);
+
+/* ------------------------------- */
+
 #endif /* __g_undo_h_ */