Index: /trunk/src/org/expeditee/actions/Misc.java
===================================================================
--- /trunk/src/org/expeditee/actions/Misc.java	(revision 335)
+++ /trunk/src/org/expeditee/actions/Misc.java	(revision 336)
@@ -498,4 +498,9 @@
 					+ "' could not be found.");
 		}
+	}
+
+	public static void MessageLn(Item message) {
+		if (message instanceof Text)
+			MessageBay.displayMessage((Text) message);
 	}
 
Index: /trunk/src/org/expeditee/actions/Simple.java
===================================================================
--- /trunk/src/org/expeditee/actions/Simple.java	(revision 335)
+++ /trunk/src/org/expeditee/actions/Simple.java	(revision 336)
@@ -1253,21 +1253,5 @@
 				Frame frame2 = (Frame) context.getPointers().getVariable(
 						tokens[2]).getValue();
-				// Check that all the items on the frame are the same
-				List<Item> items1 = frame1.getVisibleItems();
-				List<Item> items2 = frame2.getVisibleItems();
-				if (items1.size() != items2.size()) {
-					throw new UnitTestFailedException(items1.size() + " items",
-							items2.size() + " items");
-				} else {
-					for (int i = 0; i < items1.size(); i++) {
-						Item i1 = items1.get(i);
-						Item i2 = items2.get(i);
-						String s1 = i1.getText();
-						String s2 = i2.getText();
-						if (!s1.equals(s2)) {
-							throw new UnitTestFailedException(s1, s2);
-						}
-					}
-				}
+				frame1.assertEquals(frame2);
 			} else if (tokens[0].equals("assertdefined")) {
 				assertExactParametreCount(tokens, 1);
@@ -1687,16 +1671,11 @@
 			double delay = context.getPrimitives().getDoubleValue(tokens[1]);
 			String s = getMessage(tokens, context, code.toString(), " ", 2);
-			for (int i = 0; i < s.length(); i++) {
-				FrameKeyboardActions.processChar(s.charAt(i), false);
-				Thread.sleep((int) (delay * 1000));
-			}
+			DisplayIO.typeStringDirect(delay, s);
 		} else if (tokens[0].equals("type") || tokens[0].equals("typenospaces")) {
 
 			String s = getMessage(tokens, context, code.toString(), tokens[0]
 					.equals("type") ? " " : "", 1);
-			for (int i = 0; i < s.length(); i++) {
-				FrameKeyboardActions.processChar(s.charAt(i), false);
-				Thread.sleep(25);
-			}
+			
+			DisplayIO.typeStringDirect(0.025, s);
 		} else if (tokens[0].equals("runstring")) {
 			String codeText = getMessage(tokens, context, code.toString(), " ",
Index: /trunk/src/org/expeditee/agents/SearchGreenstone.java
===================================================================
--- /trunk/src/org/expeditee/agents/SearchGreenstone.java	(revision 335)
+++ /trunk/src/org/expeditee/agents/SearchGreenstone.java	(revision 336)
@@ -33,6 +33,9 @@
 
 	private static boolean _showAbstract = false;
+
 	private static boolean _showKeywords = false;
+
 	private static boolean _showAuthors = false;
+
 	private static boolean _showDate = false;
 
@@ -89,4 +92,11 @@
 		if (settings == null)
 			return;
+
+		_maxResults = "10";
+		_showAbstract = false;
+		_showKeywords = false;
+		_showAuthors = false;
+		_showDate = false;
+		_locationChoice = 1;
 
 		// Set the settings
@@ -330,11 +340,11 @@
 		if (_showDate && rd.metadataExists("Date"))
 			text += ", " + rd.getDate();
-		
+
 		if (_showAbstract && rd.metadataExists("Abstract"))
 			text += "\n  " + rd.getAbstract();
-		
+
 		if (_showAuthors && rd.metadataExists("Creator"))
 			text += "\nAuthors" + rd.getAuthors().toString();
-		
+
 		if (_showKeywords && rd.getKeywords().size() > 0)
 			text += "\nKeywords" + rd.getKeywords().toString();
Index: /trunk/src/org/expeditee/gui/DisplayIO.java
===================================================================
--- /trunk/src/org/expeditee/gui/DisplayIO.java	(revision 335)
+++ /trunk/src/org/expeditee/gui/DisplayIO.java	(revision 336)
@@ -8,4 +8,5 @@
 import java.awt.Robot;
 import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
 import java.awt.geom.Point2D;
 import java.awt.image.MemoryImageSource;
@@ -55,12 +56,13 @@
 	@SuppressWarnings("unchecked")
 	private static Stack<String>[] _VisitedFrames = new Stack[2];
+
 	@SuppressWarnings("unchecked")
 	private static Stack<String>[] _BackedUpFrames = new Stack[2];
-	
+
 	// used to change the mouse cursor position on the screen
 	private static Robot _Robot;
 
 	private static boolean _TwinFrames = false;
-	
+
 	/** Notified whenever the frame changes */
 	private static HashSet<DisplayIOObserver> _displayIOObservers = new HashSet<DisplayIOObserver>();
@@ -102,5 +104,5 @@
 		}
 	}
