protected boolean evalCommand(String ci) throws InterruptedException {

		String ciLC = ci.toLowerCase();

		// skip the following commands
		if (ciLC.startsWith("define ") || ciLC.startsWith("static ") || ciLC.startsWith("cancel"))
			return true;

		// call external scripts
		if (ciLC.startsWith("external")) {
			String address = ci.substring(8).trim();
			if (address != null && !address.equals("")) {
				Matcher matcher = NNI.matcher(address);
				if (matcher.find()) {
					byte i = Byte.parseByte(address);
					String s = externalScripts.get(i);
					if (s == null) {
						out(ScriptEvent.FAILED, "External command error: " + ci);
						return false;
					}
					evaluateExternalClause(s);
				}
				else {
					evaluateExternalClause(readText(address, view));
				}
			}
			return true;
		}

		logicalStack.clear();

		if (!checkParenthesisBalance(ci))
			return false;

		// get
		Matcher matcher = GET.matcher(ci);
		if (matcher.find()) {
			if (evaluateGetClause(ci.substring(matcher.end()).trim().toLowerCase()))
				return true;
		}

		// plot
		matcher = PLOT.matcher(ci);
		if (matcher.find()) {
			if (evaluatePlotClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// store
		matcher = STORE.matcher(ci);
		if (matcher.find()) {
			if (evaluateStoreClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// increment or decrement operator
		matcher = INCREMENT_DECREMENT.matcher(ci);
		if (matcher.find())
			return evaluateIncrementOperator(ci);

		matcher = SET_VAR.matcher(ci);
		if (!matcher.find()) {
			try {
				ci = replaceVariablesWithValues(useDefinitions(ci));
			}
			catch (EvaluationException ex) {
				ex.printStackTrace(System.err);
				return false;
			}
		}

		// select
		matcher = SELECT.matcher(ci);
		if (matcher.find()) {
			if (evaluateSelectClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// mouse cursor
		matcher = CURSOR.matcher(ci);
		if (matcher.find()) {
			if (evaluateCursorClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// background
		matcher = BACKGROUND.matcher(ci);
		if (matcher.find()) {
			if (evaluateBackgroundClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// charge
		matcher = CHARGE.matcher(ci);
		if (matcher.find()) {
			if (evaluateChargeClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// damp
		matcher = DAMP.matcher(ci);
		if (matcher.find()) {
			if (evaluateDampClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// restrain
		matcher = RESTRAIN.matcher(ci);
		if (matcher.find()) {
			if (evaluateRestrainClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// heat
		matcher = HEAT.matcher(ci);
		if (matcher.find()) {
			if (evaluateHeatClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// trajectory
		matcher = TRAJECTORY.matcher(ci);
		if (matcher.find()) {
			if (evaluateTrajectoryClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// camera
		matcher = CAMERA.matcher(ci);
		if (matcher.find()) {
			if (evaluateCameraClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// show
		matcher = SHOW.matcher(ci);
		if (matcher.find()) {
			if (evaluateShowClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// set
		matcher = SET.matcher(ci);
		if (matcher.find()) {
			if (evaluateSetClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// add
		matcher = ADD.matcher(ci);
		if (matcher.find()) {
			if (evaluateAddClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// move
		matcher = MOVE.matcher(ci);
		if (matcher.find()) {
			if (evaluateMoveClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// delay
		matcher = DELAY.matcher(ci);
		if (matcher.find()) {
			if (evaluateDelayClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// load
		matcher = LOAD.matcher(ci);
		if (matcher.find()) {
			if (evaluateLoadClause(ci.substring(matcher.end()).trim(), false))
				return true;
		}

		// script/source
		matcher = SOURCE.matcher(ci);
		if (matcher.find()) {
			if (evaluateSourceClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// print
		matcher = PRINT.matcher(ci);
		if (matcher.find()) {
			if (evaluatePrintClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// minimize
		matcher = MINIMIZE.matcher(ci);
		if (matcher.find()) {
			if (evaluateMinimizeClause(ci.substring(matcher.end()).trim()))
				return true;
		}

		// build radial bond
		matcher = BUILD_RBOND.matcher(ci);
		if (matcher.find()) {
			if (evaluateBuildRBondClause(ci.substring(ci.startsWith("rbond") ? 5 : 4).trim()))
				return true;
		}

		// build angular bond
		matcher = BUILD_ABOND.matcher(ci);
		if (matcher.find()) {
			if (evaluateBuildABondClause(ci.substring(ci.startsWith("abond") ? 5 : 4).trim()))
				return true;
		}

		// build torsional bond
		matcher = BUILD_TBOND.matcher(ci);
		if (matcher.find()) {
			if (evaluateBuildTBondClause(ci.substring(ci.startsWith("tbond") ? 5 : 4).trim()))
				return true;
		}

		// show message
		matcher = MESSAGE.matcher(ci);
		if (matcher.find()) {
			String s = XMLCharacterDecoder.decode(ci.substring(matcher.end()).trim());
			String slc = s.toLowerCase();
			int a = slc.indexOf("<t>");
			int b = slc.indexOf("</t>");
			String info;
			if (a != -1 && b != -1) {
				info = s.substring(a, b + 4).trim();
				slc = info.toLowerCase();
				if (!slc.startsWith("<html>")) {
					info = "<html>" + info;
				}
				if (!slc.endsWith("</html>")) {
					info = info + "</html>";
				}
			}
			else {
				matcher = Compiler.HTML_EXTENSION.matcher(s);
				if (matcher.find()) {
					info = readText(s, view);
				}
				else {
					info = "Unknown text";
				}
			}
			final String info2 = format(info);
			EventQueue.invokeLater(new Runnable() {
				public void run() {
					showMessageDialog(info2, view.getCodeBase(), view);
				}
			});
			return true;
		}

		out(ScriptEvent.FAILED, "Unrecognized command: " + ci);
		return false;

	}