diff --git a/src/g_editor.c b/src/g_editor.c
index c2ad235ed2eaf88e7830619e892b1cec67e5792c..66a0d3d9bb0ac2958df970465fb3929c8f890514 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -36,6 +36,8 @@ static void canvas_cut(t_canvas *x);
 static void canvas_undo(t_canvas *x);
 static int paste_xyoffset = 0; /* a counter of pastes to make x,y offsets */
 static void canvas_mouseup_gop(t_canvas *x, t_gobj *g);
+static void canvas_done_popup(t_canvas *x, t_float which, t_float xpos, t_float ypos);
+static void canvas_doarrange(t_canvas *x, t_float which, t_gobj *oldy, t_gobj *oldy_prev, t_gobj *oldy_next);
 
 // jsarlo
 static char canvas_cnct_inlet_tag[4096];
@@ -916,16 +918,7 @@ static void *canvas_undo_set_apply(t_canvas *x, t_gobj *obj)
     buf->u_objectbuf = canvas_docopy(x);
 
 	/* store index of the currently selected object */
-    t_selection *sel = x->gl_editor->e_selection;
-	t_gobj *tgt = sel->sel_what;
-	int index = 0;
-	for (y = x->gl_list; y; y = y->g_next) {
-		if (y == tgt) {
-			buf->u_index = index;
-			break;
-		}
-		index++;
-	}
+	buf->u_index = glist_getindex(x, obj);
 
     return (buf);
 }
@@ -972,6 +965,153 @@ void canvas_apply_setundo(t_canvas *x, t_gobj *y)
 	canvas_setundo(x, canvas_undo_apply, canvas_undo_set_apply(x, y), "apply");
 }
 