-	
+
 	/**
 	 * Adds a DisplayIOObserver to the DisplayIO. DisplayIOObserver's are
@@ -110,30 +112,32 @@
 	 * 
 	 * @param observer
-	 * 		The observer to add
+	 *            The observer to add
 	 * 
 	 * @throws NullPointerException
-	 * 		If observer is null.
+	 *             If observer is null.
 	 */
 	public static void addDisplayIOObserver(DisplayIOObserver observer) {
-		if (observer == null) throw new NullPointerException("observer");
+		if (observer == null)
+			throw new NullPointerException("observer");
 		_displayIOObservers.add(observer);
 	}
-	
-	/**
-	 * Removes a DisplayIOObserver from the DisplayIO. 
+
+	/**
+	 * Removes a DisplayIOObserver from the DisplayIO.
 	 * 
 	 * @see #addDisplayIOObserver(DisplayIOObserver)
 	 * 
 	 * @param observer
-	 * 		The observer to add
+	 *            The observer to add
 	 * 
 	 * @throws NullPointerException
-	 * 		If observer is null.
+	 *             If observer is null.
 	 */
 	public static void removeDisplayIOObserver(DisplayIOObserver observer) {
-		if (observer == null) throw new NullPointerException("observer");
+		if (observer == null)
+			throw new NullPointerException("observer");
 		_displayIOObservers.remove(observer);
 	}
-	
+
 	public static void setTextCursor(Text text, int cursorMovement) {
 		setTextCursor(text, cursorMovement, false, false);
@@ -366,9 +370,9 @@
 		return null;
 	}
