protected boolean evaluateSingleKeyword(String str) throws InterruptedException {
		if (super.evaluateSingleKeyword(str))
			return true;
		String strLC = str.toLowerCase();
		if ("paint".equals(strLC)) { // paint
			model.computeForce(-1);
			view.repaint();
			return true;
		}
		if ("focus".equals(strLC)) { // focus
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					view.requestFocusInWindow();
				}
			});
			return true;
		}
		if ("beep".equals(strLC)) { // beep
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					Toolkit.getDefaultToolkit().beep();
				}
			});
			return true;
		}
		if ("run".equals(strLC)) { // run
			// FIXME: Why do we need to do this to make "delay modeltime" to work with a prior "run" command?
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
			}
			// must be invoked later for it to work properly, as it does from a button
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					model.run();
				}
			});
			return true;
		}
		if ("init".equals(strLC)) { // cause the initialization script to be executed, if any
			if (model.getInitializationScript() != null)
				model.runScript(model.getInitializationScript());
			return true;
		}
		if ("mark".equals(strLC)) { // mark
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					model.markSelection();
				}
			});
			notifyChange();
			return true;
		}
		if ("remove".equals(strLC)) { // remove selected objects
			// CAUTION!!!!!!!!! PUTTING INTO EVENTQUEUE is dangerous if there are commands following it!
			removeSelectedObjects();
			// EventQueue.invokeLater(new Runnable() { public void run() { removeSelectedObjects(); } });
			notifyChange();
			return true;
		}
		if (strLC.startsWith("stop")) {
			if ("stop".equals(strLC)) { // stop
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						model.stop();
					}
				});
				return true;
			}
			if ("immediately".equals(strLC.substring(4).trim())) { // stop immediately
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						model.stopImmediately();
					}
				});
				return true;
			}
		} else if (strLC.startsWith("reset")) {
			if ("reset".equals(strLC)) { // reset
				evaluateLoadClause((String) model.getProperty("url"));
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						readdMouseAndKeyScripts(model.getInitializationScript());
						model.notifyModelListeners(new ModelEvent(model, ModelEvent.MODEL_RESET));
						model.notifyPageComponentListeners(new PageComponentEvent(model, PageComponentEvent.COMPONENT_RESET));
					}
				});
				return true;
			}
			if ("silently".equals(strLC.substring(5).trim())) { // reset silently
				evaluateLoadClause((String) model.getProperty("url"));
				readdMouseAndKeyScripts(model.getInitializationScript());
				return true;
			}
		} else if (strLC.startsWith("snapshot")) {
			if ("snapshot".equals(strLC)) { // snapshot
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						model.notifyPageComponentListeners(new PageComponentEvent(view, PageComponentEvent.SNAPSHOT_TAKEN));
					}
				});
				return true;
			}
			if ("nodescription".equals(strLC.substring(8).trim())) { // snapshot nodescription
				EventQueue.invokeLater(new Runnable() {
					public void run() {
						model.notifyPageComponentListeners(new PageComponentEvent(view, PageComponentEvent.SNAPSHOT_TAKEN_NODESCRIPTION));
					}
				});
				return true;
			}
		}
		return false;
	}