+/* --------- 6. arrange (to front/back)  ----------- */
+
+typedef struct _undo_arrange       
+{
+	int u_previndex;			/* old index */
+	int u_newindex;				/* new index */
+} t_undo_arrange;
+
+static void *canvas_undo_set_arrange(t_canvas *x, t_gobj *obj, int newindex)
+{
+	// newindex tells us is the new index at the beginning (0) or the end (1)
+
+    t_undo_arrange *buf;
+    t_gobj *y;
+	/* enable editor (in case it is disabled) and select the object we are working on */
+	if (!x->gl_edit)
+		canvas_editmode(x, 1);
+
+	// select the object
+	if (!glist_isselected(x, obj))
+		glist_select(x, obj);
+
+    buf = (t_undo_arrange *)getbytes(sizeof(*buf));
+
+	// set the u_newindex appropriately
+	if (newindex == 0) buf->u_newindex = 0;
+	else buf->u_newindex = glist_getindex(x, 0) - 1;
+
+	/* store index of the currently selected object */
+	buf->u_previndex = glist_getindex(x, obj);
+
+	//fprintf(stderr,"undo_set_arrange %d %d\n", buf->u_previndex, buf->u_newindex);		
+
+    return (buf);
+}
+
+static void canvas_undo_arrange(t_canvas *x, void *z, int action)
+{
+    t_undo_arrange *buf = z;
+	t_gobj *y=NULL, *prev=NULL, *next=NULL;
+
+	if (!x->gl_edit)
+		canvas_editmode(x, 1);
+
+    if (action == UNDO_UNDO)
+    {
+		// this is our object
+		y = glist_nth(x, buf->u_newindex);
+
+		//fprintf(stderr,"canvas_undo_arrange UNDO_UNDO %d %d\n", buf->u_previndex, buf->u_newindex);		
+
+		/* select object */
+		glist_noselect(x);
+		glist_select(x, y);
+
+		if (buf->u_newindex) {
+			// if it is the last object
+			
+			// first previous object should point to nothing
+			prev = glist_nth(x, buf->u_newindex - 1);
+			prev->g_next = NULL;	
+
+			/* now we reuse vars for the follwoing:
+			   old index should be right before the object previndex
+			   is pointing to as the object was moved to the end */
+
+			/* old position is not first */
+			if (buf->u_previndex) {
+				prev = glist_nth(x, buf->u_previndex - 1);
+				next = prev->g_next;
+
+				// now readjust pointers
+				prev->g_next = y;
+				y->g_next = next;
+			}
+			/* old position is first */
+			else {
+				prev = NULL;
+				next = x->gl_list;
+
+				// now readjust pointers
+				y->g_next = next;
+				x->gl_list = y;
+			}
+
+			// and finally redraw canvas
+			canvas_redraw(x);
+		}
+		else {
+			// if it is the first object
+
+			/* old index should be right after the object previndex
+			   is pointing to as the object was moved to the end */
+			prev = glist_nth(x, buf->u_previndex);
+
+			// next may be NULL and that is ok
+			next = prev->g_next;
+
+			//first glist pointer needs to point to the second object
+			x->gl_list = y->g_next;
+
+			//now readjust pointers
+			prev->g_next = y;
+			y->g_next = next;
+
+			// and finally redraw canvas
+			canvas_redraw(x);
+		}
+    }
+	else if (action == UNDO_REDO) {
+		// find our object
+		y = glist_nth(x, buf->u_previndex);
+
+		//fprintf(stderr,"canvas_undo_arrange UNDO_REDO %d %d\n", buf->u_previndex, buf->u_newindex);	
+
+		/* select object */
+		glist_noselect(x);
+		glist_select(x, y);
+
+		int action;
+		if (!buf->u_newindex) action = 4;
+		else action = 3;
+
+		t_gobj *oldy_prev=NULL, *oldy_next=NULL;
+
+		// if there is an object before ours (in other words our index is > 0
+		if (glist_getindex(x,y))
+			oldy_prev = glist_nth(x, buf->u_previndex - 1);
+			
+		// if there is an object after ours
+		if (y->g_next)
+			oldy_next = y->g_next;
+
+		canvas_doarrange(x, action, y, oldy_prev, oldy_next);
+	}
+    else if (action == UNDO_FREE)
+    {
+        t_freebytes(buf, sizeof(*buf));
+    }
+}
+
+void canvas_arrange_setundo(t_canvas *x, t_gobj *obj, int newindex)
+{
+	canvas_setundo(x, canvas_undo_arrange, canvas_undo_set_arrange(x, obj, newindex), "arrange");
+}
+
+
 /* ------------------------ event handling ------------------------ */
 
 static char *cursorlist[] = {
@@ -1433,6 +1573,44 @@ static void canvas_donecanvasdialog(t_glist *x,
 	sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", (long unsigned int)canvas);
 }
 
+/* called by undo/redo arrange and done_canvas_popup. only done_canvas_popup
+   checks if it is a valid action and activates undo option */
+static void canvas_doarrange(t_canvas *x, t_float which, t_gobj *oldy, t_gobj *oldy_prev, t_gobj *oldy_next)
+{
+	t_gobj *y_begin = x->gl_list;
+	t_gobj *y_end = glist_nth(x, glist_getindex(x,0) - 1);
+
+	if (which == 3) /* to front */
+	{
+		//put the object at the end of the cue
+		y_end->g_next = oldy;
+		oldy->g_next = NULL;
+
+		// now fix links in the hole made in the list due to moving of the oldy
+		// (we know there is oldy_next as y_end != oldy in canvas_done_popup)
+		if (oldy_prev) //there is indeed more before the oldy position
+			oldy_prev->g_next = oldy_next;
+		else x->gl_list = oldy_next;
+
+		// and finally redraw
+		canvas_redraw(x);	
+	}
+	if (which == 4) /* to back */
+	{
+		x->gl_list = oldy; //put it to the beginning of the cue
+		oldy->g_next = y_begin; //make it point to the old beginning
+
+		// now fix links in the hole made in the list due to moving of the oldy
+		// (we know there is oldy_prev as y_begin != oldy in canvas_done_popup)
+		if (oldy_next) //there is indeed more after oldy position
+			oldy_prev->g_next = oldy_next;
+		else oldy_prev->g_next = NULL; //oldy was the last in the cue
+
+		// and finally redraw
+		canvas_redraw(x);
+	}
+}
+
     /* called from the gui when a popup menu comes back with "properties,"
         "open," or "help." */
 	/* Ivica Ico Bukvic <ico@bukvic.net> 2010-11-17
@@ -1440,19 +1618,32 @@ static void canvas_donecanvasdialog(t_glist *x,
 static void canvas_done_popup(t_canvas *x, t_float which, t_float xpos, t_float ypos)
 {
     char pathbuf[FILENAME_MAX], namebuf[FILENAME_MAX];
-    t_gobj *y;
+    t_gobj *y, *oldy=NULL, *oldy_prev=NULL, *oldy_next=NULL, *y_begin, *y_end=NULL;
+
+	//mark the beginning of the glist for front/back
+	y_begin = x->gl_list;
+	
     for (y = x->gl_list; y; y = y->g_next)
     {
-		/* if we are sending "to back" we need to select all objects
-		   but the one originally selected */
-		if (which == 4) /* to back */
+		if (which == 3 || which == 4) /* to-front or to-back */
 		{
 			if (!x->gl_edit)
-				x->gl_edit = !x->gl_edit;
-			if (glist_isselected(x, y))
-				glist_deselect(x, y);
-			else if (!glist_isselected(x, y))
-				glist_select(x, y);
+				canvas_editmode(x, 1);
+
+			// if next one is the one selected for moving
+			if (y->g_next && glist_isselected(x, y->g_next)) {
+				oldy_prev = y;
+				oldy = y->g_next;
+				//if there is more after the selected object
+				if (oldy->g_next)
+					oldy_next = oldy->g_next;
+			}
+			else if (glist_isselected(x, y) && oldy == NULL) {
+				//selected obj is the first in the cue
+				oldy = y;
+				if (y->g_next)
+					oldy_next = y->g_next;
+			}
 		}
         int x1, y1, x2, y2;
         if (canvas_hitbox(x, y, xpos, ypos, &x1, &y1, &x2, &y2))
@@ -1502,40 +1693,24 @@ static void canvas_done_popup(t_canvas *x, t_float which, t_float xpos, t_float
                 open_via_helppath(namebuf, dir);
                 return;
             }
-			else if (which == 3) /* to front */
-			{
-				if (!x->gl_edit)
-					x->gl_edit = !x->gl_edit;
-				if (!glist_isselected(x, y))
-					glist_select(x, y);
-			}
-			else if (which == 4) /* to back */
-			{
-				/* if the item we are sending back is selected
-				   deselect it */
-				if (glist_isselected(x, y))
-					glist_deselect(x, y);
-			}
         }
     }
