Index: /trunk/.classpath
===================================================================
--- /trunk/.classpath	(revision 66)
+++ /trunk/.classpath	(revision 67)
@@ -2,4 +2,5 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="tests"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/>
Index: /trunk/src/org/expeditee/actions/NavigationActions.java
===================================================================
--- /trunk/src/org/expeditee/actions/NavigationActions.java	(revision 66)
+++ /trunk/src/org/expeditee/actions/NavigationActions.java	(revision 67)
@@ -117,6 +117,7 @@
 	
 	public static void NextFrame(boolean addToBack) {
+		addToBack = adjustAddToBack(addToBack);
 		Frame next = FrameIO.LoadNext();
-		FrameUtils.DisplayFrame(next, true);
+		FrameUtils.DisplayFrame(next, addToBack);
 	}
 	
@@ -145,4 +146,5 @@
 	
 	public static void PreviousFrame(boolean addToBack) {
+		addToBack = adjustAddToBack(addToBack);
 		Frame prev = FrameIO.LoadPrevious();
 		FrameUtils.DisplayFrame(prev, addToBack);
@@ -213,6 +215,6 @@
 		// ByMike: Find the first occurence of a ParentItem linked to the source
 		while (parentItemLinkedToSource < items.size()
-				&& (items.get(parentItemLinkedToSource).getLink() == null || !items
-						.get(parentItemLinkedToSource).getLink().toLowerCase()
+				&& (items.get(parentItemLinkedToSource).getAbsoluteLink() == null || !items
+						.get(parentItemLinkedToSource).getAbsoluteLink().toLowerCase()
 						.equals(sourceName))) {
 			parentItemLinkedToSource++; // ByRob: this increments to the next
@@ -224,5 +226,5 @@
 			if (items.get(i).isLinkValid()
 					&& !items.get(i).isAnnotation()
-					&& !items.get(i).getLink().toLowerCase().equals(
+					&& !items.get(i).getAbsoluteLink().toLowerCase().equals(
 							source.getFrameName().toLowerCase())) {
 				_LastItemUsed = items.get(i);
@@ -250,3 +252,28 @@
 			DisplayIO.ToggleTwinFrames();
 	}
+	
+	// When display frame is called with addToBack set to false multiple
+	// times...
+	// The first time we add to back but after that we dont
+	// This flag stores the state for the addToBack parameter the last time this
+	// method was called
+	private static boolean _lastAddToBack = true;
+
+	public static void ResetLastAddToBack() {
+		_lastAddToBack = true;
+	}
+	
+	private static boolean adjustAddToBack(boolean addToBack) {
+		boolean originalAddToBack = addToBack;
+		
+		if (!addToBack && _lastAddToBack){
+			//This adds the first frame to the backup stack when the user
+			//navigates through a bunch of frames with the keyboard!
+			addToBack = true;
+		}
+		
+		_lastAddToBack = originalAddToBack;
+		
+		return addToBack;
+	}
 }
Index: /trunk/src/org/expeditee/actions/Simple.java
===================================================================
--- /trunk/src/org/expeditee/actions/Simple.java	(revision 66)
+++ /trunk/src/org/expeditee/actions/Simple.java	(revision 67)
@@ -1977,5 +1977,5 @@
 
 				item.setPosition(newX, newY);
-				DisplayIO.repaint();
+				FrameGraphics.Repaint();
 			}
 			// Thread.yield();
@@ -2037,5 +2037,5 @@
 				return Status.OK;
 			} else if (tokens[0].equals("repaint")) {
-				DisplayIO.repaint();
+				FrameGraphics.Repaint();
 				return Status.OK;
 			}
Index: /trunk/src/org/expeditee/gui/AttributeUtils.java
===================================================================
--- /trunk/src/org/expeditee/gui/AttributeUtils.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/AttributeUtils.java	(revision 67)
@@ -587,10 +587,10 @@
 	 *            The String to strip
 	 * @return The part of the String that is after a colon if there is one, or
-	 *         null if there is no colon
+	 *         the entire string if there is no colon
 	 */
 	public static String stripValue(String toStrip) {
 		int ind = toStrip.lastIndexOf(SEPARATOR_CHAR);
 		if (ind < 0)
-			return null;
+			return toStrip;
 
 		toStrip = toStrip.substring(ind + 1);
Index: /trunk/src/org/expeditee/gui/Browser.java
===================================================================
--- /trunk/src/org/expeditee/gui/Browser.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/Browser.java	(revision 67)
@@ -31,5 +31,5 @@
 public class Browser extends JFrame implements ComponentListener,
 		WindowListener, WindowStateListener {
-	
+
 	/**
 	 * Default version - just to stop eclipse from complaining about it.
@@ -40,5 +40,5 @@
 
 	public static Browser _theBrowser;
-	
+
 	/**
 	 * Constructs a new Browser object, then launches it
@@ -49,32 +49,33 @@
 		_theBrowser = new Browser();
 		// Why do we want to ignore repaint?
-		// b.setIgnoreRepaint(true);
+		//_theBrowser.setIgnoreRepaint(true);
 		_theBrowser.requestFocus();
 		// FrameGraphics.ForceRepaint();
 	}
-	
+
 	public void setSizes(Dimension size) {
 		setSize(size);
 		setPreferredSize(size);
-		addWindowListener(this);
-		addWindowStateListener(this);
-
+
+		FrameGraphics.setMaxSize(this.getContentPane().getSize());
+	}
+
+	public Browser() {
+		// Use the default values initially so we can load the profile frame
+		setSizes(new Dimension(UserSettings.InitialWidth,
+				UserSettings.InitialHeight));
 		// center the frame on the screen
 		Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
 		double xpos = screen.getWidth() / 2;
 		double ypos = screen.getHeight() / 2;
-		setLocation((int) (xpos - (size.getWidth() / 2)), (int) (ypos - (size
-				.getHeight() / 2)));
-
-		FrameGraphics.setMaxSize(this.getContentPane().getSize());
-	}
-
-	public Browser() {
-		// Use the default values initially so we can load the profile frame
-		setSizes(new Dimension(UserSettings.InitialWidth,
-				UserSettings.InitialHeight));
+		setLocation((int) (xpos - (UserSettings.InitialWidth / 2)),
+				(int) (ypos - (UserSettings.InitialHeight / 2)));
+
+		addWindowListener(this);
+		addWindowStateListener(this);
 
 		UserSettings.Init();
-		UserSettings.Username = FrameIO.ConvertToValidFramesetName(System.getProperty("user.name"));
+		UserSettings.Username = FrameIO.ConvertToValidFramesetName(System
+				.getProperty("user.name"));
 		String userName = UserSettings.Username;
 		Frame profile = FrameIO.LoadProfile(userName);
@@ -83,7 +84,8 @@
 				profile = FrameIO.CreateNewProfile(userName);
 			} catch (Exception e) {
-				//TODO tell the user that there was a problem creating the profile frame and close nicely
+				// TODO tell the user that there was a problem creating the
+				// profile frame and close nicely
 				e.printStackTrace();
-				assert(false);
+				assert (false);
 			}
 		}
@@ -95,12 +97,14 @@
 				UserSettings.InitialHeight));
 
-		//set the layout to absolute layout for widgets
+		// set the layout to absolute layout for widgets
 		this.getContentPane().setLayout(new AbsoluteLayout());
-		//enable the glasspane-for capturing all mouse events
-		this.setGlassPane(new MouseEventRouter(getJMenuBar(), getContentPane()));
+		// enable the glasspane-for capturing all mouse events
+		this
+				.setGlassPane(new MouseEventRouter(getJMenuBar(),
+						getContentPane()));
 		this.getGlassPane().setVisible(true);
 		this.getContentPane().setBackground(Color.white);
 		this.getContentPane().setFocusTraversalKeysEnabled(false);
-		
+
 		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
@@ -147,5 +151,5 @@
 	private void setupGraphics() {
 		g = (Graphics2D) this.getContentPane().getGraphics();
-		assert g != null;
+		assert (g != null);
 		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
 				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
@@ -154,8 +158,13 @@
 	}
 
+	// private int count = 0;
 	@Override
 	public void paint(Graphics g) {
+		// All this does is make sure the screen is repainted when the browser
+		// is moved so that some of the window is off the edge of the display
+		// then moved back into view
 		super.paint(g);
 		FrameGraphics.Repaint();
+		//System.out.println("Paint " + count++);
 	}
 
@@ -166,5 +175,6 @@
 		setSizes(this.getSize());
 		setupGraphics();
-		repaint();
+		FrameIO.RefreshCasheImages();
+		FrameGraphics.Repaint();
 	}
 
@@ -211,12 +221,7 @@
 	}
 
-	/*
-	 * public void windowGainedFocus(WindowEvent e) { FrameGraphics.Repaint(); }
-	 * 
-	 * public void windowLostFocus(WindowEvent e) { //FrameGraphics.Repaint(); }
-	 */
 	public void windowStateChanged(WindowEvent e) {
-		//FrameGraphics.Repaint();
-		//System.out.println('C');
+		// FrameGraphics.Repaint();
+		// System.out.println('C');
 	}
 
Index: /trunk/src/org/expeditee/gui/DisplayIO.java
===================================================================
--- /trunk/src/org/expeditee/gui/DisplayIO.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/DisplayIO.java	(revision 67)
@@ -15,4 +15,5 @@
 import javax.swing.JOptionPane;
 
+import org.expeditee.actions.NavigationActions;
 import org.expeditee.items.Item;
 import org.expeditee.items.ItemParentStateChangedEvent;
@@ -54,6 +55,4 @@
 	private static Robot _Robot;
 
-	// public static JMenuBar _MenuBar = new JMenuBar();
-
 	private static boolean _TwinFrames = false;
 
@@ -61,5 +60,5 @@
 	 * The title to display in the Title bar.
 	 */
-	public static final String TITLE = "Exp16May2008A";
+	public static final String TITLE = "Exp17May2008A";
 
 	private DisplayIO() {
@@ -114,9 +113,4 @@
 		}
 
-		/*
-		 * System.out.println("hs: " + hotspotPos + " start: " + start + " font: " +
-		 * size + " cursor: " + (cursorSize - start));
-		 */
-
 		int[] pixels = new int[cursorSize * cursorSize];
 
@@ -229,11 +223,4 @@
 
 	/**
-	 * Forces a complete repaint of the GUI and Frame
-	 */
-	public static void repaint() {
-		_Browser.repaint();
-	}
-
-	/**
 	 * Returns the top item (last added) of the Back-Stack (which is popped off)
 	 * 
@@ -519,42 +506,4 @@
 
 	/**
-	 * Adds the given JMenu to the JMenuBar of the GUI
-	 * 
-	 * @param menu
-	 *            The menu to add
-	 */
-	/*
-	 * public static void addMenu(JMenu menu) { if (menu.getItemCount() == 0)
-	 * return;
-	 * 
-	 * _MenuBar.add(menu); // show progress _Browser.loadedMenu(menu.getText()); }
-	 */
-
-	/**
-	 * Performs the same action as if the user had clicked on the MenuItem at
-	 * the given index in the Menu at the given index.
-	 * 
-	 * @param menu
-	 *            The index of the menu (starts from 0)
-	 * @param index
-	 *            The index of the Item to simulate a click on (starts from 0)
-	 */
-	/*
-	 * public static void activateMenuItem(int menu, int index) { if
-	 * (_MenuBar.getComponentCount() < menu) return;
-	 * 
-	 * JMenu act = _MenuBar.getMenu(menu);
-	 * 
-	 * if (act.getComponentCount() < index) return;
-	 * 
-	 * act.getItem(index).doClick(); }
-	 * 
-	 * public static int getMenuHeight() { if (_MenuBar.getHeight() < 5) return
-	 * 21;
-	 * 
-	 * return _MenuBar.getHeight() - 5; }
-	 */
-
-	/**
 	 * Returns the current mouse X coordinate. This coordinate is relative to
 	 * the left edge of the frame the mouse is in. It takes into account the
@@ -589,4 +538,6 @@
 
 	public static void Back() {
+		NavigationActions.ResetLastAddToBack();
+		
 		int side = getCurrentSide();
 
Index: /trunk/src/org/expeditee/gui/Frame.java
===================================================================
--- /trunk/src/org/expeditee/gui/Frame.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/Frame.java	(revision 67)
@@ -41,15 +41,9 @@
 
 	// The various attributes of this Frame
-	/**
-	 * TODO: Change these to non-string attributes (where applicable). All
-	 * processing to\from Java types should be done in KMSReader and KMSWriter.
-	 */
 	private String _frameset = null;
 
 	private int _number = -1;
 
-	private int _version = 1;
-
-	private int _fversion = -1;
+	private int _version = 0;
 
 	private String _protection = null;
@@ -90,5 +84,5 @@
 
 	public static List<Item> FreeItems = new ArrayList<Item>();
-	
+
 	// for drawing purposes
 	private List<InteractiveWidget> _iWidgets = new ArrayList<InteractiveWidget>();
@@ -101,6 +95,4 @@
 	private Text _frameName = null;
 
-	// private Text _template = UserSettings.ItemTemplate.copy();
-
 	private List<Overlay> _overlays = new ArrayList<Overlay>();
 
@@ -122,9 +114,8 @@
 	public void setBuffer(VolatileImage newBuffer) {
 		_buffer = newBuffer;
-		// setBufferValid(true);
 	}
 
 	public boolean isBufferValid() {
-		if (_buffer != null && _buffer.contentsLost())
+		if (_buffer == null || _buffer.contentsLost())
 			return false;
 
@@ -132,5 +123,5 @@
 	}
 
-	public void setBufferValid(boolean newValue) {
+	private void setBufferValid(boolean newValue) {
 		_validBuffer = newValue;
 	}
@@ -147,9 +138,9 @@
 				i.setID(++_lineCount);
 	}
-	
+
 	/**
 	 * 
 	 * @return The interactive widgets that are currently ancored in this frame.
-	 * Hence it exlcudes free-widgets. Returns a copy
+	 *         Hence it exlcudes free-widgets. Returns a copy
 	 */
 	public List<InteractiveWidget> getInteractiveWidgets() {
@@ -181,5 +172,5 @@
 		_change = value;
 
-		if (_change){
+		if (_change) {
 			setBufferValid(false);
 			_saved = false;
@@ -204,21 +195,23 @@
 			_sorted = true;
 		}
-		
+
 		List<Item> visibleItems = new ArrayList<Item>();
-		
-		for(Item i: _body) {
+
+		for (Item i : _body) {
 			if (i.isVisible())
 				visibleItems.add(i);
 		}
-		
+
 		return visibleItems;
 	}
-	
-	/**
-	 * @param i Item to check if contained in this frame
+
+	/**
+	 * @param i
+	 *            Item to check if contained in this frame
 	 * @return True if this frame contains i.
 	 */
 	public boolean containsItem(Item i) {
-		if (i == null) throw new NullPointerException("i"); 
+		if (i == null)
+			throw new NullPointerException("i");
 		return _body.contains(i);
 	}
@@ -234,6 +227,6 @@
 		for (Item i : getItems()) {
 			// only add up normal body text items
-			if ((i instanceof Text) && 
-					(includeAnnotations || !i.isAnnotation())) {
+			if ((i instanceof Text)
+					&& (includeAnnotations || !i.isAnnotation())) {
 				bodyTextItems.add((Text) i);
 			}
@@ -241,5 +234,5 @@
 		bodyTextItems.remove(getTitle());
 
-		return bodyTextItems;		
+		return bodyTextItems;
 	}
 
@@ -316,7 +309,9 @@
 				frameTitle.stripFirstWord();
 		}
-		//TODO Widgets... check this out
-		// Brook: Cannot figure what is going on above... widget  annot titles should be stripped always
-		if (ItemUtils.isTag(frameTitle, ItemUtils.GetTag(ItemUtils.TAG_IWIDGET))) {
+		// TODO Widgets... check this out
+		// Brook: Cannot figure what is going on above... widget annot titles
+		// should be stripped always
+		if (ItemUtils
+				.isTag(frameTitle, ItemUtils.GetTag(ItemUtils.TAG_IWIDGET))) {
 			frameTitle.stripFirstWord();
 		}
@@ -425,5 +420,5 @@
 
 		for (Item i : _body)
-			if (i.isVisible() /*&& i != _frameName*/ && i.intersects(poly)) {
+			if (i.isVisible() /* && i != _frameName */&& i.intersects(poly)) {
 				if (!results.contains(i))
 					results.add(i);
@@ -462,4 +457,9 @@
 	 */
 	public void setFrameNumber(int number) {
+		assert (number >= 0);
+
+		if (_number == number)
+			return;
+
 		_number = number;
 		boolean oldchange = _change;
@@ -469,5 +469,5 @@
 		if (_frameName != null) {
 			id = _frameName.getID();
-		} else{
+		} else {
 			id = -1 * getNextItemID();
 		}
@@ -493,5 +493,5 @@
 
 	/**
-	 * Sets the version of this Frame to the given String.
+	 * Increments the version of this Frame to the given String.
 	 * 
 	 * @param version
@@ -500,14 +500,4 @@
 	public void setVersion(int version) {
 		_version = version;
-	}
-
-	/**
-	 * Sets the format version of this Frame to the given String.
-	 * 
-	 * @param version
-	 *            The format version to use for this Frame.
-	 */
-	public void setFormatVersion(int version) {
-		_fversion = version;
 	}
 
@@ -593,6 +583,6 @@
 		if (item != null) {
 			if (_body.contains(item)) {
-				//System.out.println("Item (" + item.getClass().getSimpleName()
-				//		+ ") with ID " + item.getID() + " already in body.");
+				// System.out.println("Item (" + item.getClass().getSimpleName()
+				// + ") with ID " + item.getID() + " already in body.");
 				return;
 			}
@@ -600,5 +590,5 @@
 			if (item instanceof Line)
 				_lineCount++;
-			
+
 			_itemCount = Math.max(_itemCount, item.getID());
 
@@ -609,14 +599,15 @@
 
 			item.setMaxSize(FrameGraphics.getMaxFrameSize());
-			//add widget items to the list of widgets
+			// add widget items to the list of widgets
 			if (item instanceof WidgetCorner) {
-				InteractiveWidget iw = ((WidgetCorner)item).getWidgetSource();
-				if (!this._iWidgets.contains(iw)) { // A set would have been best
-					_iWidgets.add(iw); 
+				InteractiveWidget iw = ((WidgetCorner) item).getWidgetSource();
+				if (!this._iWidgets.contains(iw)) { // A set would have been
+													// best
+					_iWidgets.add(iw);
 				}
 			}
-			
-			item.onParentStateChanged(new ItemParentStateChangedEvent(
-					this, ItemParentStateChangedEvent.EVENT_TYPE_ADDED));
+
+			item.onParentStateChanged(new ItemParentStateChangedEvent(this,
+					ItemParentStateChangedEvent.EVENT_TYPE_ADDED));
 
 			change();
@@ -648,16 +639,15 @@
 
 	public void removeItem(Item item) {
-		if (_body.remove(item))
+		if (_body.remove(item)) {
 			change();
-		
-		// Remove widgets from the widget list
-		if (item != null) {
-			item.onParentStateChanged(new ItemParentStateChangedEvent(
-					this, ItemParentStateChangedEvent.EVENT_TYPE_REMOVED));
-			if (item instanceof WidgetCorner) {
-				_iWidgets.remove(((WidgetCorner)item).getWidgetSource()); 
-			}
-		}
-		
+			// Remove widgets from the widget list
+			if (item != null) {
+				item.onParentStateChanged(new ItemParentStateChangedEvent(this,
+						ItemParentStateChangedEvent.EVENT_TYPE_REMOVED));
+				if (item instanceof WidgetCorner) {
+					_iWidgets.remove(((WidgetCorner) item).getWidgetSource());
+				}
+			}
+		}
 	}
 
@@ -760,10 +750,13 @@
 	 * @return The version of this Frame.
 	 */
+	public int getVersion(boolean increment) {
+		// System.out.println("Version: " + _version);
+		if (increment)
+			_version++;
+		return _version;
+	}
+
 	public int getVersion() {
-		return _version;
-	}
-
-	public int getFormatVersion() {
-		return _fversion;
+		return getVersion(true);
 	}
 
@@ -843,5 +836,4 @@
 		s += "Name: " + _frameset + _number + "\n";
 		s += "Version: " + _version + "\n";
-		s += "Format Version: " + _fversion + "\n";
 		s += "Protection: " + _protection + "\n";
 		s += "Owner: " + _owner + "\n";
@@ -935,21 +927,28 @@
 	 * @param overlay
 	 *            The Frame to add
-	 *            
+	 * 
 	 * @throws NullPointerException
-	 *            If overlay is null.
+	 *             If overlay is null.
 	 */
 	public void addOverlay(Overlay overlay) {
-		if (overlay == null) throw new NullPointerException("overlay");
-		if (_overlays.contains(overlay)) return;
-		
+		if (overlay == null)
+			throw new NullPointerException("overlay");
+		// make sure we dont add this frame as an overlay of itself
+		if (overlay.Frame == this)
+			return;
+
+		if (_overlays.contains(overlay))
+			return;
+
 		_overlays.add(overlay);
-		
-		// Items must be notified that they have been added to this frame via the overlay...
+
+		// Items must be notified that they have been added to this frame via
+		// the overlay...
 		List<Item> items = new LinkedList<Item>();
-		FrameGraphics.AddAllOverlayItems(items, overlay.Frame, new LinkedList<Frame>());
+		FrameGraphics.AddAllOverlayItems(items, overlay.Frame,
+				new LinkedList<Frame>());
 		for (Item i : items) {
-			i.onParentStateChanged(new ItemParentStateChangedEvent(
-					this, 
-					ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY, 
+			i.onParentStateChanged(new ItemParentStateChangedEvent(this,
+					ItemParentStateChangedEvent.EVENT_TYPE_ADDED_VIA_OVERLAY,
 					overlay.Level));
 		}
@@ -957,50 +956,56 @@
 
 	/**
-	 * Removes the given overlay from the list of overlays being drawn with this Frame.
+	 * Removes the given overlay from the list of overlays being drawn with this
+	 * Frame.
 	 * 
 	 * @param overlay
 	 *            The overlay to remove
-	 *            
+	 * 
 	 * @throws NullPointerException
-	 *            If overlay is null.
+	 *             If overlay is null.
 	 */
 	public void removeOverlay(Overlay overlay) {
-		if (overlay == null) throw new NullPointerException("overlay");
-	
+		if (overlay == null)
+			throw new NullPointerException("overlay");
+
 		this._overlays.remove(overlay);
-		
-		// Items must be notified that they have been removed from this frame via the overlay...
+
+		// Items must be notified that they have been removed from this frame
+		// via the overlay...
 		List<Item> items = new LinkedList<Item>();
-		FrameGraphics.AddAllOverlayItems(items, overlay.Frame, new LinkedList<Frame>());
+		FrameGraphics.AddAllOverlayItems(items, overlay.Frame,
+				new LinkedList<Frame>());
 		for (Item i : items) {
-			i.onParentStateChanged(new ItemParentStateChangedEvent(
-					this, 
-					ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY, 
+			i.onParentStateChanged(new ItemParentStateChangedEvent(this,
+					ItemParentStateChangedEvent.EVENT_TYPE_REMOVED_VIA_OVERLAY,
 					overlay.Level));
 		}
 	}
-	
-	/**
-	 * Removes the given Frame from the list of overlayed Frames being drawn with
-	 * this Frame.
+
+	/**
+	 * Removes the given Frame from the list of overlayed Frames being drawn
+	 * with this Frame.
 	 * 
 	 * @param overlayedFrame
 	 *            The Frame to remove
-	 *            
+	 * 
 	 * @throws NullPointerException
-	 *            If overlayedFrame is null.
+	 *             If overlayedFrame is null.
 	 */
 	public void removeOverlay(Frame overlayedFrame) {
-		if (overlayedFrame == null) throw new NullPointerException("overlay");
-		
+		if (overlayedFrame == null)
+			throw new NullPointerException("overlay");
+
 		// Locate the oveylay(s) that match this
 		List<Overlay> overlaysToRemove = new LinkedList<Overlay>();
 		for (Overlay o : _overlays) {
-			if (overlayedFrame.equals(o.Frame)) overlaysToRemove.add(o);
-		}
-		for (Overlay o : overlaysToRemove) { // must be enumerated seperate to above...
+			if (overlayedFrame.equals(o.Frame))
+				overlaysToRemove.add(o);
+		}
+		for (Overlay o : overlaysToRemove) { // must be enumerated seperate
+												// to above...
 			removeOverlay(o);
 		}
-		
+
 	}
 
@@ -1010,7 +1015,8 @@
 		return l;
 	}
-	
-	/**
-	 * @return All overlays seen by this frame (including its overlays' overlays).
+
+	/**
+	 * @return All overlays seen by this frame (including its overlays'
+	 *         overlays).
 	 */
 	public List<Overlay> getOverlaysDeep() {
@@ -1019,34 +1025,40 @@
 		return l;
 	}
-	
-	private boolean getOverlaysDeep(List<Overlay> overlays, Frame overlay, List<Frame> seenOverlays) {
-
-			if (seenOverlays.contains(overlay))
-				return false;
-
-			seenOverlays.add(overlay);
-
-			for (Overlay o : overlay.getOverlays()) {
-				if (getOverlaysDeep(overlays, o.Frame, seenOverlays)) {
-					overlays.add(o);
-				}
-			}
-			
-			return true;
-	}
-	
+
+	private boolean getOverlaysDeep(List<Overlay> overlays, Frame overlay,
+			List<Frame> seenOverlays) {
+
+		if (seenOverlays.contains(overlay))
+			return false;
+
+		seenOverlays.add(overlay);
+
+		for (Overlay o : overlay.getOverlays()) {
+			if (getOverlaysDeep(overlays, o.Frame, seenOverlays)) {
+				overlays.add(o);
+			}
+		}
+
+		return true;
+	}
+
 	/**
 	 * Gets the overlay on this frame which owns the given item.
-	 * @param item The item - must not be null.
-	 * @return The overlay that contains the itm. Null if no overlay owns the item.
+	 * 
+	 * @param item
+	 *            The item - must not be null.
+	 * @return The overlay that contains the itm. Null if no overlay owns the
+	 *         item.
 	 */
 	public Overlay getOverlayOwner(Item item) {
-		if (item == null) throw new NullPointerException("item");
+		if (item == null)
+			throw new NullPointerException("item");
 		List<Overlay> overlays = getOverlaysDeep();
 		for (Overlay l : overlays) {
-			//if (l.Frame.containsItem(item)) return l;
-			if (item.getParent() == l.Frame) return l;
-		}
-		
+			// if (l.Frame.containsItem(item)) return l;
+			if (item.getParent() == l.Frame)
+				return l;
+		}
+
 		return null;
 	}
@@ -1089,5 +1101,5 @@
 		List<Item> copies = ItemUtils.CopyItems(toMergeWith.getItems());
 		copies.remove(toMergeWith.getFrameNameItem());
-		
+
 		for (Item i : copies) {
 			if (i.getID() >= 0) {
@@ -1143,4 +1155,5 @@
 	/**
 	 * Creates a new text item with the given text.
+	 * 
 	 * @param text
 	 * @return
Index: /trunk/src/org/expeditee/gui/FrameGraphics.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameGraphics.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/FrameGraphics.java	(revision 67)
@@ -59,4 +59,6 @@
 	public static final int MODE_XRAY = 2;
 
+	public static final Color ERROR_COLOR = Color.red;
+
 	private static int _Mode = MODE_NORMAL;
 
@@ -64,25 +66,10 @@
 	private static boolean _SupressErrors = false;
 
+	public static String MESSAGES_FRAMESET_NAME = "Messages";
 	// The link to the message frameset
-	public static Text MessageLink = new Text(-2, "Messages");
-
-	// Date\time formatter for timestamping the messages
-	/*
-	 * private static SimpleDateFormat _formatter = new SimpleDateFormat( "
-	 * [ddMMMyyyy:HHmm]");
-	 */
+	public static Text MessageLink = new Text(-2, MESSAGES_FRAMESET_NAME);
 
 	// creator for creating the message frames
 	private static FrameCreator _creator;
-
-	/**
-	 * Returns the Graphics2D object currently being used to draw with, this may
-	 * be null if no Graphics2D has been assigned yet.
-	 * 
-	 * @return the Graphics2D object being used to draw, or null.
-	 */
-	public static Graphics2D getGraphics() {
-		return _DisplayGraphics;
-	}
 
 	/**
@@ -154,5 +141,5 @@
 				MESSAGE_LINK_X);
 
-		Repaint();
+		//Repaint();
 	}
 
@@ -471,4 +458,5 @@
 	 */
 	public static void Repaint() {
+		//Thread.dumpStack();
 		if (_DisplayGraphics == null)
 			return;
@@ -627,5 +615,5 @@
 		// if the creator needs to be initialised (happens on first message)
 		if (_creator == null) {
-			_creator = new FrameCreator("Messages", true);
+			_creator = new FrameCreator(MESSAGES_FRAMESET_NAME, true);
 
 			// set up 'Messages' link on the right hand side
@@ -699,5 +687,5 @@
 		if (tokens.length > 1)
 			link = tokens[tokens.length - 1];
-		displayMessage(message, link, Color.RED);
+		displayMessage(message, link, ERROR_COLOR);
 	}
 
@@ -706,40 +694,5 @@
 			return;
 		Misc.Beep();
-		displayMessage(message, null, Color.RED);
-
-		// Michael is confused about why this code is gettting into infinite
-		// loop
-
-		/*
-		 * Exception e = new Exception();
-		 * 
-		 * try{ throw e; }catch(Exception ex){ StackTraceElement[] trace =
-		 * ex.getStackTrace(); message += " (" + trace[1].getFileName() + ":" +
-		 * trace[1].getLineNumber() + ")";
-		 * 
-		 * String source = trace[1].getClassName(); source = "src.java." +
-		 * source; source = source.replace(".", File.separator); source +=
-		 * ".java";
-		 * 
-		 * try{ BufferedReader reader = new BufferedReader(new
-		 * FileReader(source)); FrameCreator creator = new
-		 * FrameCreator("Messages", false);
-		 * 
-		 * int min = trace[1].getLineNumber() - 10; int max =
-		 * trace[1].getLineNumber() + 3;
-		 * 
-		 * int line = 0; while(reader.ready()){ if(line > min && line < max)
-		 * if(line == trace[1].getLineNumber() - 1)
-		 * creator.addText(reader.readLine(), Color.RED); else
-		 * creator.addText(reader.readLine()); else if(line > max) break; else
-		 * reader.readLine();
-		 * 
-		 * line++; }
-		 * 
-		 * reader.close();
-		 * 
-		 * displayMessage(message, creator.getCurrent(), Color.RED);
-		 * }catch(Exception ioe){ ioe.printStackTrace(); } }
-		 */
+		displayMessage(message, null, ERROR_COLOR);
 	}
 
Index: /trunk/src/org/expeditee/gui/FrameIO.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameIO.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/FrameIO.java	(revision 67)
@@ -548,4 +548,11 @@
 	}
 
+	public static void RefreshCasheImages() {
+		SuspendCache();
+		for (Frame f : _Cache.values())
+			f.setBuffer(null);
+		ResumeCache();
+	}
+
 	/**
 	 * Creates a new frameset using the given name. This includes creating a new
@@ -603,4 +610,8 @@
 	}
 
+	public static String SaveFrame(Frame toSave, boolean inc) {
+		return SaveFrame(toSave, inc, true);
+	}
+
 	/**
 	 * Saves the given Frame to disk in the corresponding frameset directory, if
@@ -613,6 +624,9 @@
 	 *            True if the saved frames counter should be incremented, false
 	 *            otherwise.
-	 */
-	public static String SaveFrame(Frame toSave, boolean inc) {
+	 * @param checkBackup
+	 *            True if the frame should be checked for the back up tag
+	 */
+	public static String SaveFrame(Frame toSave, boolean inc,
+			boolean checkBackup) {
 
 		if (toSave == null)
@@ -630,14 +644,50 @@
 				.getFrameName());
 
+		// Check if the frame exists
+		if (checkBackup && fullPath == null) {
+			// The first time a frame with the backup tag is saved, dont back it
+			// up
+			checkBackup = false;
+		}
+
 		FrameWriter writer = null;
+		int savedVersion;
 		try {
 			// if its a new frame or an existing Exp frame...
 			if (fullPath == null || fullPath.endsWith(ExpReader.EXTENTION)) {
 				writer = new ExpWriter();
+				savedVersion = ExpReader.getVersion(fullPath);
 			} else {
 				writer = new KMSWriter();
+				savedVersion = KMSReader.getVersion(fullPath);
 			}
-
-			if (toSave.getFrameNumber() > 0
+			// Check if we are trying to save an out of date version
+			if (savedVersion > toSave.getVersion(false)
+					&& !toSave.getFramesetName().equalsIgnoreCase(
+							FrameGraphics.MESSAGES_FRAMESET_NAME)) {
+				// remove this frame from the cache if it is there
+				// This will make sure links to the original are set correctly
+				_Cache.remove(toSave.getFrameName().toLowerCase());
+				int nextnum = ReadINF(toSave.path, toSave.getFramesetName()) + 1;
+				SuspendCache();
+				Frame original = LoadFrame(toSave.getFrameName());
+				toSave.setFrameNumber(nextnum);
+				ResumeCache();
+				// Put the modified version in the cache
+				_Cache.put(toSave.getFrameName().toLowerCase(), toSave);
+				// Show the messages alerting the user
+				Text originalMessage = new Text(-1);
+				originalMessage.setColor(FrameGraphics.ERROR_COLOR);
+				originalMessage.setText(original.getFrameName()
+						+ " was updated by another user.");
+				originalMessage.setLink(original.getFrameName());
+				Text yourMessage = new Text(-1);
+				yourMessage.setColor(FrameGraphics.ERROR_COLOR);
+				yourMessage.setText("Your version was renamed "
+						+ toSave.getFrameName());
+				yourMessage.setLink(toSave.getFrameName());
+				FrameGraphics.DisplayMessage(originalMessage);
+				FrameGraphics.DisplayMessage(yourMessage);
+			} else if (checkBackup
 					&& ItemUtils.ContainsTag(toSave.getItems(),
 							ItemUtils.TAG_BACKUP)) {
@@ -649,6 +699,9 @@
 				int nextnum = ReadINF(toSave.path, toSave.getFramesetName()) + 1;
 
-				original.setFrameNumber(-nextnum);
-				SaveFrame(original, inc);
+				// Give it a negative framenumber so that when it is saved the
+				// backup tag will be ignored
+				original.setFrameNumber(nextnum);
+				original.change();
+				SaveFrame(original, false, false);
 
 				Item i = ItemUtils.FindTag(toSave.getItems(),
@@ -657,6 +710,4 @@
 				toSave.setFrameNumber(orignum);
 				ResumeCache();
-			} else if (toSave.getFrameNumber() < 0) {
-				toSave.setFrameNumber(-toSave.getFrameNumber());
 			}
 
@@ -1000,5 +1051,5 @@
 				int copyNumber = 1;
 				File dest = new File(destPath + File.separator);
-				//Create the trash folder if it doesnt already exist
+				// Create the trash folder if it doesnt already exist
 				if (!dest.getParentFile().exists())
 					dest.mkdirs();
@@ -1006,5 +1057,5 @@
 				// a number to the end
 				while (dest.exists()) {
-					dest = new File(destPath + ++copyNumber + File.separator );
+					dest = new File(destPath + ++copyNumber + File.separator);
 				}
 				return framesetDirectory.renameTo(dest);
Index: /trunk/src/org/expeditee/gui/FrameKeyboardActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/FrameKeyboardActions.java	(revision 67)
@@ -17,5 +17,4 @@
 import org.expeditee.actions.Simple;
 import org.expeditee.io.Logger;
-import org.expeditee.items.Constraint;
 import org.expeditee.items.Dot;
 import org.expeditee.items.Item;
Index: /trunk/src/org/expeditee/gui/FrameMouseActions.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/FrameMouseActions.java	(revision 67)
@@ -1,4 +1,5 @@
 package org.expeditee.gui;
 
+import java.awt.Point;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -261,5 +262,5 @@
 		// pre-cache the frame if it is linked
 		if (on != null && on.getLink() != null && on.isLinkValid()) {
-			FrameIO.Precache(on.getLink());
+			FrameIO.Precache(on.getAbsoluteLink());
 		}
 
@@ -739,5 +740,6 @@
 									.getPosition(), false);
 							pickup(newPoint);
-							ItemUtils.EnclosedCheck(toDisconnect.getCurrentFrame().getItems());
+							ItemUtils.EnclosedCheck(toDisconnect
+									.getParentOrCurrentFrame().getItems());
 							return;
 						}
@@ -913,8 +915,28 @@
 
 						if (toCopy.size() > 0) {
+							//Find the closest item to the mouse cursor
+							double currentX = DisplayIO.getMouseX();
+							double currentY = DisplayIO.getMouseY();
+							Item closest = null;
+							double shortestDistance = Double.MAX_VALUE; 
+							for(int i = 0; i < toCopy.size(); i++) {
+								Item next = toCopy.get(i);
+								if (next instanceof Line)
+									continue;
+								double distance = Point.distance(currentX, currentY, next.getX(), next.getY());
+								if (distance  < shortestDistance) {
+									shortestDistance = distance;
+									closest = next;
+								}
+							}
+							//Move the cursor to closest item
+							DisplayIO.setCursorPosition(closest.getPosition());
+							//Pickup copy of the stuff inside the rectange
 							pickup(copy(toCopy));
+							//Remove the rectangle
 							DisplayIO.getCurrentFrame().removeAllItems(
 									d.getAllConnected());
 						} else {
+							//Pick up a copy of the rectangle
 							pickup(copy(d.getAllConnected()));
 						}
@@ -1443,9 +1465,13 @@
 		setTdfcItem(linker);
 
-		// Set the link for an @Parent annotation item if one is on the frame
-		for (Item i : next.getItems()) {
-			if ((i instanceof Text) && ItemUtils.isTag(i, ItemUtils.TAG_PARENT)
-					&& i.getLink() == null)
-				i.setLink(DisplayIO.getCurrentFrame().getFrameName());
+		for (Text i : next.getBodyTextItems(true)) {
+			// Set the link for @Parent annotation item if one
+			if (ItemUtils.isTag(i, ItemUtils.TAG_PARENT) && i.getLink() == null) {
+				Frame parent = linker.getParentOrCurrentFrame();
+				i.setLink(parent.getFrameName());
+			} else if (ItemUtils.isTag(i, ItemUtils.TAG_BACKUP)) {
+				// Delink backup tag if it is on the frame
+				i.setLink(null);
+			}
 		}
 
@@ -1594,6 +1620,4 @@
 			// reset the mouse cursor
 			updateCursor();
-			FrameGraphics.Repaint();
-
 			ItemUtils.EnclosedCheck(current.getItems());
 			FrameGraphics.Repaint();
@@ -1604,10 +1628,14 @@
 
 	private static void deleteItems(List<Item> itemList) {
-		Frame current = DisplayIO.getCurrentFrame();
+		List<Frame> modifiedFrames = new LinkedList<Frame>();
+		// Get a list of all the modified frames
+		for (Item i : itemList) {
+			Frame parent = i.getParent();
+			if (parent != null)
+				modifiedFrames.add(parent);
+		}
+
 		List<Item> toUndo = new LinkedList<Item>();
 		List<Item> seen = new LinkedList<Item>();
-
-		// Mike: Removed code that checked for rectangles and removed them
-		// completely!!
 
 		// disconnect any connected items
@@ -1623,28 +1651,13 @@
 					toUndo.addAll(copy(i));
 			}
-
 			seen.add(i);
 		}
-
-		// Mike: What is the point of the code below
-		// It causes problems when deleting three items off the cursor which
-		// include a non dot or line item
-		/*
-		 * // check for rectangle deletion if (itemList.size() == 3) { boolean
-		 * rectangle = false; Dot dot = null; // check that this is indeed a
-		 * rectangle for (Item check : itemList) { if (dot == null && check
-		 * instanceof Dot) dot = (Dot) check; else if (check != dot &&
-		 * !dot.getLines().contains(check)) { rectangle = false; break; } else
-		 * rectangle = true; } // if this is a rectangle, remove the entire
-		 * rectangle if (rectangle) { // List<Item> copy =
-		 * copy(dot.getAllConnected());
-		 * current.addAllToUndo(dot.getAllConnected());
-		 * current.removeAllItems(dot.getAllConnected()); itemList.clear(); //
-		 * reset the mouse cursor updateCursor(); FrameGraphics.Repaint();
-		 * return; } }
-		 */
-
-		current.removeAllItems(itemList);
-		current.addAllToUndo(itemList);
+		for (Frame f : modifiedFrames) {
+			f.removeAllItems(itemList);
+			ItemUtils.EnclosedCheck(f.getItems());
+		}
+		// TODO: How should undelete deal with undo when items are removed from
+		// the current frame as well as the overlay frame
+		DisplayIO.getCurrentFrame().addAllToUndo(itemList);
 		itemList.clear();
 	}
@@ -1964,5 +1977,5 @@
 
 		FrameGraphics.Repaint();
-		ItemUtils.EnclosedCheck(toAnchor.getCurrentFrame().getItems());
+		ItemUtils.EnclosedCheck(toAnchor.getParentOrCurrentFrame().getItems());
 	}
 
Index: /trunk/src/org/expeditee/gui/FrameUtils.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameUtils.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/FrameUtils.java	(revision 67)
@@ -302,5 +302,5 @@
 		return true;
 	}
-
+	
 	/**
 	 * Displays the given Frame on the display. If the current frame has changed
@@ -318,5 +318,5 @@
 		if (toDisplay == null)
 			return;
-
+		
 		Frame current = DisplayIO.getCurrentFrame();
 
@@ -613,5 +613,5 @@
 			}
 		}
-		return new Color[]{Color.black, Color.white};
+		return new Color[] { Color.black, Color.white };
 	}
 
@@ -1257,5 +1257,5 @@
 				for (File helpFrameset : helpFramesets) {
 					String framesetName = helpFrameset.getName();
-					Frame indexFrame = FrameIO.LoadFrame(framesetName+ '1');
+					Frame indexFrame = FrameIO.LoadFrame(framesetName + '1');
 					// Look through the folder for help index pages
 					if (indexFrame != null
Index: /trunk/src/org/expeditee/gui/MouseEventRouter.java
===================================================================
--- /trunk/src/org/expeditee/gui/MouseEventRouter.java	(revision 66)
+++ /trunk/src/org/expeditee/gui/MouseEventRouter.java	(revision 67)
@@ -95,7 +95,7 @@
 				forwardToExpiditee = true;
 			} else if (DisplayIO.getCurrentFrame() != null) { // is mouse over
-																// a specific
-																// expeditee
-																// item?
+				// a specific
+				// expeditee
+				// item?
 				// NOTE: Do not use FrameUtils.getCurrentItem() - thats relevent
 				// for old mouse position only
@@ -110,5 +110,5 @@
 						.getCurrentFrame(), containerPoint.x, containerPoint.y) != null);
 			}
-			
+
 			if (forwardToExpiditee) {
 
@@ -125,5 +125,5 @@
 				MouseEvent expediteeEvent = SwingUtilities.convertMouseEvent(e
 						.getComponent(), e, _contentPane);
-				
+
 				switch (e.getID()) {
 				case MouseEvent.MOUSE_MOVED:
@@ -131,7 +131,10 @@
 
 					// Ensure that expiditee has focus only if no popups exist
-					if (!Browser._theBrowser.getContentPane().isFocusOwner()
-							&& !isPopupVisible()) {
-						Browser._theBrowser.getContentPane().requestFocus();
+					if (Browser._theBrowser.getContentPane() != null) {
+						if (!Browser._theBrowser.getContentPane()
+								.isFocusOwner()
+								&& !isPopupVisible()) {
+							Browser._theBrowser.getContentPane().requestFocus();
+						}
 					}
 
Index: /trunk/src/org/expeditee/io/Conversion.java
===================================================================
--- /trunk/src/org/expeditee/io/Conversion.java	(revision 66)
+++ /trunk/src/org/expeditee/io/Conversion.java	(revision 67)
@@ -10,5 +10,4 @@
 import java.util.StringTokenizer;
 
-import org.expeditee.gui.DisplayIO;
 import org.expeditee.items.Item;
 import org.expeditee.items.Text;
@@ -48,4 +47,5 @@
 		}
 
+		// check if its a normal rgb code ie. 100 0 40
 		Color rgb = getRGBColor(colorCode, current);
 		if (rgb != null)
@@ -58,5 +58,5 @@
 		char c = colorCode.charAt(last);
 
-		while (c >= '0' && c <= '9') {
+		while (Character.isDigit(c)) {
 			num = c + num;
 			if (last <= 0)
@@ -69,4 +69,7 @@
 		if (num.length() > 0)
 			amount = Float.parseFloat(num);
+		
+		if(amount > 10) 
+			amount = 10;
 
 		float color[] = { 0, 0, 0 };
@@ -74,10 +77,10 @@
 		if (colorCode.toLowerCase().startsWith("red"))
 			color[0] = amount / 10;
-
-		if (colorCode.toLowerCase().startsWith("green"))
+		else if (colorCode.toLowerCase().startsWith("green"))
 			color[1] = amount / 10;
-
-		if (colorCode.toLowerCase().startsWith("blue"))
+		else if (colorCode.toLowerCase().startsWith("blue"))
 			color[2] = amount / 10;
+		else
+			return current;
 
 		return new Color(color[0], color[1], color[2]);
@@ -88,11 +91,9 @@
 
 		try {
-			String r = colorCode.substring(0, colorCode.indexOf(" "));
-			colorCode = colorCode.substring(r.length() + 1);
-
-			String g = colorCode.substring(0, colorCode.indexOf(" "));
-			colorCode = colorCode.substring(g.length() + 1);
-
-			String b = colorCode.substring(0);
+			String[] values = colorCode.trim().split("\\s+");
+			
+			String r = values.length > 0 ? values[0] : "0";
+			String g = values.length > 1 ? values[1] : "0";
+			String b = values.length > 2 ? values[2] : "0";
 
 			if (current != null && (r.startsWith("+") || r.startsWith("-"))) {
@@ -125,5 +126,5 @@
 			return new Color(color[0], color[1], color[2]);
 		} catch (Exception e) {
-			return current;
+			return null;
 		}
 	}
@@ -200,12 +201,12 @@
 		String code = "t";
 		String fontName = font.getFamily().toLowerCase();
-		
+
 		for (int i = 0; i < Text.FONT_WHEEL.length; i++) {
-			if (Text.FONT_WHEEL[i].equals(fontName)){
+			if (Text.FONT_WHEEL[i].equals(fontName)) {
 				code = "" + Text.FONT_CHARS[i];
 				break;
 			}
 		}
-		
+
 		switch (font.getStyle()) {
 		case Font.BOLD:
@@ -297,6 +298,16 @@
 	 */
 	public static int getFrameNumber(String framename) {
-		String num = framename
-				.replaceFirst("^\\w+([^\\d]+|\\d+[.][^\\d]+)", "");
+		String num = null;
+		// The framename must end in a digit
+		assert (Character.isDigit(framename.charAt(framename.length() - 1)));
+		// And start with a letter
+		assert (Character.isLetter(framename.charAt(0)));
+		// start at the end and find the first non digit char
+		for (int i = framename.length() - 2; i >= 0; i--) {
+			if (!Character.isDigit(framename.charAt(i))) {
+				num = framename.substring(i + 1);
+				break;
+			}
+		}
 
 		try {
@@ -309,5 +320,5 @@
 	/**
 	 * Returns the frameset poriton of the given Frame name (frame number
-	 * removed)
+	 * removed) converted to lower case.
 	 * 
 	 * @param frame
@@ -319,10 +330,15 @@
 	}
 
-	public static String getFrameset(String frame, boolean convertToLower) {
-		String set = frame.replaceFirst("(\\d+|[.]\\d+)$", "");
-
-		// if there is no frameset given, then add the current frameset
-		if (set.length() == 0) {
-			set = DisplayIO.getCurrentFrame().getFramesetName();
+	public static String getFrameset(String framename, boolean convertToLower) {
+		String set = null;
+		assert (Character.isDigit(framename.charAt(framename.length() - 1)));
+		// And start with a letter
+		assert (Character.isLetter(framename.charAt(0)));
+		// start at the end and find the first non digit char
+		for (int i = framename.length() - 2; i >= 0; i--) {
+			if (!Character.isDigit(framename.charAt(i))) {
+				set = framename.substring(0, i + 1);
+				break;
+			}
 		}
 
@@ -343,14 +359,16 @@
 	 */
 	public static int getJustification(String justCode) {
+		assert (justCode != null);
+		justCode = justCode.trim().toLowerCase();
 		// as read from file
 		if (justCode.length() == 1) {
 			switch (justCode.charAt(0)) {
-			case 'F':
+			case 'f':
 				return Item.JUSTIFICATION_FULL;
-			case 'L':
+			case 'l':
 				return Item.JUSTIFICATION_LEFT;
-			case 'R':
+			case 'r':
 				return Item.JUSTIFICATION_RIGHT;
-			case 'C':
+			case 'c':
 				return Item.JUSTIFICATION_CENTER;
 			}
@@ -358,5 +376,4 @@
 
 		// from the user
-		justCode = justCode.trim().toLowerCase();
 		if (justCode.equals("center"))
 			return Item.JUSTIFICATION_CENTER;
@@ -395,4 +412,6 @@
 	public static Object Convert(Class type, String value, Object orig) {
 		// System.out.println("Orig: " + orig);
+		assert (value != null);
+		value = value.trim();
 
 		if (type == String.class
@@ -401,12 +420,4 @@
 		else if (type == String.class)
 			return value;
-
-		/*
-		 * if(type == int.class || type == Integer.class){ return
-		 * Integer.parseInt(value); }
-		 * 
-		 * if(type == float.class || type == Float.class){ return
-		 * Float.parseFloat(value); }
-		 */
 
 		if (type == Font.class) {
@@ -510,4 +521,5 @@
 
 	public static Object[] Convert(Method method, String value, Object current) {
+		value = value.trim();
 
 		String name = method.getName();
Index: /trunk/src/org/expeditee/io/DefaultFrameWriter.java
===================================================================
--- /trunk/src/org/expeditee/io/DefaultFrameWriter.java	(revision 66)
+++ /trunk/src/org/expeditee/io/DefaultFrameWriter.java	(revision 67)
@@ -4,8 +4,11 @@
 import java.io.FileWriter;
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
 
 import org.expeditee.gui.Frame;
 import org.expeditee.gui.FrameIO;
 import org.expeditee.items.Item;
+import org.expeditee.items.Text;
 
 public abstract class DefaultFrameWriter extends ItemWriter implements
@@ -23,4 +26,83 @@
 
 	protected boolean _stop = false;
+
+	// keep track of methods that are put on the same line
+	protected static LinkedHashMap<String, Method> _ItemTags = null;
+
+	protected static LinkedHashMap<String, Method> _FrameTags = null;
+
+	public DefaultFrameWriter() {
+		if (_ItemTags != null && _FrameTags != null)
+			return;
+
+		_ItemTags = new LinkedHashMap<String, Method>();
+		_FrameTags = new LinkedHashMap<String, Method>();
+
+		Class[] param = {};
+
+		try {
+			_FrameTags.put("A", Frame.class.getMethod("getFrameName", param));
+			_FrameTags.put("V", Frame.class.getMethod("getVersion", param));
+			_FrameTags.put("p", Frame.class.getMethod("getProtection", param));
+			_FrameTags.put("U", Frame.class.getMethod("getOwner", param));
+			_FrameTags.put("D", Frame.class.getMethod("getDateCreated", param));
+			_FrameTags.put("M", Frame.class.getMethod("getLastModifyUser",
+					param));
+			_FrameTags.put("d", Frame.class.getMethod("getLastModifyDate",
+					param));
+			_FrameTags.put("F", Frame.class.getMethod("getFrozenDate", param));
+
+			_FrameTags.put("O", Frame.class.getMethod("getForegroundColor",
+					param));
+			_FrameTags.put("B", Frame.class.getMethod("getBackgroundColor",
+					param));
+			_ItemTags.put("S", Item.class.getMethod("getTypeAndID", param));
+			_ItemTags.put("s", Item.class.getMethod("getDateCreated", param));
+			_ItemTags.put("d", Item.class.getMethod("getColor", param));
+			_ItemTags.put("G", Item.class
+					.getMethod("getBackgroundColor", param));
+			_ItemTags.put("P", Item.class.getMethod("getPosition", param));
+			_ItemTags.put("F", Item.class.getMethod("getLink", param));
+			_ItemTags.put("X", Item.class.getMethod("getAction", param));
+			_ItemTags.put("x", Item.class.getMethod("getActionMark", param));
+			_ItemTags.put("U", Item.class.getMethod("getActionCursorEnter",
+					param));
+			_ItemTags.put("V", Item.class.getMethod("getActionCursorLeave",
+					param));
+			_ItemTags.put("W", Item.class.getMethod("getActionEnterFrame",
+					param));
+			_ItemTags.put("Y", Item.class.getMethod("getActionLeaveFrame",
+					param));
+			_ItemTags.put("D", Item.class.getMethod("getData", param));
+			_ItemTags.put("u", Item.class.getMethod("getHighlight", param));
+			_ItemTags.put("e", Item.class.getMethod("getFillColor", param));
+			_ItemTags.put("i", Item.class.getMethod("getFillPattern", param));
+			_ItemTags.put("o", Item.class.getMethod("getOwner", param));
+			_ItemTags.put("n", Item.class.getMethod("getLinkMark", param));
+			_ItemTags.put("q", Item.class.getMethod("getLinkFrameset", param));
+			_ItemTags.put("y", Item.class.getMethod("getLinkTemplate", param));
+			_ItemTags.put("g", Item.class.getMethod("getLinePattern", param));
+
+			_ItemTags.put("j", Item.class.getMethod("getArrow", param));
+
+			_ItemTags.put("f", Text.class.getMethod("getFont", param));
+			_ItemTags.put("t", Text.class.getMethod("getSpacing", param));
+			_ItemTags.put("T", Text.class.getMethod("getText", param));
+
+			_ItemTags.put("a", Text.class.getMethod("getWordSpacing", param));
+			_ItemTags.put("b", Text.class.getMethod("getLetterSpacing", param));
+			_ItemTags
+					.put("m", Text.class.getMethod("getInitialSpacing", param));
+			_ItemTags.put("w", Text.class.getMethod("getWidth", param));
+			_ItemTags.put("k", Text.class.getMethod("getJustification", param));
+
+			_ItemTags.put("h", Item.class.getMethod("getThickness", param));
+			_ItemTags.put("l", Item.class.getMethod("getLineIDs", param));
+			_ItemTags.put("c", Item.class.getMethod("getConstraintIDs", param));
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
 
 	public void setOutputLocation(String filename) {
@@ -125,3 +207,4 @@
 		return "Not Supported";
 	}
+
 }
Index: /trunk/src/org/expeditee/io/ExpReader.java
===================================================================
--- /trunk/src/org/expeditee/io/ExpReader.java	(revision 66)
+++ /trunk/src/org/expeditee/io/ExpReader.java	(revision 67)
@@ -1,7 +1,4 @@
 package org.expeditee.io;
 
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Point;
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -9,6 +6,4 @@
 import java.lang.reflect.Method;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
 
 import org.expeditee.gui.Frame;
@@ -26,5 +21,5 @@
  * 
  */
-public class ExpReader implements FrameReader {
+public class ExpReader extends FrameReader {
 
 	public static final String EXTENTION = ".exp";
@@ -32,8 +27,4 @@
 	private BufferedReader _reader = null;
 
-	private static LinkedHashMap<Character, Method> _ItemTags = null;
-
-	private static LinkedHashMap<Character, Method> _FrameTags = null;
-
 	private String _frameName;
 
@@ -42,97 +33,7 @@
 	 */
 	public ExpReader(String frameName) {
+		super();
+
 		_frameName = frameName;
-
-		if (_ItemTags != null && _FrameTags != null)
-			return;
-
-		_ItemTags = new LinkedHashMap<Character, Method>();
-		_FrameTags = new LinkedHashMap<Character, Method>();
-
-		Class[] pString = { String.class };
-		Class[] pInt = { int.class };
-		Class[] pFloat = { float.class };
-		Class[] pColor = { Color.class };
-		Class[] pBool = { boolean.class };
-		Class[] pFont = { Font.class };
-		Class[] pPoint = { Point.class };
-		Class[] pArrow = { int.class, double.class };
-		Class[] pList = { List.class };
-		Class[] pIntArray = { int[].class };
-		Class[] pItem = { Item.class };
-
-		try {
-			_FrameTags.put('V', Frame.class.getMethod("setVersion", pInt));
-			_FrameTags
-					.put('p', Frame.class.getMethod("setProtection", pString));
-			_FrameTags.put('U', Frame.class.getMethod("setOwner", pString));
-			_FrameTags.put('D', Frame.class
-					.getMethod("setDateCreated", pString));
-			_FrameTags.put('M', Frame.class.getMethod("setLastModifyUser",
-					pString));
-			_FrameTags.put('d', Frame.class.getMethod("setLastModifyDate",
-					pString));
-			_FrameTags
-					.put('F', Frame.class.getMethod("setFrozenDate", pString));
-
-			_FrameTags.put('O', Frame.class.getMethod("setForegroundColor",
-					pColor));
-			_FrameTags.put('B', Frame.class.getMethod("setBackgroundColor",
-					pColor));
-
-			_ItemTags.put('S', Item.class.getMethod("setID", pInt));
-			_ItemTags.put('s', Item.class.getMethod("setDateCreated", pString));
-			_ItemTags.put('d', Item.class.getMethod("setColor", pColor));
-			_ItemTags.put('G', Item.class.getMethod("setBackgroundColor",
-					pColor));
-			_ItemTags.put('P', Item.class.getMethod("setPosition", pPoint));
-			_ItemTags.put('F', Item.class.getMethod("setLink", pString));
-			_ItemTags.put('X', Item.class.getMethod("setAction", pList));
-			_ItemTags.put('x', Item.class.getMethod("setActionMark", pBool));
-			_ItemTags.put('U', Item.class.getMethod("setActionCursorEnter",
-					pList));
-			_ItemTags.put('V', Item.class.getMethod("setActionCursorLeave",
-					pList));
-			_ItemTags.put('W', Item.class.getMethod("setActionEnterFrame",
-					pList));
-			_ItemTags.put('Y', Item.class.getMethod("setActionLeaveFrame",
-					pList));
-			_ItemTags.put('D', Item.class.getMethod("setData", pString));
-			_ItemTags.put('u', Item.class.getMethod("setHighlight", pBool));
-			_ItemTags.put('e', Item.class.getMethod("setFillColor", pColor));
-			_ItemTags.put('i', Item.class.getMethod("setFillPattern", pString));
-			_ItemTags.put('o', Item.class.getMethod("setOwner", pString));
-			_ItemTags.put('n', Item.class.getMethod("setLinkMark", pBool));
-			_ItemTags
-					.put('q', Item.class.getMethod("setLinkFrameset", pString));
-			_ItemTags
-					.put('y', Item.class.getMethod("setLinkTemplate", pString));
-			_ItemTags.put('g', Item.class
-					.getMethod("setLinePattern", pIntArray));
-
-			_ItemTags.put('j', Item.class.getMethod("setArrow", pArrow));
-
-			_ItemTags.put('f', Text.class.getMethod("setFont", pFont));
-			_ItemTags.put('t', Text.class.getMethod("setSpacing", pInt));
-			_ItemTags.put('T', Text.class.getMethod("appendLine", pString));
-
-			_ItemTags.put('a', Text.class.getMethod("setWordSpacing", pInt));
-			_ItemTags.put('b', Text.class.getMethod("setLetterSpacing", pInt));
-			_ItemTags.put('m', Text.class.getMethod("setInitialSpacing", pInt));
-			_ItemTags.put('w', Text.class.getMethod("setWidth", pInt));
-			_ItemTags.put('k', Text.class.getMethod("setJustification", pInt));
-
-			_ItemTags.put('h', Item.class.getMethod("setThickness", pFloat));
-			_ItemTags.put('l', Item.class.getMethod("setLineIDs", pString));
-			_ItemTags.put('c', Item.class
-					.getMethod("setConstraintIDs", pString));
-
-			// Lines and constraints are created differently
-			_ItemTags.put('L', Line.class.getMethod("setStartItem", pItem));
-			_ItemTags.put('C', Constraint.class.getMethod("getID",
-					(Class[]) null));
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
 	}
 
@@ -144,5 +45,5 @@
 	 * @return true if s begins with a KMS tag
 	 */
-	private boolean isValidLine(String s) {
+	private static boolean isValidLine(String s) {
 		return s.length() >= 2 && s.charAt(1) == ' '
 				&& Character.isLetter(s.charAt(0));
@@ -280,10 +181,10 @@
 	}
 
-	private Character getTag(String line) {
+	private static Character getTag(String line) {
 		assert (line.length() > 0);
 		return line.charAt(0);
 	}
 
-	private String getValue(String line) {
+	private static String getValue(String line) {
 		if (line.length() > 2)
 			return line.substring(2);
@@ -309,6 +210,8 @@
 
 		if (toRun == null) {
-			System.out.println("Tag '" + tag + "' in '" + line
-					+ "' is not supported.");
+			if (tag != 'v') {
+				System.out.println("Tag '" + tag + "' in '" + line
+						+ "' is not supported.");
+			}
 			return;
 		}
@@ -331,3 +234,21 @@
 		return new java.awt.Point(x, y);
 	}
+
+	public static int getVersion(String fullpath) {
+		try {
+			BufferedReader reader = new BufferedReader(new FileReader(fullpath));
+			String next = "";
+			// First read the header lines until we get the version number
+			while (reader.ready() && !(next = reader.readLine()).equals("Z")) {
+				if (isValidLine(next)) {
+					Character tag = getTag(next);
+					String value = getValue(next);
+					if (tag.equals('V'))
+						return Integer.parseInt(value);
+				}
+			}
+		} catch (Exception e) {
+		}
+		return 0;
+	}
 }
Index: /trunk/src/org/expeditee/io/ExpWriter.java
===================================================================
--- /trunk/src/org/expeditee/io/ExpWriter.java	(revision 66)
+++ /trunk/src/org/expeditee/io/ExpWriter.java	(revision 67)
@@ -1,5 +1,4 @@
 package org.expeditee.io;
 
-import java.awt.Rectangle;
 import java.io.File;
 import java.io.FileWriter;
@@ -7,5 +6,4 @@
 import java.lang.reflect.Method;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -17,5 +15,4 @@
 import org.expeditee.items.Line;
 import org.expeditee.items.Picture;
-import org.expeditee.items.Text;
 import org.expeditee.items.WidgetCorner;
 import org.expeditee.items.WidgetEdge;
@@ -34,83 +31,8 @@
 	private StringBuilder _stringWriter = null;
 
-	// keep track of methods that are put on the same line
-	private static LinkedHashMap<String, Method> _ItemTags = null;
-
-	private static LinkedHashMap<String, Method> _FrameTags = null;
-
 	private static final char TERMINATOR = 'Z';
 
 	public ExpWriter() {
-		if (_ItemTags != null && _FrameTags != null)
-			return;
-
-		_ItemTags = new LinkedHashMap<String, Method>();
-		_FrameTags = new LinkedHashMap<String, Method>();
-
-		Class[] param = {};
-
-		try {
-			_FrameTags.put("V", Frame.class.getMethod("getVersion", param));
-			_FrameTags.put("p", Frame.class.getMethod("getProtection", param));
-			_FrameTags.put("U", Frame.class.getMethod("getOwner", param));
-			_FrameTags.put("D", Frame.class.getMethod("getDateCreated", param));
-			_FrameTags.put("M", Frame.class.getMethod("getLastModifyUser",
-					param));
-			_FrameTags.put("d", Frame.class.getMethod("getLastModifyDate",
-					param));
-			_FrameTags.put("F", Frame.class.getMethod("getFrozenDate", param));
-
-			_FrameTags.put("O", Frame.class.getMethod("getForegroundColor",
-					param));
-			_FrameTags.put("B", Frame.class.getMethod("getBackgroundColor",
-					param));
-
-			_ItemTags.put("S", Item.class.getMethod("getTypeAndID", param));
-			_ItemTags.put("s", Item.class.getMethod("getDateCreated", param));
-			_ItemTags.put("d", Item.class.getMethod("getColor", param));
-			_ItemTags.put("G", Item.class
-					.getMethod("getBackgroundColor", param));
-			_ItemTags.put("P", Item.class.getMethod("getPosition", param));
-			_ItemTags.put("F", Item.class.getMethod("getLink", param));
-			_ItemTags.put("X", Item.class.getMethod("getAction", param));
-			_ItemTags.put("x", Item.class.getMethod("getActionMark", param));
-			_ItemTags.put("U", Item.class.getMethod("getActionCursorEnter",
-					param));
-			_ItemTags.put("V", Item.class.getMethod("getActionCursorLeave",
-					param));
-			_ItemTags.put("W", Item.class.getMethod("getActionEnterFrame",
-					param));
-			_ItemTags.put("Y", Item.class.getMethod("getActionLeaveFrame",
-					param));
-			_ItemTags.put("D", Item.class.getMethod("getData", param));
-			_ItemTags.put("u", Item.class.getMethod("getHighlight", param));
-			_ItemTags.put("e", Item.class.getMethod("getFillColor", param));
-			_ItemTags.put("i", Item.class.getMethod("getFillPattern", param));
-			_ItemTags.put("o", Item.class.getMethod("getOwner", param));
-			_ItemTags.put("n", Item.class.getMethod("getLinkMark", param));
-			_ItemTags.put("q", Item.class.getMethod("getLinkFrameset", param));
-			_ItemTags.put("y", Item.class.getMethod("getLinkTemplate", param));
-			_ItemTags.put("g", Item.class.getMethod("getLinePattern", param));
-
-			_ItemTags.put("j", Item.class.getMethod("getArrow", param));
-
-			_ItemTags.put("f", Text.class.getMethod("getFont", param));
-			_ItemTags.put("t", Text.class.getMethod("getSpacing", param));
-			_ItemTags.put("T", Text.class.getMethod("getText", param));
-
-			_ItemTags.put("a", Text.class.getMethod("getWordSpacing", param));
-			_ItemTags.put("b", Text.class.getMethod("getLetterSpacing", param));
-			_ItemTags
-					.put("m", Text.class.getMethod("getInitialSpacing", param));
-			_ItemTags.put("w", Text.class.getMethod("getWidth", param));
-			_ItemTags.put("k", Text.class.getMethod("getJustification", param));
-
-			_ItemTags.put("h", Item.class.getMethod("getThickness", param));
-			_ItemTags.put("l", Item.class.getMethod("getLineIDs", param));
-			_ItemTags.put("c", Item.class.getMethod("getConstraintIDs", param));
-
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+		super();
 	}
 
@@ -128,4 +50,10 @@
 		} else
 			_writer = new ProxyWriter(new FileWriter(_filename));
+		
+		try {
+			_ItemTags.put("S", Item.class.getMethod("getTypeAndID", new Class[] {}));
+		} catch (Exception e) {
+
+		}
 	}
 
@@ -225,5 +153,5 @@
 		// Dont save the item if it is off the screen
 		if (item.offScreen()) {
-			System.out.println("item offscreen!");
+			//System.out.println("item offscreen!");
 			return;
 		}
Index: /trunk/src/org/expeditee/io/FrameReader.java
===================================================================
--- /trunk/src/org/expeditee/io/FrameReader.java	(revision 66)
+++ /trunk/src/org/expeditee/io/FrameReader.java	(revision 67)
@@ -1,11 +1,118 @@
 package org.expeditee.io;
 
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Point;
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.LinkedHashMap;
+import java.util.List;
 
 import org.expeditee.gui.Frame;
+import org.expeditee.items.Constraint;
+import org.expeditee.items.Item;
+import org.expeditee.items.Line;
+import org.expeditee.items.Text;
 
-public interface FrameReader {
+public abstract class FrameReader {
+	protected static LinkedHashMap<Character, Method> _ItemTags = null;
 
-	public abstract Frame readFrame(String fullPath)
-			throws IOException;
+	protected static LinkedHashMap<Character, Method> _FrameTags = null;
+	
+	protected static Class[] pString = { String.class };
+	protected static Class[] pInt = { int.class };
+	protected static Class[] pFloat = { float.class };
+	protected static Class[] pColor = { Color.class };
+	protected static Class[] pBool = { boolean.class };
+	protected static Class[] pFont = { Font.class };
+	protected static Class[] pPoint = { Point.class };
+	protected static Class[] pArrow = { int.class, double.class };
+	protected static Class[] pList = { List.class };
+	protected static Class[] pIntArray = { int[].class };
+	protected static Class[] pItem = { Item.class };
+	
+	public FrameReader(){
+		if (_ItemTags != null && _FrameTags != null)
+			return;
+
+		_ItemTags = new LinkedHashMap<Character, Method>();
+		_FrameTags = new LinkedHashMap<Character, Method>();
+
+		try {
+			_FrameTags.put('A', Frame.class.getMethod("setFrameName", pString));
+			_FrameTags.put('V', Frame.class.getMethod("setVersion", pInt));
+			_FrameTags
+					.put('p', Frame.class.getMethod("setProtection", pString));
+			_FrameTags.put('U', Frame.class.getMethod("setOwner", pString));
+			_FrameTags.put('D', Frame.class
+					.getMethod("setDateCreated", pString));
+			_FrameTags.put('M', Frame.class.getMethod("setLastModifyUser",
+					pString));
+			_FrameTags.put('d', Frame.class.getMethod("setLastModifyDate",
+					pString));
+			_FrameTags
+					.put('F', Frame.class.getMethod("setFrozenDate", pString));
+
+			_FrameTags.put('O', Frame.class.getMethod("setForegroundColor",
+					pColor));
+			_FrameTags.put('B', Frame.class.getMethod("setBackgroundColor",
+					pColor));
+
+			_ItemTags.put('S', Item.class.getMethod("setID", pInt));
+			_ItemTags.put('s', Item.class.getMethod("setDateCreated", pString));
+			_ItemTags.put('d', Item.class.getMethod("setColor", pColor));
+			_ItemTags.put('G', Item.class.getMethod("setBackgroundColor",
+					pColor));
+			_ItemTags.put('P', Item.class.getMethod("setPosition", pPoint));
+			_ItemTags.put('F', Item.class.getMethod("setLink", pString));
+			_ItemTags.put('X', Item.class.getMethod("setAction", pList));
+			_ItemTags.put('x', Item.class.getMethod("setActionMark", pBool));
+			_ItemTags.put('U', Item.class.getMethod("setActionCursorEnter",
+					pList));
+			_ItemTags.put('V', Item.class.getMethod("setActionCursorLeave",
+					pList));
+			_ItemTags.put('W', Item.class.getMethod("setActionEnterFrame",
+					pList));
+			_ItemTags.put('Y', Item.class.getMethod("setActionLeaveFrame",
+					pList));
+			_ItemTags.put('D', Item.class.getMethod("setData", pString));
+			_ItemTags.put('u', Item.class.getMethod("setHighlight", pBool));
+			_ItemTags.put('e', Item.class.getMethod("setFillColor", pColor));
+			_ItemTags.put('i', Item.class.getMethod("setFillPattern", pString));
+			_ItemTags.put('o', Item.class.getMethod("setOwner", pString));
+			_ItemTags.put('n', Item.class.getMethod("setLinkMark", pBool));
+			_ItemTags
+					.put('q', Item.class.getMethod("setLinkFrameset", pString));
+			_ItemTags
+					.put('y', Item.class.getMethod("setLinkTemplate", pString));
+			_ItemTags.put('g', Item.class
+					.getMethod("setLinePattern", pIntArray));
+
+			_ItemTags.put('j', Item.class.getMethod("setArrow", pArrow));
+
+			_ItemTags.put('f', Text.class.getMethod("setFont", pFont));
+			_ItemTags.put('t', Text.class.getMethod("setSpacing", pInt));
+			_ItemTags.put('T', Text.class.getMethod("appendLine", pString));
+
+			_ItemTags.put('a', Text.class.getMethod("setWordSpacing", pInt));
+			_ItemTags.put('b', Text.class.getMethod("setLetterSpacing", pInt));
+			_ItemTags.put('m', Text.class.getMethod("setInitialSpacing", pInt));
+			_ItemTags.put('w', Text.class.getMethod("setWidth", pInt));
+			_ItemTags.put('k', Text.class.getMethod("setJustification", pInt));
+
+			_ItemTags.put('h', Item.class.getMethod("setThickness", pFloat));
+			_ItemTags.put('l', Item.class.getMethod("setLineIDs", pString));
+			_ItemTags.put('c', Item.class
+					.getMethod("setConstraintIDs", pString));
+			// Lines and constraints are created differently
+			_ItemTags.put('L', Line.class.getMethod("setStartItem", pItem));
+			_ItemTags.put('C', Constraint.class.getMethod("getID",
+					(Class[]) null));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		
+	}
+	
+	public abstract Frame readFrame(String fullPath) throws IOException;
 }
Index: /trunk/src/org/expeditee/io/KMSReader.java
===================================================================
--- /trunk/src/org/expeditee/io/KMSReader.java	(revision 66)
+++ /trunk/src/org/expeditee/io/KMSReader.java	(revision 67)
@@ -1,7 +1,4 @@
 package org.expeditee.io;
 
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Point;
 import java.io.BufferedReader;
 import java.io.FileReader;
@@ -13,5 +10,4 @@
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.List;
 
 import org.expeditee.gui.Frame;
@@ -30,5 +26,5 @@
  * 
  */
-public class KMSReader implements FrameReader {
+public class KMSReader extends FrameReader {
 
 	private BufferedReader _reader = null;
@@ -48,21 +44,7 @@
 		_FrameTags = new LinkedHashMap<String, Method>();
 
-		Class[] pString = { String.class };
-		Class[] pInt = { int.class };
-		Class[] pFloat = { float.class };
-		Class[] pColor = { Color.class };
-		Class[] pBool = { boolean.class };
-		Class[] pFont = { Font.class };
-		Class[] pPoint = { Point.class };
-		Class[] pArrow = { int.class, double.class };
-		Class[] pList = { List.class };
-		Class[] pIntArray = { int[].class };
-		Class[] pItem = { Item.class };
-
 		try {
 			_FrameTags.put("A", Frame.class.getMethod("setFrameName", pString));
 			_FrameTags.put("V", Frame.class.getMethod("setVersion", pInt));
-			_FrameTags
-					.put("v", Frame.class.getMethod("setFormatVersion", pInt));
 			_FrameTags
 					.put("p", Frame.class.getMethod("setProtection", pString));
@@ -152,5 +134,5 @@
 	 * @return true if s begins with a KMS tag
 	 */
-	private boolean isValidLine(String s) {
+	private static boolean isValidLine(String s) {
 		return s.length() >= 3 && s.charAt(0) == '+' && s.charAt(2) == '+'
 				&& Character.isLetter(s.charAt(1));
@@ -332,5 +314,5 @@
 	}
 
-	private String getTag(String line) {
+	private static String getTag(String line) {
 		assert (line.charAt(0) == '+');
 		assert (line.length() > 2);
@@ -338,5 +320,5 @@
 	}
 
-	private String getValue(String line) {
+	private static String getValue(String line) {
 		assert (line.charAt(0) == '+');
 		if (line.length() > 4)
@@ -365,5 +347,5 @@
 
 		if (_FrameTags.get(tag) == null) {
-			if (!tag.equals("t"))
+			if (!tag.equals("t") && !tag.equals("v") )
 				FrameGraphics.ErrorMessage("Tag '" + tag + "' in '" + line
 						+ "' is not supported.");
@@ -530,3 +512,23 @@
 		return toMake;
 	}
+	
+	public static int getVersion(String fullpath) {
+		try {
+			BufferedReader reader = new BufferedReader(new FileReader(fullpath));
+			String next = "";
+			// First read the header lines until we get the version number
+			while (reader.ready() && (next = reader.readLine())!= null) {
+				if (isValidLine(next)) {
+					char tag = getTag(next).charAt(0);
+					String value = getValue(next);
+					if (tag == 'V')
+						return Integer.parseInt(value);
+					else if(tag == 'Z')
+						return 0;
+				}
+			}
+		} catch (Exception e) {
+		}
+		return 0;
+	}
 }
Index: /trunk/src/org/expeditee/io/KMSWriter.java
===================================================================
--- /trunk/src/org/expeditee/io/KMSWriter.java	(revision 66)
+++ /trunk/src/org/expeditee/io/KMSWriter.java	(revision 67)
@@ -7,5 +7,4 @@
 import java.lang.reflect.Method;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -17,5 +16,4 @@
 import org.expeditee.items.Line;
 import org.expeditee.items.Picture;
-import org.expeditee.items.Text;
 import org.expeditee.stats.SessionStats;
 
@@ -32,11 +30,4 @@
 	private StringBuilder _stringWriter = null;
 
-	// keep track of methods that are put on the same line
-	private static LinkedHashMap<String, Method> _ItemTags = null;
-
-	private static LinkedHashMap<String, Method> _FrameTags = null;
-
-	private static LinkedHashMap<String, Method> _BodyTags = null;
-
 	private static final char TERMINATOR = 'Z';
 
@@ -44,96 +35,5 @@
 
 	public KMSWriter() {
-		if (_ItemTags != null && _FrameTags != null)
-			return;
-
-		_ItemTags = new LinkedHashMap<String, Method>();
-		_FrameTags = new LinkedHashMap<String, Method>();
-		_BodyTags = new LinkedHashMap<String, Method>();
-
-		Class[] param = {};
-
-		try {
-			_FrameTags.put("A", Frame.class.getMethod("getFrameName", param));
-			_FrameTags.put("V", Frame.class.getMethod("getVersion", param));
-			_FrameTags.put("v", Frame.class
-					.getMethod("getFormatVersion", param));
-			_FrameTags.put("p", Frame.class.getMethod("getProtection", param));
-			_FrameTags.put("U", Frame.class.getMethod("getOwner", param));
-			_FrameTags.put("D", Frame.class.getMethod("getDateCreated", param));
-			_FrameTags.put("M", Frame.class.getMethod("getLastModifyUser",
-					param));
-			_FrameTags.put("d", Frame.class.getMethod("getLastModifyDate",
-					param));
-			_FrameTags.put("F", Frame.class.getMethod("getFrozenDate", param));
-
-			_BodyTags.put("O", Frame.class.getMethod("getForegroundColor",
-					param));
-			_BodyTags.put("B", Frame.class.getMethod("getBackgroundColor",
-					param));
-			_BodyTags
-					.put("v", Frame.class.getMethod("getFormatVersion", param));
-
-			_ItemTags.put("S", Item.class.getMethod("getID", param));
-			_ItemTags.put("s", Item.class.getMethod("getDateCreated", param));
-			_ItemTags.put("d", Item.class.getMethod("getColor", param));
-			_ItemTags.put("G", Item.class
-					.getMethod("getBackgroundColor", param));
-			_ItemTags.put("P", Item.class.getMethod("getPosition", param));
-			_ItemTags.put("F", Item.class.getMethod("getLink", param));
-			_ItemTags.put("X", Item.class.getMethod("getAction", param));
-			_ItemTags.put("x", Item.class.getMethod("getActionMark", param));
-			_ItemTags.put("U", Item.class.getMethod("getActionCursorEnter",
-					param));
-			_ItemTags.put("V", Item.class.getMethod("getActionCursorLeave",
-					param));
-			_ItemTags.put("W", Item.class.getMethod("getActionEnterFrame",
-					param));
-			_ItemTags.put("Y", Item.class.getMethod("getActionLeaveFrame",
-					param));
-			_ItemTags.put("D", Item.class.getMethod("getData", param));
-			_ItemTags.put("u", Item.class.getMethod("getHighlight", param));
-			_ItemTags.put("e", Item.class.getMethod("getFillColor", param));
-			_ItemTags.put("i", Item.class.getMethod("getFillPattern", param));
-			_ItemTags.put("o", Item.class.getMethod("getOwner", param));
-			_ItemTags.put("n", Item.class.getMethod("getLinkMark", param));
-			_ItemTags.put("q", Item.class.getMethod("getLinkFrameset", param));
-			_ItemTags.put("y", Item.class.getMethod("getLinkTemplate", param));
-			_ItemTags.put("g", Item.class.getMethod("getLinePattern", param));
-
-			_ItemTags.put("j", Item.class.getMethod("getArrow", param));
-
-			_ItemTags.put("f", Text.class.getMethod("getFont", param));
-			_ItemTags.put("t", Text.class.getMethod("getSpacing", param));
-			_ItemTags.put("T", Text.class.getMethod("getText", param));
-
-			_ItemTags.put("a", Text.class.getMethod("getWordSpacing", param));
-			_ItemTags.put("b", Text.class.getMethod("getLetterSpacing", param));
-			_ItemTags
-					.put("m", Text.class.getMethod("getInitialSpacing", param));
-			_ItemTags.put("w", Text.class.getMethod("getWidth", param));
-			_ItemTags.put("k", Text.class.getMethod("getJustification", param));
-
-			_ItemTags.put("h", Dot.class.getMethod("getThickness", param));
-			_ItemTags.put("l", Dot.class.getMethod("getLineIDs", param));
-			_ItemTags.put("c", Dot.class.getMethod("getConstraintIDs", param));
-
-			// Lines and constraints are created differently
-			/*
-			 * _LineTags.put("L", Line.class.getMethod("getID", param));
-			 * _LineTags.put("s", Line.class.getMethod("getLineEnds", param));
-			 * _LineTags.put("g", Line.class.getMethod("getLinePattern",
-			 * param));
-			 * 
-			 * _ConstraintTags.put("C", Constraint.class.getMethod("getID",
-			 * (Class[]) null)); _ConstraintTags.put("s",
-			 * Constraint.class.getMethod("getLineEnds", (Class[]) null));
-			 */
-		} catch (SecurityException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		} catch (NoSuchMethodException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
+		super();
 	}
 
@@ -152,4 +52,9 @@
 			_writer = new ProxyWriter(new FileWriter(_filename));
 
+		try {
+			_ItemTags.put("S", Item.class.getMethod("getID", new Class[] {}));
+		} catch (Exception e) {
+
+		}
 		// _writer = new BufferedWriter(new FileWriter(filepath.toLowerCase() +
 		// filename.toLowerCase()));
@@ -171,5 +76,4 @@
 
 		writeHeader(frame);
-		// writeBody(frame);
 
 		// write out each Item in the Frame.
@@ -192,4 +96,7 @@
 		Iterator<String> it = _FrameTags.keySet().iterator();
 		Object[] param = {};
+
+		// Write the version tag
+		writeLine("v", "22");
 
 		while (it.hasNext()) {
@@ -212,27 +119,4 @@
 			}
 		}
-
-		writeTerminator();
-		it = _BodyTags.keySet().iterator();
-
-		while (it.hasNext()) {
-			String tag = it.next();
-			try {
-				Object o = _BodyTags.get(tag).invoke(toWrite, param);
-				o = Conversion.ConvertToKMS(_BodyTags.get(tag), o);
-				if (o != null) {
-					writeLine(tag, (String) o);
-				}
-			} catch (IllegalArgumentException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			} catch (IllegalAccessException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			} catch (InvocationTargetException e) {
-				// TODO Auto-generated catch block
-				e.printStackTrace();
-			}
-		}
 	}
 
@@ -267,16 +151,8 @@
 			item = ((Picture) item).getText();
 
-		/*
-		 * if(item instanceof Text) writeClass(item); else if(item instanceof
-		 * Dot) writeDot((Dot) item);
-		 */
 		if (item.getLines().size() > 0)
 			writePoint(item);
 		else if (!(item instanceof Line))
 			writeClass(item);
-		// lines are saved at the end of the file
-		/*
-		 * else if (item instanceof Line) ;
-		 */
 		else
 			System.out.println("Unknown Item: " + item.getID());
@@ -338,6 +214,5 @@
 						if (_points.contains(c.getStart())
 								&& _points.contains(c.getEnd())) {
-							writeLine("C", c.getID() + " "
-									+ c.getType());
+							writeLine("C", c.getID() + " " + c.getType());
 							writeLine("s", c.getLineEnds());
 						}
@@ -348,5 +223,4 @@
 			// remove the point from the list
 			_points.remove(0);
-
 		}
 	}
@@ -354,5 +228,5 @@
 	@Override
 	protected String finaliseFrame() throws IOException {
-		writeLine("" + DELIMITER + TERMINATOR + DELIMITER);
+		writeTerminator();
 
 		writeLine(SessionStats.getFrameEventList());
@@ -399,72 +273,5 @@
 			}
 		}
-
-		/*
-		 * Method[] methods = toWrite.getClass().getMethods(); ArrayList<String>
-		 * meths = new ArrayList<String>();
-		 * 
-		 * for(Method m : methods) meths.add(m.getName());
-		 * 
-		 * String start = _Tags.get("DelimiterStart"); String end =
-		 * _Tags.get("DelimiterEnd");
-		 * 
-		 * Iterator<String> it = _Tags.keySet().iterator();
-		 * 
-		 * String term = null; LinkedList<Method> seen = new LinkedList<Method>();
-		 * 
-		 * while(it.hasNext()){ String name = it.next(); String cName =
-		 * className;
-		 * 
-		 * if(writeSuper && name.startsWith(superName)) cName = superName;
-		 * 
-		 * if(name.startsWith(cName)){ String tag = start + _Tags.get(name) +
-		 * end; String output = "";
-		 * 
-		 * //check for other methods that go on this line LinkedList<String>
-		 * shared = _SharedLine.get(name); LinkedList<String> runMethods = new
-		 * LinkedList<String>();
-		 * 
-		 * if(shared != null) runMethods.addAll(shared);
-		 * 
-		 * name = name.substring((cName + ".").length());
-		 * runMethods.addFirst(name);
-		 * 
-		 * //loop through all methods and concat their output Iterator
-		 * methodIterator = runMethods.iterator();
-		 * 
-		 * while(methodIterator.hasNext()){ name = "get" +
-		 * methodIterator.next();
-		 * 
-		 * int ind = meths.indexOf(name);
-		 * 
-		 * if(ind >= 0){ Method m = methods[ind];
-		 * 
-		 * if(!seen.contains(m)){ try { if(m.getParameterTypes().length == 0){
-		 * Object val = m.invoke(toWrite, (Object[]) null);
-		 * 
-		 * if(val instanceof List){ int count = 0; for(Object o : (List) val){
-		 * if(count == 0) output += " " +
-		 * KMSConversion.ConvertToKMS(name.substring(3), o); else output += "\n" +
-		 * tag + " " + KMSConversion.ConvertToKMS(name.substring(3), o);
-		 * 
-		 * count++; } }else{ String res =
-		 * KMSConversion.ConvertToKMS(name.substring(3), val);
-		 * 
-		 * if(res != null) output += " " + res; } } } catch (Exception e) {
-		 * Logger.Log(e); }
-		 * 
-		 * seen.add(m); } }else if(name.equals("getTerminator")){ term = start +
-		 * _Tags.get(cName + ".Terminator") + end; }else System.out.println("No
-		 * method found: " + cName + "." + name); }
-		 * 
-		 * if(output.length() > 0) writeLine(tag + output); } } if(term != null)
-		 * writeLine(term);
-		 */
-	}
-
-	/*
-	 * private void writeBody(Object toWrite) throws IOException{
-	 * writeClass(toWrite, "Body", " ", false); }
-	 */
+	}
 
 	/**
Index: /trunk/src/org/expeditee/items/Dot.java
===================================================================
--- /trunk/src/org/expeditee/items/Dot.java	(revision 66)
+++ /trunk/src/org/expeditee/items/Dot.java	(revision 67)
@@ -302,5 +302,5 @@
 	public void anchor() {
 		super.anchor();
-		Frame current = getCurrentFrame();
+		Frame current = getParentOrCurrentFrame();
 		for (Line line : getLines()) {
 			if (line.getID() < 0 && !current.getItems().contains(line)) {
Index: /trunk/src/org/expeditee/items/Item.java
===================================================================
--- /trunk/src/org/expeditee/items/Item.java	(revision 66)
+++ /trunk/src/org/expeditee/items/Item.java	(revision 67)
@@ -399,5 +399,5 @@
 		// if its a relative link then return absolute
 		if (FrameIO.isPositiveInteger(link)) {
-			return _parent.getFramesetName() + Conversion.getFrameNumber(link);
+			return _parent.getFramesetName() + link;
 		}
 		return link;
@@ -1457,5 +1457,5 @@
 
 	public void anchor() {
-		Frame current = getCurrentFrame();
+		Frame current = getParentOrCurrentFrame();
 		setID(current.getNextItemID());
 		setOffset(0, 0);
@@ -1474,5 +1474,5 @@
 	 * @return
 	 */
-	public Frame getCurrentFrame() {
+	public Frame getParentOrCurrentFrame() {
 		// if the item is from an overlay the parent will NOT be null
 		if (getParent() == null) {
Index: /trunk/tests/org/expeditee/io/ConversionTest.java
===================================================================
--- /trunk/tests/org/expeditee/io/ConversionTest.java	(revision 67)
+++ /trunk/tests/org/expeditee/io/ConversionTest.java	(revision 67)
@@ -0,0 +1,115 @@
+package org.expeditee.io;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import junit.framework.TestCase;
+
+import org.expeditee.items.Item;
+
+public class ConversionTest extends TestCase {
+
+	public final void testGetColor() {
+		assertTrue(Conversion.getColor("100 0 0", Color.white).equals(Color.red));
+		assertTrue(Conversion.getColor("0 100 0", Color.white).equals(Color.green));
+		assertTrue(Conversion.getColor("0 0 100", Color.white).equals(Color.blue));
+		assertTrue(Conversion.getColor("100 100 100", Color.white).equals(Color.white));
+		assertEquals(Color.green,Conversion.getColor("-100 0 100", Color.white));
+		assertEquals(Conversion.getColor("+0 100 0", Color.black),Color.green);
+		assertEquals(Color.white, Conversion.getColor("a0a0a0", Color.white));
+		assertEquals(Conversion.getColor("red9", Color.white),new Color(0.9F, 0.0F, 0.0F));
+		assertEquals(Conversion.getColor("BlUe15", Color.white),new Color(0.0F, 0.0F, 1.0F));
+		assertEquals(Conversion.getColor("GREEN0", Color.white),new Color(0.0F, 0.0F, 0.0F));
+	}
+
+	public final void testGetKMSColorCode() {
+		assertTrue(Conversion.getKMSColorCode(Color.red).equals("100 0 0"));
+		assertTrue(Conversion.getKMSColorCode(Color.green).equals("0 100 0"));
+		assertTrue(Conversion.getKMSColorCode(Color.blue).equals("0 0 100"));
+	}
+
+	/*public final void testAdjustIntInt() {
+		fail("Not yet implemented");
+	}
+
+	public final void testAdjustPoint() {
+		fail("Not yet implemented");
+	}
+
+	public final void testDeAdjust() {
+		fail("Not yet implemented");
+	}
+
+	public final void testGetKMSFontCode() {
+		fail("Not yet implemented");
+	}
+
+	public final void testGetFont() {
+		fail("Not yet implemented");
+	}*/
+
+	public final void testGetFrameNumber() {
+		assertEquals(1, Conversion.getFrameNumber("a1"));
+		assertEquals(91, Conversion.getFrameNumber("a91"));
+		assertEquals(1, Conversion.getFrameNumber("a1C1"));
+	}
+
+	public final void testGetFrameset() {
+		assertTrue(Conversion.getFrameset("a1").equals("a"));
+		assertTrue(Conversion.getFrameset("a91").equals("a"));
+		assertTrue(Conversion.getFrameset("Aa1C1").equals("aa1c"));
+		assertTrue(Conversion.getFrameset("Aa1C1", false).equals("Aa1C"));
+		assertTrue(Conversion.getFrameset("Abc1C1", true).equals(
+				Conversion.getFrameset("Abc1C1")));
+	}
+
+	public final void testGetJustification() {
+		assertEquals(Item.JUSTIFICATION_CENTER, Conversion.getJustification("center"));
+		assertEquals(Item.JUSTIFICATION_CENTER, Conversion.getJustification("c"));
+		assertEquals(Item.JUSTIFICATION_RIGHT, Conversion.getJustification("R"));
+		assertEquals(Item.JUSTIFICATION_RIGHT, Conversion.getJustification("RIGHT"));
+		assertEquals(Item.JUSTIFICATION_LEFT, Conversion.getJustification("L"));
+		assertEquals(Item.JUSTIFICATION_LEFT, Conversion.getJustification("lEfT"));
+		assertEquals(Item.JUSTIFICATION_FULL, Conversion.getJustification("f"));
+		assertEquals(Item.JUSTIFICATION_FULL, Conversion.getJustification("FuLl"));
+		assertEquals(Item.JUSTIFICATION_NONE, Conversion.getJustification("NONE"));
+	}
+
+	public final void testGetKMSJustificationCode() {
+		assertEquals("C", Conversion.getKMSJustificationCode(Item.JUSTIFICATION_CENTER));
+		assertEquals("L", Conversion.getKMSJustificationCode(Item.JUSTIFICATION_LEFT));
+		assertEquals("R", Conversion.getKMSJustificationCode(Item.JUSTIFICATION_RIGHT));
+		assertEquals("F", Conversion.getKMSJustificationCode(Item.JUSTIFICATION_FULL));
+		assertEquals(null, Conversion.getKMSJustificationCode(Item.JUSTIFICATION_NONE));
+		assertEquals(null, Conversion.getKMSJustificationCode(Integer.MAX_VALUE));
+		assertEquals(null, Conversion.getKMSJustificationCode(Integer.MIN_VALUE));
+	}
+
+	public final void testConvertClassString() {
+		assertEquals("Test", Conversion.Convert(String.class, "Test"));
+		assertEquals(null, Conversion.Convert(String.class, ""));
+		assertEquals(Conversion.getFont("tr16"), Conversion.Convert(Font.class, "tr16"));
+		assertEquals(Color.red, Conversion.Convert(Color.class, "red"));
+		assertEquals(Color.red, Conversion.Convert(Color.class, "Red"));
+		assertEquals(Color.red, Conversion.Convert(Color.class, "RED"));
+		assertEquals(Color.red, Conversion.Convert(Color.class, " 100 "));
+		assertEquals(Color.green, Conversion.Convert(Color.class, "0  100"));
+		assertEquals(Color.blue, Conversion.Convert(Color.class, "0 0 100"));
+	}
+
+	public final void testConvertClassStringObject() {
+		assertEquals(Color.red, Conversion.Convert(Color.class, "+100 0 -100", Color.blue));
+		assertEquals(Color.black, Conversion.Convert(Color.class, "-0 0 100", Color.blue));
+		//TODO add more stuff to here
+	}
+
+	public final void testConvertMethodString() {
+	}
+
+	public final void testConvertMethodStringObject() {
+	}
+
+	public final void testConvertToKMS() {
+	}
+
+}
