Index: /trunk/src/org/expeditee/agents/Format.java
===================================================================
--- /trunk/src/org/expeditee/agents/Format.java	(revision 743)
+++ /trunk/src/org/expeditee/agents/Format.java	(revision 744)
@@ -163,5 +163,5 @@
 		 */
 		start.setChanged(true);
-		start.addToUndo(changedItems);
+		start.addToUndoMove(changedItems);
 		FrameGraphics.requestRefresh(true);
 		return null;
Index: /trunk/src/org/expeditee/agents/HFormat.java
===================================================================
--- /trunk/src/org/expeditee/agents/HFormat.java	(revision 743)
+++ /trunk/src/org/expeditee/agents/HFormat.java	(revision 744)
@@ -48,5 +48,5 @@
 		
 		System.out.println(changedItems);
-		start.addToUndo(changedItems);
+		start.addToUndoMove(changedItems);
 		return null;
 	}
Index: /trunk/src/org/expeditee/gui/Frame.java
===================================================================
--- /trunk/src/org/expeditee/gui/Frame.java	(revision 743)
+++ /trunk/src/org/expeditee/gui/Frame.java	(revision 744)
@@ -94,6 +94,25 @@
 	private boolean _saved = false;
 
+	private static final class History {
+		public enum Type {
+			deletion,
+			movement
+		}
+		public final List<Item> items;
+		public final Type type;
+		
+		public History(Collection<Item> items, Type type) {
+			this.items = new LinkedList<Item>(items);
+			this.type = type;
+		}
+		
+		public String toString() {
+			return this.type.toString() + ":\n" + this.items.toString();
+		}
+	}
+	
 	// list of deleted items that can be restored
-	private Stack<List<Item>> _undo = new Stack<List<Item>>();
+	private Stack<History> _undo = new Stack<History>();
+	private Stack<History> _redo = new Stack<History>();
 
 	// basically just a list of smaller objects?
@@ -892,21 +911,27 @@
 
 	/**
-	 * Adds the given list of Items to the undo stack. This is the same as
-	 * calling addToUndo() for each Item in the list.
-	 * 
-	 * @param items
-	 *            The List of Items to add to the undo stack.
-	 */
-	public void addToUndo(Collection<Item> items) {
+	 * Adds the given History event to the stack.
+	 * 
+	 * @param stack The stack to add to
+	 * @param items The items to put in the event
+	 * @param type  The type of event that occurred
+	 */
+	private void addToUndo(Collection<Item> items, History.Type type) {
 		if (items.size() < 1)
 			return;
 		
-//		System.out.println("Added: " + items);
-
-		_undo.push(new LinkedList<Item>(items));
+		System.out.println("Added: " + items);
+
+		_undo.push(new History(items, type));
+	}
+	
+	public void addToUndoDelete(Collection<Item> items) {
+		addToUndo(items, History.Type.deletion);
+	}
+	public void addToUndoMove(Collection<Item> items) {
+		addToUndo(items, History.Type.movement);
 	}
 
 	public void undo() {
-		List<Item> undo = null;
 		boolean bReparse = false;
 		boolean bRecalculate = false;
@@ -915,15 +940,13 @@
 			return;
 
-		undo = _undo.pop();
+		History undo = _undo.pop();
 		
-//		System.out.println("Undoing: " + undo);
-
-		for(Item i : undo) {
-			// if the change was to characteristics
-			if(i.isVisible() && _body.contains(i)) {
-				_body.set(_body.indexOf(i), i);
-			// the item was deleted
-			} else {
-				_body.add(i);
+		System.out.println("Undoing: " + undo);
+
+		switch(undo.type) {
+		case deletion:
+			_redo.push(undo);
+    		for(Item i : undo.items) {
+    			_body.add(i);
 				bReparse |= i.hasOverlay();
 				bRecalculate |= i.recalculateWhenChanged();
@@ -935,5 +958,71 @@
 					i.setOffset(0, 0);
 				}
-			}
+    		}
+    		break;
+		case movement:
+			List<Item> changed = new LinkedList<Item>(_body);
+			changed.retainAll(undo.items);
+			_redo.push(new History(changed, History.Type.movement));
+			for(Item i : undo.items) {
+				int index;
+				if(i.isVisible() && (index = _body.indexOf(i)) != -1) {
+					_body.set(index, i);
+				}
+    		}
+			break;
+		}
+		change();
+		FrameMouseActions.getInstance().refreshHighlights();
+		if (bReparse) {
+			FrameUtils.Parse(this, false, false);
+		} else {
+			notifyObservers(bRecalculate);
+		}
+		// always request a refresh otherwise filled shapes
+		// that were broken by a deletion and then reconnected by the undo
+		// don't get filled until the user otherwise causes them to redraw
+		FrameGraphics.requestRefresh(false);
+		FrameGraphics.Repaint();
+		ItemUtils.EnclosedCheck(_body);
+	}
+	
+	public void redo() {
+		boolean bReparse = false;
+		boolean bRecalculate = false;
+
+		if (_redo.size() <= 0)
+			return;
+
+		History redo = _redo.pop();
+		
+		System.out.println("Redoing: " + redo);
+
+		switch(redo.type) {
+		case deletion:
+			_undo.push(redo);
+    		for(Item i : redo.items) {
+    			_body.remove(i);
+				bReparse |= i.hasOverlay();
+				bRecalculate |= i.recalculateWhenChanged();
+				if (i instanceof Line) {
+					Line line = (Line) i;
+					line.getStartItem().removeLine(line);
+					line.getEndItem().removeLine(line);
+				} else {
+					i.setOffset(0, 0);
+				}
+    		}
+    		break;
+		case movement:
+			List<Item> changed = new LinkedList<Item>(_body);
+			changed.retainAll(redo.items);
+			_undo.push(new History(changed, History.Type.movement));
+			for(Item i : redo.items) {
+				int index;
+				if(i.isVisible() && (index = _body.indexOf(i)) != -1) {
+					_body.set(index, i);
+				}
+    		}
+			break;
 		}
 		change();
@@ -1477,5 +1566,5 @@
 		}
 		_body.removeAll(newBody);
-		addToUndo(_body);
+		addToUndoDelete(_body);
 		_body = newBody;
 		change();
Index: /trunk/src/org/expeditee/gui/FrameKeyboardActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 743)
+++ /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 744)
@@ -817,5 +817,9 @@
 			break;
 		case KeyEvent.VK_Z:
