// Empty object with references to the real Interpreter object. This object // is created to make it possible to load the real Interpreter object into // the "window" object, so that the "setTimeout", eval functions and dialog // events do not need to duplicate "this" on every call. Insteed of this, // they can simply call directly to window[strInterpreterId].functionname. function Interpreter(strCode) { // Create a random ID which can be used by _Interpreter to call itself. this.strInterpreterId = "Interpreter" + Math.random(); // Create the real interpreter object window[this.strInterpreterId] = new _Interpreter(strCode + "\n", this.strInterpreterId); // Store the interpreters id to a global variable if (typeof window["vdsinterpreteridlist"] == "undefined") { window["vdsinterpreteridlist"] = new Array(this.strInterpreterId); } else { window["vdsinterpreteridlist"][window["vdsinterpreteridlist"].length] = this.strInterpreterId; } // Placeholder for _Interpreter.execute() function this.execute = function() { window[this.strInterpreterId].execute(); } // Placeholder for _Interpreter.executeLine() function this.executeLine = function(intLine) { return window[this.strInterpreterId].executeLine(intLine); } // Placeholder for _Interpreter.stop() function this.stop = function() { // Call the _Interpreter.stop() function. Do NOT remove the // window[this.strInterpreterId] array since the debugger might // want to take a look at some values. window[this.strInterpreterId].stop(); } // Returns an array with all variables this.getVariables = function() { return window[this.strInterpreterId].arrVariables; } // Returns variable value this.getVariable = function(strVariable) { return window[this.strInterpreterId].getVariable(strVariable); } // Sets the value of a variable this.setVariable = function(strVariable, strValue) { window[this.strInterpreterId].setVariable(strVariable, strValue); } // Get the current state of the interpreter this.getState = function() { return window[this.strInterpreterId].state; } // Get the line being executed this.getLine = function() { return window[this.strInterpreterId].intCurrentLine; } // Returns the last event which is read out by @event() this.getEvent = function() { return window[this.strInterpreterId].arrLastEvent; } // Returns an array with ALL occured events this.getEvents = function() { return window[this.strInterpreterId].arrEventHistory; } } // The real Interpreter object function _Interpreter(strCode, strInterpreterId) { // Variables this.strInterpreterId = strInterpreterId; this.code = strCode; this.arrLines = strCode.split("\n"); this.arrCode = new Array(); this.arrLabels = new Array(); this.arrVariables = new Array(); this.arrGosubs = new Array(); this.arrLists = new Array(); this.intCurrentLine = ""; this.strLastExecuted = ""; this.arrEvents = new Array(); this.arrEventsHistory = new Array(); this.arrLastEvent = new Array("", "", ""); this.intWaitLine = ""; this.strFieldsep = "|"; // Array to hold the dialogs. The first dialog will be the current browser window this.arrDialogs = new Array(); this.arrDialogs[0] = window; this.arrDialogs[0].elements = new Array(); this.intSelectedDialog = 0; // Functions this.preParseLines = _Interpreter_preParseLines; this.preParseParameters = _Interpreter_preParseParameters; this.execute = _Interpreter_execute; this.executeLine = _Interpreter_executeLine; this.stop = _Interpreter_stop; this.parseParameter = _Interpreter_parseParameter; this.parseFunction = _Interpreter_parseFunction; this.setVariable = _Interpreter_setVariable; this.getVariable = _Interpreter_getVariable; this.setLabel = _Interpreter_setLabel; this.getLabel = _Interpreter_getLabel; this.addEvent = _Interpreter_addEvent; this.getLine = _Interpreter_getLine; this.getParsedLine = _Interpreter_getParsedLine; this.executeFunction = _Interpreter_executeFunction; this.executeCommand = _Interpreter_executeCommand; this.error = _Interpreter_error; this.waitEvent = _Interpreter_waitEvent; // Prepare the code to be executed by parsing lines and parameters this.preParseLines(); // Will parse the code into an array, line by line function _Interpreter_preParseLines() { this.arrCode = this.code.split("\n"); // Loop through all lines for (var i=0; i < this.arrCode.length; i++) { this.arrCode[i] = this.preParseParameters(trim(this.arrCode[i]), i); } } // Will parse one line of code into an array, parameter by parameter function _Interpreter_preParseParameters(strLine, intLine) { // First, define the type of command: // - command f.e. info Hello world! // - variable f.e. %varname = Hello world! // - label f.e. :Hello World // - comment f.e. # Hello world! or rem Hello World! if ((strLine.charAt(0) == "#") || (strLine.substr(0, 3).toLowerCase() == "rem")) { // Comment, return without modifications in this format: // - ["comment", value] return ["comment", strLine.substr(1)]; } else if (strLine.charAt(0) == "%") { // Variable, return in this format: // - ["variable", variablename, value] if (strLine.indexOf("=") < 0) { // No value assigned to variable return ["variable", trim(strLine), ""]; } else { return ["variable", trim(strLine.substr(0, strLine.indexOf("="))), trim(strLine.substr(strLine.indexOf("=") + 1))]; } } else if (strLine.charAt(0) == ":") { // Label, return without modifications in this format: // - ["label", name] // Also, save a reference to the line on which this label can be found to this.arrLabels this.setLabel(trim(strLine.substr(1)), intLine + 1); return ["label", trim(strLine.substr(1))]; } else if (trim(strLine) == "") { // Empty string, return a comment for reference in format: // - ["comment", "Empty line"] return ["comment", "Empty line"]; } else { // Command, return in this format: // - ["command", commandname, [parameter1, parameter2, parameter3, etc.]] if (strLine.indexOf(" ") > 0) { // Parse command parameters. Do not split within double quotes and when // the scope is within a function. var strCommandName = trim(strLine.substr(0, strLine.indexOf(" "))); var strParameters = trim(strLine.substr(strLine.indexOf(" "))); var arrParameters = new Array(""); var boolDoubleQuotes = false; var intFunctionCounter = 0; for (var i=0; i < strParameters.length; i++) { if ((strParameters.charAt(i) == ",") && (boolDoubleQuotes == false) && (intFunctionCounter == 0)) { arrParameters[arrParameters.length] = ""; } else if (strParameters.charAt(i) == "\"") { boolDoubleQuotes =! boolDoubleQuotes; arrParameters[arrParameters.length - 1] += "\""; } else if ((strParameters.charAt(i) == "@") && (boolDoubleQuotes == false)) { intFunctionCounter++; arrParameters[arrParameters.length - 1] += "@"; } else if ((strParameters.charAt(i) == ")") && (boolDoubleQuotes == false)) { if (intFunctionCounter > 0) { intFunctionCounter--; } arrParameters[arrParameters.length - 1] += ")"; } else { arrParameters[arrParameters.length - 1] += strParameters.charAt(i); } } // Trim all whitespaces from the parameters for(var i=0; i < arrParameters.length; i++) { arrParameters[i] = trim(arrParameters[i]); } return ["command", strCommandName, arrParameters]; } else { // Command without parameters return ["command", strLine]; } } } // Will execute the complete code by calling this.executeLine in a loop function _Interpreter_execute(intLine) { if (typeof intLine == "undefined") { var intLine = 1; } while ((((intLine != "") && (intLine <= this.arrCode.length)) && (intLine != "WAIT")) && (this.terminate != true)) { intLine = this.executeLine(intLine); } if (intLine == "WAIT") { this.state = "WAITING"; } else if ((intLine == "") || this.terminate == true) { this.state = "STOPPED"; this.stop(); } } // Executes a line and returns the next linenumber to be executed function _Interpreter_executeLine(intLine) { this.state = "RUNNING"; this.intCurrentLine = intLine; var intNextLine; var arrLine = this.arrCode[intLine - 1]; var arrParameters = new Array(); if (arrLine[0] == "command") { // Command, first loop through arrLine[2] to get all parameters (if any), then // execute the function in arrLine[1] with the parameters of arrLine[2] (if any) if (typeof arrLine[2] != "undefined") { // Command call with parameters for (i=0; i < arrLine[2].length; i++) { arrParameters[i] = this.parseParameter(arrLine[2][i]); } // Remember which command has been executed for debugging purposes this.strLastExecuted = ["command", arrLine[1]]; // Execute the command intNextLine = this.executeCommand(arrLine[1], arrParameters); } else { // Command call without parameters // Remember which command has been executed for debugging purposes this.strLastExecuted = ["command", arrLine[1]]; // Execute the command intNextLine = this.executeCommand(arrLine[1]); } } else if (arrLine[0] == "variable") { // Variable, first get the value of arrLine[2] and then assign it to arrLine[1] this.setVariable(arrLine[1], this.parseParameter(arrLine[2])); } else if ((arrLine[0] == "label") || (arrLine[0] == "comment")) { // Label or comment, do not execute these lines? } if (typeof intNextLine == "undefined") { intNextLine = intLine + 1; } if (intNextLine == "WAIT") { return "WAIT"; } else if (intNextLine <= this.arrCode.length) { return intNextLine; } else { return ""; } } // Terminates this interpreter and closes all windows function _Interpreter_stop() { // Stop _Interpreter_execute from functioning this.terminate = true; this.state = "STOPPED"; // Stop all timers if (this.eventTimeout) { window.clearTimeout(this.eventTimeout); } if (this.waitTimeout) { window.clearTimeout(this.waitTimeout); } // Close all child dialogs for (var i in this.arrDialogs) { // If there are elements on the main dialog, remove them. After that, close all child dialogs if (i == 0) { for (var j in this.arrDialogs[i].elements) { this.arrDialogs[i].document.body.removeChild(this.arrDialogs[i].elements[j]); } } else { // Close all child dialogs. Use a try-catch statement to prevent errors when closing // dialogs which might already be closed by the user after the interpreter stopped. if (this.arrDialogs[i]) { try { this.arrDialogs[i].close(); } catch (e) { } } } } } // Executes code (one command or function parameter ór the value which should be assigned to a variable) function _Interpreter_parseParameter(strCode) { var strOutput = ""; var i = 0; var boolDoubleQuotes = false; var intFunctionCounter = 0; var strTempFunction = ""; var strTempVariable = ""; while (i < strCode.length) { if (strCode.charAt(i) == "\"") { boolDoubleQuotes =! boolDoubleQuotes; } else if ((boolDoubleQuotes == false) && (strCode.charAt(i) == "@")) { // Found a function, loop to the last closing bracket that belongs to it and // call this.parseFunction intFunctionCounter++; strTempFunction = "@"; while (intFunctionCounter != 0) { i++; strTempFunction += strCode.charAt(i); if (strCode.charAt(i) == "\"") { boolDoubleQuotes =! boolDoubleQuotes; } else if (strCode.charAt(i) == "@") { intFunctionCounter++; } else if (strCode.charAt(i) == ")") { intFunctionCounter--; } if (i > strCode.length) { // No closing bracket found for function return this.error(24); } } strOutput += this.parseFunction(strTempFunction); } else if ((boolDoubleQuotes == false) && (strCode.charAt(i) == "%")) { // Found a variable, replace it with its value strTempVariable = "%"; i++; while ("|abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_".indexOf(strCode.charAt(i)) > 0) { strTempVariable += strCode.charAt(i); i++; } i--; strOutput += this.getVariable(strTempVariable); } else { strOutput += strCode.charAt(i); } i++; } return strOutput; } // Executes a function and returns its value. To get the value of the parameters, calls this.parseParameter // Receives code like @functionname(randomstuff,more random stuff). After parsing the parameters, call // this.executeFunction to get the return value of the function. function _Interpreter_parseFunction(strCode) { var strOutput = ""; var strFunction = trim(strCode.substr(1, strCode.indexOf("(") - 1)); // Remember which function has been executed for debugging purposes this.strLastExecuted = ["function", strFunction]; var arrParameters = new Array(""); var boolDoubleQuotes = false; var intFunctionCounter = 0; for (var i=strCode.indexOf("(") + 1; i < strCode.length - 1; i++) { if (strCode.charAt(i) == "\"") { boolDoubleQuotes =! boolDoubleQuotes; arrParameters[arrParameters.length - 1] += strCode.charAt(i); } else if (strCode.charAt(i) == "@") { intFunctionCounter++; arrParameters[arrParameters.length - 1] += strCode.charAt(i); } else if (strCode.charAt(i) == ")") { if (intFunctionCounter > 0) { intFunctionCounter--; } arrParameters[arrParameters.length - 1] += strCode.charAt(i); } else if (((strCode.charAt(i) == ",") && (boolDoubleQuotes == false)) && (intFunctionCounter == 0)) { arrParameters[arrParameters.length] = ""; } else { arrParameters[arrParameters.length - 1] += strCode.charAt(i); } } // Execute the content of the parameters for (var i=0; i < arrParameters.length; i++) { arrParameters[i] = this.parseParameter(trim(arrParameters[i])); } strOutput = this.executeFunction(strFunction, arrParameters); return strOutput; } // Sets the value of a variable function _Interpreter_setVariable(strVariable, strValue) { this.arrVariables[strVariable.toLowerCase()] = strValue; } // Return the value of a variable function _Interpreter_getVariable(strVariable) { if (typeof this.arrVariables[strVariable.toLowerCase()] == "undefined") { return ""; } else { return this.arrVariables[strVariable.toLowerCase()]; } } // Add a label to the this.arrLabels array function _Interpreter_setLabel(strLabel, intLine) { this.arrLabels[strLabel.toLowerCase()] = intLine; } // Returns the line number of the specified label function _Interpreter_getLabel(strLabel) { if (typeof this.arrLabels[strLabel.toLowerCase()] == "undefined") { return this.error(12); } else { return this.arrLabels[strLabel.toLowerCase()]; } } // Add an event to the event queue function _Interpreter_addEvent(intDialog, strName, strEvent) { this.arrEvents.push([intDialog, strName.toUpperCase(), strEvent.toUpperCase()]); this.arrEventsHistory.push([intDialog, strName.toUpperCase(), strEvent.toUpperCase()]); } // Returns the original source text from the specified line function _Interpreter_getLine(intLine) { return this.arrLines[intLine - 1]; } // Get the array parsed by preParseParameters() for the specified line function _Interpreter_getParsedLine(intLine) { return this.arrCode[intLine - 1]; } // Function called by parseFunction() to actually execute the given function and to // return its value. Note that functions are ordered into these groups: // - Conditional // - Maths // - Windows // - Lists // - Strings // - Default function _Interpreter_executeFunction(strFunction, arrParameters) { strFunction = strFunction.toLowerCase(); switch(strFunction) { /************************************************************************* * CONDITIONAL * *************************************************************************/ /* Done: - both - equal - greater - not - null - numeric - unequal - zero */ case "both": // Conditional - @both(, , [...]) // - Note, can accept any number of parameters for (var i=0; i < arrParameters.length; i++) { if ((arrParameters[i] == 0) || (arrParameters[i] == "")) { return 0; } } return 1; break; case "equal": // Conditional - @equal(, , [exact]) if (typeof arrParameters[2] == "undefined") { arrParameters[0] = arrParameters[0].toLowerCase(); arrParameters[1] = arrParameters[1].toLowerCase(); } if (arrParameters[0] == arrParameters[1]) { return 1; } else { return 0; } break; case "greater": // Conditional - @greater(, ) // - Note, also works on strings if (arrParameters[0] > arrParameters[1]) { return 1; } else { return 0; } break; case "not": // Conditional - @not() if ((arrParameters[0] == 0) || (arrParameters[0] == "")) { return 1; } else { return 0; } break; case "null": // Conditional - @null() // - Note, same as @not if ((arrParameters[0] == 0) || (arrParameters[0] == "")) { return 1; } else { return 0; } break; case "numeric": // Conditional - @numeric() // Note, returns 1 with value 1.234e5 if (arrParameters[0] == (arrParameters[0] * 1)) { return 1; } else { return 0; } break; case "unequal": // Conditional - @unequal(, , [exact]) if (typeof arrParameters[2] == "undefined") { arrParameters[0] = arrParameters[0].toLowerCase(); arrParameters[1] = arrParameters[1].toLowerCase(); } if (arrParameters[0] == arrParameters[1]) { return 0; } else { return 1; } break; case "zero": // Conditional - @zero() // Note, same as @not if ((arrParameters[0] == 0) || (arrParameters[0] == "")) { return 1; } else { return 0; } break; /************************************************************************* * MATHS * *************************************************************************/ /* Done: - abs - diff - div - fadd - fdiv - fmul - fsub - pred - prod - succ - sum Todo: - fabs - fatn - fcos - fexp - fint - fln - format - frac - fsin - fsqt - hex - mod - random Info: - http://www.javascripter.net/faq/mathfunc.htm */ case "abs": // Maths - @abs() return Math.abs(arrParameters[0]); break; case "diff": // Maths - @diff(, ) // - Note, can accept any number of parameters var intValue = Math.round(arrParameters[0]); for (var i=1; i < arrParameters.length; i++) { intValue -= Math.round(arrParameters[i]); } return intValue; break; case "div": // Maths - @div(, ) var intValue = Math.round(Math.round(arrParameters[0]) / Math.round(arrParameters[1])); if (intValue == "Infinity") { return this.error(26); } return intValue; break; case "fadd": // Maths - @fadd(, ) // - Note, can accept any number of parameters var intValue = 0; for (var i=0; i < arrParameters.length; i++) { intValue += (arrParameters[i] * 1); } return intValue; break; case "fdiv": // Maths - @fdiv(, ) var intValue = (arrParameters[0] / arrParameters[1]); if (intValue == "Infinity") { return this.error(26); } return intValue; break; case "fmul": // Maths - @fmul(, ) return (arrParameters[0] * arrParameters[1]); break; case "fsub": // Maths - @fsub(, ) // - Note, can accept any number of parameters var intValue = arrParameters[0]; for (var i=1; i < arrParameters.length; i++) { intValue -= (arrParameters[i] * 1); } return intValue; break; case "pred": // Maths - @pred() if (arrParameters[0] * 1 != arrParameters[0]) { return this.error(25); } return ((arrParameters[0] * 1) - 1); break; case "prod": // Maths - @prod(, ) return (Math.round(arrParameters[0]) * Math.round(arrParameters[1])); break; case "succ": // Maths - @succ() if (arrParameters[0] * 1 != arrParameters[0]) { return this.error(25); } return ((arrParameters[0] * 1) + 1); break; case "sum": // Maths - @sum(, , [...]) // - Note, can accept any number of parameters var intValue = 0; for (var i=0; i < arrParameters.length; i++) { intValue += Math.round(0 + arrParameters[i], 10); } return intValue; break; /************************************************************************* * WINDOWS * *************************************************************************/ /* Done: - ask - dlgpos - dlgtext - input - query - msgbox Todo: - focus */ case "ask": // Windows - @ask() if (this.arrDialogs[this.intSelectedDialog].confirm(arrParameters[0]) == true) { return 1; } else { return 0; } break; case "dlgpos": // Windows - @dlgpos(, ) // Note, can be T(op), L(eft), W(idth) or H(eight) var strDimension = arrParameters[1].substr(0, 1).toLowerCase(); if (arrParameters[0] == "") { // Positioning information about dialog if (strDimension == "t") { // Cannot retrieve a windows top position return 0; } else if (strDimension == "l") { // Cannot retrieve a windows left position return 0; } else if (strDimension == "w") { return this.arrDialogs[this.intSelectedDialog].document.body.clientWidth; } else if (strDimension == "h") { return this.arrDialogs[this.intSelectedDialog].document.body.clientHeight; } } else { // Position information about element if (typeof this.arrDialogs[this.intSelectedDialog].elements[arrParameters[0].toLowerCase()] == "undefined") { return this.error(18); } var objTempElement = this.arrDialogs[this.intSelectedDialog].elements[arrParameters[0].toLowerCase()].style; var strPosition; if (strDimension == "t") { strPosition = objTempElement.top; } else if (strDimension == "l") { strPosition = objTempElement.left; } else if (strDimension == "w") { strPosition = objTempElement.width; } else if (strDimension == "h") { strPosition = objTempElement.height; } return parseInt(strPosition); } break; case "dlgtext": // Windows - @dlgtext() if (typeof this.arrDialogs[this.intSelectedDialog].elements[arrParameters[0].toLowerCase()] == "undefined") { return this.error(18); } return this.arrDialogs[this.intSelectedDialog].elements[arrParameters[0].toLowerCase()].value; break; case "input": // Windows - @input([, ]) if (typeof arrParameters[1] == "undefined") { arrParameters[1] = ""; } var strInput = this.arrDialogs[this.intSelectedDialog].prompt(arrParameters[0], arrParameters[1]); if(strInput == null) { strInput = ""; } return strInput; break; case "msgbox": // Windows - @msgbox() if (this.arrDialogs[this.intSelectedDialog].confirm(arrParameters[0]) == true) { return 1; } else { return 0; } break; case "query": // Windows - @query() if (this.arrDialogs[this.intSelectedDialog].confirm(arrParameters[0]) == true) { return 1; } else { return 0; } break; /************************************************************************* * LISTS * *************************************************************************/ /* Done: - count - item - text - match */ case "count": // Lists - @count() var boolListExists = (typeof this.arrLists[arrParameters[0].toLowerCase()] == "object" ? true : false); if (boolListExists == true) { return this.arrLists[arrParameters[0].toLowerCase()].length; } else { return this.error(4); } break; case "item": // Lists - @item(, ) var boolListExists = (typeof this.arrLists[arrParameters[0].toLowerCase()] == "object" ? true : false); if (boolListExists == true) { if (typeof this.arrLists[arrParameters[0].toLowerCase()][arrParameters[1]] != "undefined") { return this.arrLists[arrParameters[0].toLowerCase()][arrParameters[1]]; } else { return ""; } } else { return this.error(4); } break; case "match": // Lists - @match(, ) var boolListExists = (typeof this.arrLists[arrParameters[0].toLowerCase()] == "object" ? true : false); if (boolListExists == true) { var i = 0; while (i < this.arrLists[arrParameters[0].toLowerCase()].length) { if (this.arrLists[arrParameters[0].toLowerCase()][i].indexOf(arrParameters[1]) > -1) { return i; } i++; } return ""; } else { return this.error(4); } break; case "text": // Lists - @text() var boolListExists = (typeof this.arrLists[arrParameters[0].toLowerCase()] == "object" ? true : false); if (boolListExists == true) { return this.arrLists[arrParameters[0].toLowerCase()].join("\n"); } else { return this.error(4); } break; /************************************************************************* * STRINGS * *************************************************************************/ /* Done: - asc - chr - cr - len - lf - lower - pos - strins - substr - trim - upper Todo: - fill - strdel */ case "asc": // Strings - @asc() if (arrParameters[0].length > 0) { return arrParameters[0].charCodeAt(0); } else { return this.error(11); } break; case "chr": // Strings - @chr() if ((arrParameters[0] * 1) < 256) { return String.fromCharCode((arrParameters[0] * 1)); } else { return this.error(13); } break; case "cr": // Strings - @cr() return String.fromCharCode(13); break; case "len": // Strings - @len() return arrParameters[0].length; break; case "lf": // Strings - @lf() return String.fromCharCode(10); break; case "lower": // Strings - @lower() return arrParameters[0].toLowerCase(); break; case "pos": // String - @pos(, , [exact]) if (typeof arrParameters[1] == "undefined") { return this.error(11); } else if (typeof arrParameters[2] == "undefined") { return (arrParameters[1].toLowerCase().indexOf(arrParameters[0].toLowerCase()) + 1); } else { return (arrParameters[1].indexOf(arrParameters[0]) + 1); } break; case "strins": // Strings - @strins(, , ) if (typeof arrParameters[2] == "undefined") { // Check if string2 is present, otherwise create it arrParameters[2] = ""; } if ((typeof arrParameters[1] == "undefined") || (arrParameters[1] < 1)) { // No begin or negative begin, return complete string return arrParameters[0]; } else if (arrParameters[1] > arrParameters[0].length) { // Return the original string with string2 appended return arrParameters[0] + "" + arrParameters[2]; } else { // Insert string return arrParameters[0].substr(0, arrParameters[1] - 1) + "" + arrParameters[2] + "" + arrParameters[0].substr(arrParameters[1] - 1); } break; case "substr": // Strings - @substr(, , []) if ((typeof arrParameters[1] == "undefined") || (arrParameters[1] < 1)) { // No begin or negative begin, return complete string return arrParameters[0]; } else if ((typeof arrParameters[2] == "undefined") || (arrParameters[2] == 0)) { // No end given, show only single character return arrParameters[0].substr(arrParameters[1] - 1, 1); } else if (arrParameters[2] < 0) { // Negative end value, show [begin] to [length] - [end] return arrParameters[0].substr(arrParameters[1] - 1, arrParameters[0].length - arrParameters[1] + (arrParameters[2] * 1) + 1); } else { // Normal end, show [begin] to [begin] + [end] return arrParameters[0].substr(arrParameters[1] - 1, arrParameters[2] - arrParameters[1] + 1); } break; case "trim": // Strings - @trim() return trim(arrParameters[0]); break; case "upper": // Strings - @upper() return arrParameters[0].toUpperCase(); break; /************************************************************************* * DEFAULT * *************************************************************************/ /* Done: - error handling Todo: - datetime */ case "event": // Default - @event() if (this.arrEvents.length > 0) { // Store eventname var strEvent = this.arrEvents[0][1] + this.arrEvents[0][2]; var intDialog = this.arrEvents[0][0]; // Store event in global variable for debugging this.arrLastEvent = this.arrEvents[0]; // Remove event from queue this.arrEvents.splice(0, 1); if (arrParameters[0]) { // Return eventname[fieldsep]dialogid return strEvent + this.strFieldsep + intDialog; } else { // Return eventname return strEvent; } } else { // No events available return ""; } break; default: // Unknown function, throw up an error return this.error(7); break; } } // Function called by executeLine() to actually execute the given command. Note // that commands are ordered into these groups: // - Lists // - Windows // - Script execution // - Conditional // - Loops // - Default function _Interpreter_executeCommand(strCommand, arrParameters) { strCommand = strCommand.toLowerCase(); // In case no parameters are used, do create an array for arrParameters to // prevent errors if (typeof arrParameters == "undefined") { arrParameters = new Array(); } switch(strCommand) { /************************************************************************* * LISTS * *************************************************************************/ /* Done: - list add - list create - list clear - list close - list delete NOTE: slightly different from VDS version - list insert NOTE: same function as "list put" - list put NOTE: slightly different from VDS version Todo - list append - list assign */ case "list": // Make sure to use the same cast for all subcommands var strSubCommand = arrParameters[0].toLowerCase(); arrParameters[1] = arrParameters[1].toLowerCase(); // Quick test to see if the list specified by the second parameter really exists var boolListExists = (typeof this.arrLists[arrParameters[1]] == "object" ? true : false); // Sub commands if (strSubCommand == "add") { // Lists - list add, , if (boolListExists == true) { this.arrLists[arrParameters[1]][this.arrLists[arrParameters[1]].length] = arrParameters[2]; } else { return this.error(4); } } else if (strSubCommand == "clear") { // Lists - list clear, if (boolListExists == true) { this.arrLists[arrParameters[1]] = new Array(); } else { return this.error(4); } } else if (strSubCommand == "create") { // Lists - list create, if (boolListExists == true) { return this.error(4); } else { this.arrLists[arrParameters[1]] = new Array(); } } else if (strSubCommand == "close") { // Lists - list close, if (boolListExists == true) { delete this.arrLists[arrParameters[1]]; } else { return this.error(4); } } else if (strSubCommand == "delete") { // Lists - list delete, , this.arrLists[arrParameters[1]].splice(arrParameters[2], 1); } else if (strSubCommand == "insert") { // Lists - list insert, , , if (typeof arrParameters[3] == "undefined") { arrParameters[3] = ""; } this.arrLists[arrParameters[1]].splice(arrParameters[2], 0, arrParameters[3]); } else if (strSubCommand == "put") { // Lists - list put, , , if (typeof arrParameters[3] == "undefined") { arrParameters[3] = ""; } this.arrLists[arrParameters[1]].splice(arrParameters[2], 0, arrParameters[3]); } else { // Lists - Unknown list command return this.error(14); } break; /************************************************************************* * WINDOWS * *************************************************************************/ /* Done - dialog create - dialog add - dialog close - dialog disable - dialog enable - dialog focus - dialog hide - dialog remove - dialog select - dialog set - dialog setpos - dialog show - dialog title - info - warn Todo: - dialog clear - dialog cursor - dialog settip */ case "dialog": var strSubCommand = arrParameters[0].toLowerCase(); // Sub commands if (strSubCommand == "create") { // Windows - dialog create, , <top>, <left>, <width>, <height> // Note, if <top> or <left> is ommited, the dialog will be centered on the screen if (!arrParameters[1]) { // No dialog title specified return this.error(2); } this.intSelectedDialog = this.arrDialogs.length; this.arrDialogs[this.intSelectedDialog] = window.open("", "_blank", "top=" + (arrParameters[2] || ((screen.height / 2) - ((arrParameters[5] || "1") / 2))) + ",left=" + (arrParameters[3] || ((screen.width / 2) - ((arrParameters[4] || "1") / 2))) + ",width=" + (arrParameters[4] || "1") + ",height=" + (arrParameters[5] || "1") + ",channelmode=no,directories=no,fullscreen=no,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no").window; this.arrDialogs[this.intSelectedDialog].document.body.style.backgroundColor = "#f0eee1"; this.arrDialogs[this.intSelectedDialog].document.body.style.cursor = "default"; this.arrDialogs[this.intSelectedDialog].document.title = arrParameters[1]; this.arrDialogs[this.intSelectedDialog].elements = new Array(); // Add an event which can catch close events // Note, this will NOT disable the window to be closed this.arrDialogs[this.intSelectedDialog].dialog = this.intSelectedDialog; this.arrDialogs[this.intSelectedDialog].strInterpreterId = this.strInterpreterId; this.arrDialogs[this.intSelectedDialog].document.body.onbeforeunload = function() { // Window is closed, reset the selected dialog to 0 and call the close event // Note, if the window is closed while executing (dialog) code, this might // throw up errors window[this.strInterpreterId].intSelectedDialog = 0; window[this.strInterpreterId].addEvent(this.dialog, "", "close"); } // Some browsers do not support window.document.body.onbeforeunload, so simply forward // all calls from window.onbeforeunload to window.document.body.onbeforeunload this.arrDialogs[this.intSelectedDialog].onbeforeunload = this.arrDialogs[this.intSelectedDialog].document.body.onbeforeunload; } else if (strSubCommand == "add") { // Windows - dialog add, <type>, <name>, <top>, <left>, <width>, <heigth>, <value>, <tooltip> // Be sure to always use the same cast for the element names (lowercase) var strElementType = arrParameters[1].toLowerCase(); var strElementName = arrParameters[2].toLowerCase(); // Check if element doesn't already exist if (typeof this.arrDialogs[this.intSelectedDialog].elements[strElementName] != "undefined") { return this.error(23); } // If <value> is undefined, set its value to <name> if (typeof arrParameters[7] == "undefined") { arrParameters[7] = strElementName; } // Create element if (strElementType == "button") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("input"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].type = "button"; this.arrDialogs[this.intSelectedDialog].elements[strElementName].onclick = function () { // Add event to arrEvents array window[this.strInterpreterId].addEvent(this.dialog, this.name, "BUTTON"); } } else if (strElementType == "check") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("input"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].type = "checkbox"; } else if (strElementType == "edit") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("input"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].type = "text"; } else if (strElementType == "radio") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("input"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].type = "radio"; } else if (strElementType == "text") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("div"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].innerHTML = arrParameters[7]; } else if (strElementType == "bitmap") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("img"); this.arrDialogs[this.intSelectedDialog].elements[strElementName].src = arrParameters[7]; } else if (strElementType == "group") { this.arrDialogs[this.intSelectedDialog].elements[strElementName] = this.arrDialogs[this.intSelectedDialog].document.createElement("fieldset"); } else { // Unknown element type return this.error(21); } // Element identifiers for events this.arrDialogs[this.intSelectedDialog].elements[strElementName].name = strElementName; this.arrDialogs[this.intSelectedDialog].elements[strElementName].elementType = strElementType; this.arrDialogs[this.intSelectedDialog].elements[strElementName].dialog = this.intSelectedDialog; this.arrDialogs[this.intSelectedDialog].elements[strElementName].strInterpreterId = this.strInterpreterId; // Options for all dialog elements this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.fontFamily = "Tahoma"; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.fontSize = "11px"; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.position = "absolute"; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.top = arrParameters[3]; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.left = arrParameters[4]; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.width = arrParameters[5]; this.arrDialogs[this.intSelectedDialog].elements[strElementName].style.height = arrParameters[6]; this.arrDialogs[this.intSelectedDialog].elements[strElementName].value = arrParameters[7]; if (typeof arrParameters[8] != "undefined") { this.arrDialogs[this.intSelectedDialog].elements[strElementName].title = arrParameters[8]; } // Append element to dialog this.arrDialogs[this.intSelectedDialog].document.body.appendChild(this.arrDialogs[this.intSelectedDialog].elements[strElementName]); } else if (strSubCommand == "close") { // Windows - dialog close // Note, will close selected dialog by "dialog select" or last created dialog and reset // the selected dialog to 0 this.arrDialogs[this.intSelectedDialog].close(); this.intSelectedDialog = 0; } else if (strSubCommand == "disable") { // Windows - dialog disable, <element> this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].disabled = true; } else if (strSubCommand == "enable") { // Windows - dialog enable, <element> this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].disabled = false; } else if (strSubCommand == "focus") { // Windows - dialog focus, <element> this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].focus(); } else if (strSubCommand == "hide") { // Windows - dialog hide, <element> if (typeof arrParameters[1] == "undefined") { // Hide dialog this.arrDialogs[this.intSelectedDialog].blur(); } else { // Hide element this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.visibility = "hidden"; } } else if (strSubCommand == "remove") { // Windows - dialog remove, <element> this.arrDialogs[this.intSelectedDialog].document.body.removeChild(this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()]); delete this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()]; } else if (strSubCommand == "select") { // Windows - dialog select this.intSelectedDialog = arrParameters[1]; } else if (strSubCommand == "set") { // Windows - dialog set, <name>, <value> var strTempElementType = this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].elementType; if (strTempElementType == "text") { this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].innerHTML = arrParameters[2]; } else if (strTempElementType == "bitmap") { this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].src = arrParameters[2]; } else { this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].value = arrParameters[2]; } } else if (strSubCommand == "setpos") { // Windows - dialog setpos, <element>, <top>, <left>, <width>, <height> if (!arrParameters[1]) { // Only change the dimensions of the given parameters. if (!arrParameters[4]) { arrParameters[4] = this.arrDialogs[this.intSelectedDialog].document.body.clientWidth; } if (!arrParameters[5]) { arrParameters[5] = this.arrDialogs[this.intSelectedDialog].document.body.clientHeight; } // Calculate how much to size by looking at the current clientWidth and clientHeight var intWidthAdd = arrParameters[4] - this.arrDialogs[this.intSelectedDialog].document.body.clientWidth; var intHeightAdd = arrParameters[5] - this.arrDialogs[this.intSelectedDialog].document.body.clientHeight; // Resize and reposition dialog itself this.arrDialogs[this.intSelectedDialog].resizeBy(intWidthAdd, intHeightAdd); // Check if the position is to be changed if (arrParameters[2] || arrParameters[3]) { this.arrDialogs[this.intSelectedDialog].moveTo(arrParameters[3], arrParameters[2]); } } else { if (arrParameters[2]) { // Top this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.top = arrParameters[2]; } if (arrParameters[3]) { // Left this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.left = arrParameters[3]; } if (arrParameters[4]) { // Width this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.width = arrParameters[4]; } if (arrParameters[5]) { // Height this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.height = arrParameters[5]; } } } else if (strSubCommand == "show") { // Windows - dialog show, <element> if (typeof arrParameters[1] == "undefined") { // Show dialog. // Note, This function only works if the browser itself has got focus already, // otherwise it will start blinking in the taskbar this.arrDialogs[this.intSelectedDialog].focus(); } else { // Show element this.arrDialogs[this.intSelectedDialog].elements[arrParameters[1].toLowerCase()].style.visibility = "visible"; } } else if (strSubCommand == "title") { // Windows - dialog title, <string> // Note, not all browsers support changing a window's title dynamic this.arrDialogs[this.intSelectedDialog].document.title = arrParameters[1]; } break; case "info": // Windows - info <string> if (typeof arrParameters[0] == "undefined") { arrParameters[0] = ""; } this.arrDialogs[this.intSelectedDialog].alert(arrParameters[0]); break; case "warn": // Windows - warn <string> if (typeof arrParameters[0] == "undefined") { arrParameters[0] = ""; } this.arrDialogs[this.intSelectedDialog].alert(arrParameters[0]); break; /************************************************************************* * SCRIPT EXECUTION * *************************************************************************/ /* Done: - exit - gosub - goto - option fieldsep - parse - stop Todo: - error - option - timer - (wait [event]) */ case "exit": // Script execution - exit if (this.arrGosubs.length > 0) { this.boolExecuteElsif = false; return this.arrGosubs.pop(); } else { return ""; } break; case "gosub": // Script execution - gosub <label> var intTempLine = this.getLabel(arrParameters[0]); if(intTempLine != "") { this.arrGosubs[this.arrGosubs.length] = this.intCurrentLine + 1; return intTempLine + 1; } else { return intTempLine; } break; case "goto": // Script execution - goto <label> var intTempLine = this.getLabel(arrParameters[0]); if (intTempLine != "") { return intTempLine + 1; } else { return intTempLine; } break; case "option": if (arrParameters[0].toLowerCase() == "fieldsep") { // Script execution - option fieldsep, <new fieldseperator> this.strFieldsep = arrParameters[1].substr(0, 1); } break; case "parse": // Script execution - parse "<variable>;<variable>;<...>", <string> var arrParseVariables = arrParameters[0].split(";"); var arrParseStrings = arrParameters[1].split(this.strFieldsep); for (var i=0; i < arrParseVariables.length; i++) { this.setVariable(trim(arrParseVariables[i]), trim(arrParseStrings[i])); } break; case "stop": // Script execution - stop return ""; break; case "wait": // Script execution - wait // or // Script execution - wait event, [<time>] // or // Script execution - wait <time>, [event] this.intWaitLine = this.intCurrentLine + 1; // Check if a wait time is given, if not, set it default to 1 second if (typeof arrParameters[0] == "undefined") { arrParameters[0] = 1; } // Check if the first or second parameters is "event". If the second is one, // swap it with the first if (arrParameters[1] == "event") { var intWaitTimeTemp = arrParameters[0]; arrParameters[0] = arrParameters[1]; arrParameters[1] = intWaitTimeTemp; } if (arrParameters[0] == "event") { // Wait until an event occures this.eventTimeout = window.setTimeout("window[\"" + this.strInterpreterId + "\"].waitEvent();", 1); // A maximum time is specified, set a second timer if (typeof arrParameters[1] != "undefined") { // Store this timer into a variable, so it can be cleared if a "normal" events occures // insteed of a TIMER event this.waitTimeout = window.setTimeout("window[\"" + this.strInterpreterId + "\"].addEvent(0, \"\", \"TIMER\");", (arrParameters[1] * 1000)); } } else { // Wait for x-seconds this.waitTimeout = window.setTimeout("window[\"" + this.strInterpreterId + "\"].execute(" + this.intWaitLine + ");", (arrParameters[0] * 1000)); } // Let the script know the "wait" command takes over return "WAIT"; break; /************************************************************************* * CONDITIONAL * *************************************************************************/ /* Done: - if - else - elsif - end */ case "if": // Conditional - if <statement> if ((typeof arrParameters == "undefined") || ((trim(arrParameters[0]) == 0) || (trim(arrParameters[0]) == ""))) { var intTempLine = this.intCurrentLine; var intIndent = 0; while (true) { if (intTempLine >= this.arrCode.length) { return this.error(9); } if (this.arrCode[intTempLine][1].toLowerCase() == "if") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "elsif") { if (intIndent == 0) { this.boolExecuteElsif = true; break; } } if (this.arrCode[intTempLine][1].toLowerCase() == "else") { if (intIndent == 0) { intTempLine++; break; } } if (this.arrCode[intTempLine][1].toLowerCase() == "end") { if (intIndent > 0) { intIndent--; } else { break; } } intTempLine++; } return intTempLine + 1; } else { } break; case "elsif": // Conditional - elsif <statement> // Note, should be used in conjunction with "if" if (this.boolExecuteElsif == true) { if ((typeof arrParameters == "undefined") || ((trim(arrParameters[0]) == 0) || (trim(arrParameters[0]) == ""))) { var intTempLine = this.intCurrentLine; var intIndent = 0; while (true) { if (intTempLine >= this.arrCode.length) { return this.error(9); } if (this.arrCode[intTempLine][1].toLowerCase() == "if") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "elsif") { if (intIndent == 0) { this.boolExecuteElsif = true; break; } } if (this.arrCode[intTempLine][1].toLowerCase() == "else") { if (intIndent == 0) { intTempLine++; break; } } if (this.arrCode[intTempLine][1].toLowerCase() == "end") { if (intIndent > 0) { intIndent--; } else { break; } } intTempLine++; } return intTempLine + 1; } else { this.boolExecuteElsif = false; } } else { var intTempLine = this.intCurrentLine; var intIndent = 0; while (true) { if (intTempLine >= this.arrCode.length) { return this.error(9); } if (this.arrCode[intTempLine][1].toLowerCase() == "if") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "end") { if (intIndent > 0) { intIndent--; } else { break; } } intTempLine++; } return intTempLine + 1; } break; case "else": // Conditional - else // Note, should be used in conjunction with "if" var intTempLine = this.intCurrentLine; var intIndent = 0; while (true) { if (intTempLine >= this.arrCode.length) { return this.error(9); } if (this.arrCode[intTempLine][1].toLowerCase() == "if") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "end") { if (intIndent > 0) { intIndent--; } else { break; } } intTempLine++; } return intTempLine + 1; break; case "end": // Conditional - end // Note, this function doesn't do anything by itself, but is used by "if", "elsif" and "end" to // indicate the indention of if-elsif-else-end statements break; /************************************************************************* * LOOPS * *************************************************************************/ /* Done: - repeat - until - while - wend */ case "repeat": // Loops - repeat // Note, this function should be used in conjunction with "until" break; case "until": // Loops - until <statement> if (typeof arrParameters == "undefined") { return this.error(2); } if ((trim(arrParameters[0]) == 0) || (trim(arrParameters[0]) == "")) { var intTempLine = this.intCurrentLine - 2; var intIndent = 0; while (true) { if (intTempLine < 0) { return this.error(15); } if (this.arrCode[intTempLine][1].toLowerCase() == "until") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "repeat") { if (intIndent > 0) { intIndent--; } else { return intTempLine + 1; } } intTempLine--; } } break; case "while": // Loops - while <statement> if (typeof arrParameters == "undefined") { return this.error(2); } if ((trim(arrParameters[0]) == 0) || (trim(arrParameters[0]) == "")) { var intTempLine = this.intCurrentLine; var intIndent = 0; while (true) { if (intTempLine >= this.arrCode.length) { return this.error(34); } if (this.arrCode[intTempLine][1].toLowerCase() == "while") { intIndent++; } if (this.arrCode[intTempLine][1].toLowerCase() == "wend") { if (intIndent > 0) { intIndent--; } else { return intTempLine + 2; } } intTempLine++; } } break; case "wend": // Loops - wend var intTempLine = this.intCurrentLine - 2; var intIndent = 0; while (true) { if (intTempLine < 0) { return this.error(35); } if (this.arrCode[intTempLine][1].toLowerCase() == "while") { if (intIndent > 0) { intIndent--; } else { return intTempLine + 1; } } if (this.arrCode[intTempLine][1].toLowerCase() == "wend") { intIndent++; } intTempLine--; } break; /************************************************************************* * DEFAULT * *************************************************************************/ /* Done: - error handling */ default: // Default - Error handling return this.error(1); break; } return; } // Show error messages function _Interpreter_error(strErrorCode) { var arrErrorCodes = new Array(); arrErrorCodes[1] = "Invalid command"; arrErrorCodes[2] = "Missing parameter(s) to command"; arrErrorCodes[3] = "Style already defined"; arrErrorCodes[4] = "Invalid list operation"; arrErrorCodes[5] = "Invalid variable name or too many variables"; arrErrorCodes[6] = "\"=\" symbol expected"; arrErrorCodes[7] = "Invalid @ function"; arrErrorCodes[8] = "Syntax error in @ function"; arrErrorCodes[9] = "Missing END, ELSE or ELSIF"; arrErrorCodes[10] = "Command nested too deeply"; arrErrorCodes[11] = "Missing argument(s) to @ function"; arrErrorCodes[12] = "Label not found"; arrErrorCodes[13] = "Invalid argument to @ function"; arrErrorCodes[14] = "Invalid parameter to command"; arrErrorCodes[15] = "UNTIL without REPEAT"; arrErrorCodes[16] = "Invalid style"; arrErrorCodes[17] = "Dialog already exists"; arrErrorCodes[18] = "Dialog control does not exist"; arrErrorCodes[19] = "List index out of range"; arrErrorCodes[20] = "File or path does not exist"; arrErrorCodes[21] = "Cannot create control"; arrErrorCodes[22] = "Operation invalid when no dialog showing"; arrErrorCodes[23] = "Dialog element name not valid"; arrErrorCodes[24] = "Mismatched brackets"; arrErrorCodes[25] = "Non-numeric value in arithmetic function"; arrErrorCodes[26] = "Arithmetic error"; arrErrorCodes[27] = "Untrapped error in an external command or function"; arrErrorCodes[28] = "External library not available"; arrErrorCodes[29] = "Insufficient memory for operation"; arrErrorCodes[30] = "Breakpoint reached"; arrErrorCodes[31] = "Stopped by user"; arrErrorCodes[32] = "User-defined error in external command"; arrErrorCodes[33] = "Unhandled exception"; arrErrorCodes[34] = "WEND missing"; arrErrorCodes[35] = "WEND without WHILE"; arrErrorCodes[36] = "Too many system timers"; arrErrorCodes[37] = "Cannot load resource"; arrErrorCodes[38] = "Library function not found"; arrErrorCodes[39] = "Error calling library function"; arrErrorCodes[40] = "Library not loaded"; arrErrorCodes[41] = "Too many arguments"; arrErrorCodes[42] = "Operation invalid"; // Show error message, depending on the reason why the error occured var strErrorMessage = "VISUAL DIALOGSCRIPT ERROR\n--------------------------------------\n"; strErrorMessage += "Line number:\t\t" + this.intCurrentLine + "\n"; strErrorMessage += "Error number:\t\t" + strErrorCode + "\n"; strErrorMessage += "Error description:\t\t" + arrErrorCodes[strErrorCode] + "\n"; if (this.strLastExecuted[0] == "command") { strErrorMessage += "Command:\t\t" + this.strLastExecuted[1] + "\n"; } else if (this.strLastExecuted[0] == "function") { strErrorMessage += "Function:\t\t\t@" + this.strLastExecuted[1] + "\n"; } window.alert(strErrorMessage); // Continue executing return ""; } // Used by the "wait event" command to check if an event is ready to be executed function _Interpreter_waitEvent(strTempThis) { // Check if there is an event in the queue if (this.arrEvents.length > 0) { // There is an event, clear any existing timers window.clearTimeout(this.waitTimeout); // Start executing this.execute(this.intWaitLine); } else { // No event, keep on executing this loop this.eventTimeout = window.setTimeout("window[\"" + this.strInterpreterId + "\"].waitEvent();", 1); } } // Removes leading and ending whitespaces from string function trim(strValue) { return strValue.replace(/^\s*|\s*$/g, ""); } } // If the page is loaded, this code will look for all <script type="vds"> like tags and execute its contents window.onload = function() { var scripts = document.getElementsByTagName("SCRIPT"); for(var i = 0; i < scripts.length; ++i) { if ((scripts[i].type.toLowerCase().indexOf("vds") >- 1) || (scripts[i].type.toLowerCase().indexOf("visual dialogscript") > -1)) { var script = scripts[i].text; var scriptObject = new Interpreter(script); scriptObject.execute() } } } // If the main page is unloaded, close all dialogs created by the interpreter window.onunload = function() { for (var i in window["vdsinterpreteridlist"]) { window[window["vdsinterpreteridlist"][i]].stop(); } }