-	
+
 	public static void setCurrentFrame(Frame frame, boolean incrementStats) {
 		if (frame == null)
 			return;
-		
+
 		if (_TwinFrames) {
 			if (_CurrentFrames[0] == null) {
@@ -390,5 +394,5 @@
 					+ " is already the current frame.");
 			return;
-		} else if(incrementStats) {
+		} else if (incrementStats) {
 			SessionStats.AccessedFrame();
 		}
@@ -411,5 +415,5 @@
 		// Changing frames is a Save point for saveable entities:
 		EntitySaveManager.getInstance().saveAll();
-		
+
 		if (_TwinFrames) {
 			// if the same frame is being shown in both sides, load a fresh
@@ -545,5 +549,5 @@
 		if (_Browser == null)
 			return 0;
-		
+
 		if (_TwinFrames
 				&& FrameMouseActions.MouseX >= (_Browser.getWidth() / 2F)
@@ -647,6 +651,6 @@
 		// If the top frame on the backup stack is the current frame go back
 		// again... or if it has been deleted
-		//Recursively backup the stack
-		if(frame == null || frame.equals(getCurrentFrame())) {
+		// Recursively backup the stack
+		if (frame == null || frame.equals(getCurrentFrame())) {
 			Back();
 			return false;
@@ -677,5 +681,5 @@
 		return true;
 	}
-	
+
 	public static boolean Forward() {
 		int side = getCurrentSide();
@@ -699,6 +703,6 @@
 		// If the top frame on the backup stack is the current frame go back
 		// again... or if it has been deleted
-		//Recursively backup the stack
-		if(frame == null || frame.equals(getCurrentFrame())) {
+		// Recursively backup the stack
+		if (frame == null || frame.equals(getCurrentFrame())) {
 			Forward();
 			return false;
@@ -750,6 +754,5 @@
 			_CurrentFrames[current].refreshSize();
 		if (_CurrentFrames[opposite] != null)
-			_CurrentFrames[opposite]
-					.refreshSize();
+			_CurrentFrames[opposite].refreshSize();
 
 		FrameGraphics.Clear();
@@ -792,7 +795,46 @@
 	}
 
-	public static void clickMouse(int buttons) {
+	public static void clickMouse(int buttons) throws InterruptedException {
 		_Robot.mousePress(buttons);
+		Thread.sleep(100);
 		_Robot.mouseRelease(buttons);
+	}
+
+	public static void typeKey(int key) throws InterruptedException {
+		_Robot.keyPress(key);
+		// _Robot.waitForIdle();
+		_Robot.keyRelease(key);
+		// _Robot.waitForIdle();
+		Thread.sleep(100);
+	}
+
+	public static void typeText(String s) throws InterruptedException {
+		for (int i = 0; i < s.length(); i++) {
+			char c = s.charAt(i);
+			if(Character.isUpperCase(c))
+				_Robot.keyPress(KeyEvent.VK_SHIFT);
+			typeKey(getKeyCode(c));
+			if(Character.isUpperCase(c))
+				_Robot.keyRelease(KeyEvent.VK_SHIFT);
+		}
+	}
+
+	protected static int getKeyCode(char c) {
+		switch(c){
+		case '\n':
+			return KeyEvent.VK_ENTER;
+		case ' ':
+			return KeyEvent.VK_SPACE;
+		}
+		
+		if(Character.isSpaceChar(c))
+			return  KeyEvent.VK_SPACE;
+		else if(Character.isDigit(c)){
+			return (int)(KeyEvent.VK_0 + c - '0');
+		}else if(Character.isUpperCase(c)){
+			return c;
+		}
+			
+		return (int)(KeyEvent.VK_A + c - 'a');
 	}
 
@@ -814,3 +856,15 @@
 		_BackedUpFrames[getCurrentSide()].clear();
 	}
+
+	/**
+	 * @param secondsDelay
+	 * @param s
+	 * @throws InterruptedException
+	 */
+	public static void typeStringDirect(double secondsDelay, String s) throws InterruptedException {
+		for (int i = 0; i < s.length(); i++) {
+			FrameKeyboardActions.processChar(s.charAt(i), false);
+			Thread.sleep((int) (secondsDelay * 1000));
+		}
+	}
 }
Index: /trunk/src/org/expeditee/gui/Frame.java
===================================================================
--- /trunk/src/org/expeditee/gui/Frame.java	(revision 335)
+++ /trunk/src/org/expeditee/gui/Frame.java	(revision 336)
@@ -33,4 +33,5 @@
 import org.expeditee.items.widgets.InteractiveWidget;
 import org.expeditee.items.widgets.WidgetCorner;
+import org.expeditee.simple.UnitTestFailedException;
 import org.expeditee.stats.SessionStats;
 
@@ -998,9 +999,9 @@
 		s.append(String.format("Name: %s%d%n", _frameset, _number));
 		s.append(String.format("Version: %d%n", _version));
-		s.append(String.format("Permission: %s%n", _permission.toString()));
-		s.append(String.format("Owner: %s%n", _owner));
-		s.append(String.format("Date Created: %s%n", _creationDate));
-		s.append(String.format("Last Mod. User: %s%n", _modifiedUser));
-		s.append(String.format("Last Mod. Date: %s%n", _modifiedDate));
+		//s.append(String.format("Permission: %s%n", _permission.toString()));
+		//s.append(String.format("Owner: %s%n", _owner));
+		//s.append(String.format("Date Created: %s%n", _creationDate));
+		//s.append(String.format("Last Mod. User: %s%n", _modifiedUser));
+		//s.append(String.format("Last Mod. Date: %s%n", _modifiedDate));
 		s.append(String.format("Items: %d%n", _body.size()));
 		return s.toString();
@@ -1307,4 +1308,8 @@
 			addOverlay(o);
 
+		// Add all the vectors from the overlay frame to this frame
+		for (Vector v : toAdd.Frame.getVectors())
+			addVector(v);
+
 		// Now add the items for this overlay
 		Permission permission = Permission.min(toAdd.Frame.getPermission(),
@@ -1320,4 +1325,5 @@
 			_overlayItems.add(i);
 		}
+
 		return true;
 	}
@@ -2082,3 +2088,24 @@
 		return getAnnotationValue("file");
 	}
+
+	public void assertEquals(Frame frame2) {
+		// Check that all the items on the frame are the same
+		List<Item> items1 = getVisibleItems();
+		List<Item> items2 = frame2.getVisibleItems();
+		if (items1.size() != items2.size()) {
+			throw new UnitTestFailedException(items1.size() + " items", items2
+					.size()
+					+ " items");
+		} else {
+			for (int i = 0; i < items1.size(); i++) {
+				Item i1 = items1.get(i);
+				Item i2 = items2.get(i);
+				String s1 = i1.getText();
+				String s2 = i2.getText();
+				if (!s1.equals(s2)) {
+					throw new UnitTestFailedException(s1, s2);
+				}
+			}
+		}
+	}
 }
Index: /trunk/src/org/expeditee/gui/FrameIO.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameIO.java	(revision 335)
+++ /trunk/src/org/expeditee/gui/FrameIO.java	(revision 336)
@@ -180,7 +180,7 @@
 		String fullPath = FrameIO.getFrameFullPathName(PUBLIC_PATH, frameName);
 
-		if(fullPath == null)
+		if (fullPath == null)
 			return null;
-		
+
 		File frameFile = new File(fullPath);
 		if (frameFile.exists() && frameFile.canRead()) {
@@ -209,5 +209,5 @@
 			}
 		}
-		
+
 		if (loaded == null && FrameShare.getInstance() != null) {
 			loaded = FrameShare.getInstance().loadFrame(framename, knownPath);
@@ -359,4 +359,5 @@
 
 			// do not put 0 frames or virtual frames into the cache
+			// Why are zero frames not put in the cache
 			if (_Cache.size() > MAX_CACHE)
 				_Cache.clear();
@@ -601,5 +602,16 @@
 
 		// disable caching of 0 frames
-		SuspendCache();
+		// Mike says: Why is caching of 0 frames being disabled?
+		/*
+		 * Especially since 0 frames are not event put into the cache in the
+		 * frist place
+		 */
+		// SuspendCache();
+		/*
+		 * Suspending the cache causes infinate loops when trying to load a zero
+		 * frame which has a ao which contains an v or av which contains a link
+		 * to the ao frame
+		 */
+
 		String zeroFrameName = frameset + "0";
 		Frame destFramesetZero = LoadFrame(zeroFrameName);
Index: /trunk/src/org/expeditee/gui/FrameUtils.java
===================================================================
--- /trunk/src/org/expeditee/gui/FrameUtils.java	(revision 335)
+++ /trunk/src/org/expeditee/gui/FrameUtils.java	(revision 336)
@@ -585,7 +585,7 @@
 			else if (attribute.equals("networksettings"))
 				FrameShare.init(item.getChild());
-			else if (attribute.equals("greenstonesettings"))
+			else if (attribute.equals("greenstonesettings")) {
 				SearchGreenstone.init(item.getChild());
-			else if (attribute.equals("reminders"))
+			} else if (attribute.equals("reminders"))
 				Reminders.init(item.getChild());
 			else if (attribute.equals("antialias"))
@@ -811,5 +811,5 @@
 				} else if (i.hasOverlay()) {
 					i.setVisible(true);
-					//int x = i.getBoundsHeight();
+					// int x = i.getBoundsHeight();
 				}
 			}