-			DisplayIO.getCurrentFrame().undo();
+			if(isShiftDown) {
+				DisplayIO.getCurrentFrame().redo();
+			} else {
+				DisplayIO.getCurrentFrame().undo();
+			}
 			return;
 		case KeyEvent.VK_D:
Index: /trunk/src/org/expeditee/gui/FrameMouseActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 743)
+++ /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 744)
@@ -1675,6 +1675,18 @@
 		inWindow = false;
 		// System.out.println("Left window");
-		if(FreeItems.itemsAttachedToCursor())
-			ItemSelection.cut();
+		if(FreeItems.itemsAttachedToCursor()) {
+			boolean cut = true;
+			for(Item i : FreeItems.getInstance()) {
+				for(Item j : i.getAllConnected()) {
+					if(!FreeItems.getInstance().contains(j)) {
+						cut = false;
+						break;
+					}
+				}
+			}
+			if(cut) {
+				ItemSelection.cut();
+			}
+		}
 	}
 	
@@ -2599,5 +2611,9 @@
 				// otherwise this is an undo command
 			} else {
-				DisplayIO.getCurrentFrame().undo();
+				if(isControlDown()) {
+					DisplayIO.getCurrentFrame().redo();
+				} else {
+					DisplayIO.getCurrentFrame().undo();
+				}
 			}
 			return;
@@ -2669,5 +2685,5 @@
 			SessionStats.DeletedItems(toUndo);
 			if (parent != null) {
-				parent.addToUndo(toUndo);
+				parent.addToUndoDelete(toUndo);
 				parent.removeAllItems(toUndo); // toDelete.getConnected()
 			}
@@ -2755,5 +2771,5 @@
 		// the current frame as well as the overlay frame
 		Frame currentFrame = DisplayIO.getCurrentFrame();
-		currentFrame.addToUndo(itemList);
+		currentFrame.addToUndoDelete(itemList);
 		itemList.clear();
 		if (bReparse) {
Index: /trunk/src/org/expeditee/gui/Help.java
===================================================================
--- /trunk/src/org/expeditee/gui/Help.java	(revision 743)
+++ /trunk/src/org/expeditee/gui/Help.java	(revision 744)
@@ -129,5 +129,8 @@
 			break;
 		case background:
-			if((other & cursor) == 0) return "Undo last delete";
+			if((other & cursor) == 0) {
+				if((mod & control) != 0) return "Redo";
+				return "Undo";
+			}
 			break;
 		}