-	if (which == 3) /* to front */
+
+	y_end = glist_nth(x, glist_getindex(x,0) - 1);
+
+	if (which == 3 && y_end != oldy) /* to front */
 	{
-		/* now that all are selected */
-		canvas_cut(x);
-		canvas_undo(x);
+		/* create appropriate undo action */
+		canvas_arrange_setundo(x, oldy, 1);
+
+		canvas_doarrange(x, which, oldy, oldy_prev, oldy_next);
 	}
-	if (which == 4) /* to back */
+	if (which == 4 && y_begin != oldy) /* to back */
 	{
-		/* now that all are selected */
-		canvas_cut(x);
-		canvas_undo(x);
-		/* reselect the originally selected object(s) */
-		for (y = x->gl_list; y; y = y->g_next) {
-			if (glist_isselected(x, y))
-				glist_deselect(x, y);
-			else if (!glist_isselected(x, y))
-				glist_select(x, y);
-		}
+		/* create appropriate undo action */
+		canvas_arrange_setundo(x, oldy, 0);
+
+		canvas_doarrange(x, which, oldy, oldy_prev, oldy_next);
 	}
     if (which == 0)
         canvas_properties(x);
diff --git a/src/m_pd.h b/src/m_pd.h
index f5393a118cdcf4375ee5cd67843944fa26bfc678..2a2d28dd5b409e98d26d980452e13322ce3884d6 100644
--- a/src/m_pd.h
+++ b/src/m_pd.h
@@ -11,7 +11,7 @@ extern "C" {
 #define PD_MAJOR_VERSION 0
 #define PD_MINOR_VERSION 42
 #define PD_BUGFIX_VERSION 5
-#define PD_TEST_VERSION "extended-l2ork-20101230"
+#define PD_TEST_VERSION "extended-l2ork-20110101"
 
 /* old name for "MSW" flag -- we have to take it for the sake of many old
 "nmakefiles" for externs, which will define NT and not MSW */
diff --git a/src/pd.tk b/src/pd.tk
index 24a7248a0ffeb78bc800887a9bd2b2f7b454bb5e..f680f5868ec25cbdfce30fbb875eeccbfce9e20d 100644
--- a/src/pd.tk
+++ b/src/pd.tk
@@ -2179,11 +2179,11 @@ proc pdtk_canvas_new {name width height geometry editable} {
         -command [concat popup_action $name 1] 
     $name.popup add command -label {Help} \
         -command [concat popup_action $name 2]
-	#$name.popup add separator
-    #$name.popup add command -label {To Front} \
-    #    -command [concat popup_action $name 3]
-    #$name.popup add command -label {To Back} \
-    #    -command [concat popup_action $name 4]
+	$name.popup add separator
+    $name.popup add command -label {To Front} \
+        -command [concat popup_action $name 3]
+    $name.popup add command -label {To Back} \
+        -command [concat popup_action $name 4]
 
     # fix menu font size on Windows with tk scaling = 1
     if {$pd_nt == 1} {