@@ -873,11 +873,14 @@
 										ItemUtils.TAG_VECTOR)
 								&& i.getLink() != null) {
-							addVector(vectors, Permission.none, permission, i);
+							if (!i.getAbsoluteLink().equals(toParse.getName()))
+								addVector(vectors, Permission.none, permission,
+										i);
 						} else if (!FrameGraphics.isXRayMode()
 								&& ItemUtils.startsWithTag(i,
 										ItemUtils.TAG_ACTIVE_VECTOR)
 								&& i.getLink() != null) {
-							addVector(vectors, Permission.followLinks,
-									permission, i);
+							if (!i.getAbsoluteLink().equals(toParse.getName()))
+								addVector(vectors, Permission.followLinks,
+										permission, i);
 						}
 						// check for new OVERLAY items
@@ -1032,6 +1035,6 @@
 			// thread-safe protocol for this project...
 			toParse.clearOverlays();
+			toParse.clearVectors();
 			toParse.addAllOverlays(overlays);
-			toParse.clearVectors();
 			toParse.addAllVectors(vectors);
 		}
@@ -1049,4 +1052,5 @@
 		// @v which points back to the frame with the @ao
 		Frame vector = FrameIO.LoadFrame(i.getAbsoluteLink());
+
 		// Get the permission from off the vector frame
 		Permission vectorPermission = Permission.getPermission(vector
Index: /trunk/src/org/expeditee/gui/MessageBay.java
===================================================================
--- /trunk/src/org/expeditee/gui/MessageBay.java	(revision 335)
+++ /trunk/src/org/expeditee/gui/MessageBay.java	(revision 336)
@@ -18,6 +18,6 @@
 
 /**
- * The bay at the bottom of the expeditee browser which displays messages.
- * TODO make it thread safe!
+ * The bay at the bottom of the expeditee browser which displays messages. TODO
+ * make it thread safe!
  * 
  */
@@ -75,10 +75,10 @@
 				_messages[i].setOffset(0,
 						-FrameGraphics.getMaxFrameSize().height);
-				//_messages[i].setMaxWidth(FrameGraphics.getMaxFrameSize().width);
+				// _messages[i].setMaxWidth(FrameGraphics.getMaxFrameSize().width);
 			}
 		}
 
 		_messageLink.setOffset(0, -FrameGraphics.getMaxFrameSize().height);
-		//_messageLink.setMaxWidth(FrameGraphics.getMaxFrameSize().width);
+		// _messageLink.setMaxWidth(FrameGraphics.getMaxFrameSize().width);
 		// _messageLink.setPosition(FrameGraphics.getMaxFrameSize().width
 		// - MESSAGE_LINK_Y_OFFSET, MESSAGE_LINK_X);
@@ -127,6 +127,7 @@
 		if (_messageBuffer != null) {
 			_dirtyAreas.clear();
-			addDirtyArea(new Rectangle(0, FrameGraphics.getMaxFrameSize().height,
-					_messageBuffer.getWidth(), _messageBuffer.getHeight()));
+			addDirtyArea(new Rectangle(0,
+					FrameGraphics.getMaxFrameSize().height, _messageBuffer
+							.getWidth(), _messageBuffer.getHeight()));
 		}
 	}
@@ -134,7 +135,8 @@
 	private static boolean initBuffer() {
 		if (_messageBuffer == null) {
-			if (FrameGraphics.isAudienceMode() ||
-					FrameGraphics.getMaxSize().width <= 0) return false;
-			
+			if (FrameGraphics.isAudienceMode()
+					|| FrameGraphics.getMaxSize().width <= 0)
+				return false;
+
 			GraphicsEnvironment ge = GraphicsEnvironment
 					.getLocalGraphicsEnvironment();
@@ -177,6 +179,6 @@
 	 *            The color of the message background
 	 */
-	public static synchronized void refresh(boolean useInvalidation, Graphics g,
-			Color background) {
+	public static synchronized void refresh(boolean useInvalidation,
+			Graphics g, Color background) {
 
 		if (FrameGraphics.getMaxSize().width <= 0)
@@ -220,5 +222,6 @@
 
 	private static void updateBuffer(Color background, Area clip) {
-		if (!initBuffer()) return;
+		if (!initBuffer())
+			return;
 
 		Graphics2D g = _messageBuffer.createGraphics();
@@ -255,7 +258,7 @@
 		return displayMessage(message, link, actions, color, true);
 	}
-	
-	public static Text displayMessage(String message, String link,
-		 Color color, boolean displayAlways, String action) {
+
+	public static Text displayMessage(String message, String link, Color color,
+			boolean displayAlways, String action) {
 		List<String> actions = new LinkedList<String>();
 		actions.add(action);
@@ -299,5 +302,5 @@
 					_messages[i].setOffset(0,
 							-FrameGraphics.getMaxFrameSize().height);
-					//_messages[i].setMaxWidth(FrameGraphics.getMaxFrameSize().width);
+					// _messages[i].setMaxWidth(FrameGraphics.getMaxFrameSize().width);
 					_messages[i].setColor(color);
 					_messages[i].setLink(link);
@@ -337,5 +340,5 @@
 
 		refresh(false, FrameGraphics.createGraphics(), Item.DEFAULT_BACKGROUND);
-		
+
 		return last;
 	}
@@ -344,5 +347,5 @@
 		overwriteMessage(message, null);
 	}
-	
+
 	public static void overwriteMessage(String message, Color color) {
 		for (int ind = _messages.length - 1; ind >= 0; ind--) {
@@ -412,6 +415,12 @@
 
 	public static Text displayMessage(Text message) {
-		return displayMessage(message.getFirstLine(), message.getLink(), message
-				.getAction(), message.getColor());
+		Text t = null;
+		String link = message.getLink();
+		List<String> action = message.getAction();
+		Color color = message.getColor();
+		for (String s : message.getTextList()) {
+			t = displayMessage(s, link, action, color);
+		}
+		return t;
 		// Misc.Beep();
 	}
Index: /trunk/src/org/expeditee/items/Text.java
===================================================================
--- /trunk/src/org/expeditee/items/Text.java	(revision 335)
+++ /trunk/src/org/expeditee/items/Text.java	(revision 336)
@@ -602,6 +602,5 @@
 			if (text.charAt(0) == KeyEvent.VK_BACK_SPACE) {
 				if (hasSelection()) {
-					cutSelectedText();
-					clearSelection();
+					pos = deleteSelection(pos);
 				} else if (insertPos > 0) {
 					deleteChar(insertPos - 1);
@@ -612,6 +611,5 @@
 			} else if (text.charAt(0) == KeyEvent.VK_DELETE) {
 				if (hasSelection()) {
-					cutSelectedText();
-					clearSelection();
+					pos = deleteSelection(pos);
 				} else if (insertPos < _text.length()) {
 					deleteChar(insertPos);
@@ -719,4 +717,16 @@
 	}
 
+	/**
+	 * @param pos
+	 * @return
+	 */
+	private int deleteSelection(int pos) {
+		int selectionLength = getSelectionSize();
+		cutSelectedText();
+		clearSelection();
+		pos -= selectionLength;
+		return pos;
+	}
+
 	public Point2D.Float moveCursor(int direction, float mouseX, float mouseY,
 			boolean setSelection) {
