* code cleanup and bugfix patch for t3editor / preparation for review (Thanks to...
authorThomas Hempel <thomas.hempel@typo3.org>
Tue, 12 Feb 2008 13:52:45 +0000 (13:52 +0000)
committerThomas Hempel <thomas.hempel@typo3.org>
Tue, 12 Feb 2008 13:52:45 +0000 (13:52 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@3151 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/sysext/t3editor/class.tx_t3editor.php
typo3/sysext/t3editor/css/t3editor.css
typo3/sysext/t3editor/ext_emconf.php
typo3/sysext/t3editor/jslib/parsetyposcript.js
typo3/sysext/t3editor/jslib/select.js
typo3/sysext/t3editor/jslib/stringstream.js
typo3/sysext/t3editor/jslib/t3editor.js
typo3/sysext/t3editor/jslib/tokenizetyposcript.js
typo3/sysext/t3editor/jslib/util.js
typo3/sysext/tstemplate_info/class.tx_tstemplateinfo.php

index e24815f..d1c5f0a 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2008-02-12  Thomas Hempek  <thomas@typo3-unleashed.net>
+
+       * code cleanup and bugfix patch for t3editor / preparation for review (Thanks to Tobias Liebig)
+
 2008-02-12  Oliver Hader  <oh@inpublica.de>
 
        * Cleanup of t3lib/stddb/tbl_be.php
index 8399f1e..094c23c 100755 (executable)
@@ -118,8 +118,6 @@ class tx_t3editor {
                $code = ''; // TODO find a more descriptive name (low prio)
 
                if ($this->isEnabled) {
-                               // disable the obsolete tab.js to avoid conflicts
-                       $GLOBALS['BE_USER']->uc['disableTabInTextarea'] = '1';
 
                        $path_t3e = $GLOBALS['BACK_PATH'].t3lib_extmgm::extRelPath('t3editor');
 
@@ -178,6 +176,7 @@ class tx_t3editor {
                        $code.= '<br/><br/>
                                <input type="checkbox" onclick="t3editor_toggleEditor(this);" name="t3editor_disableEditor" value="true" id="t3editor_disableEditor_'.$this->editorCounter.'_checkbox" '.$checked.' />&nbsp;
                                <label for="t3editor_disableEditor_'.$this->editorCounter.'_checkbox">deactivate t3editor</label>
+                               <input type="hidden" name="submitAjax" id="submitAjax" value="0" />
                                <br/><br/>';
 
                } else {
index 505fe66..f7bc92e 100755 (executable)
@@ -19,7 +19,7 @@
  *********************************************/
 
 span.other { color: black; }
-.ts-operator { color: black; font-weight: bold; }
+.ts-operator { color: #0000cc; font-weight: bold; }
 .ts-value { color: #cc0000; }
 .ts-objstr, .keyword, .keyword2, .keyword3, .reserved { color: #0000cc; }
 .ts-value_copy { color: #006600; }
index 1b618c1..ec47129 100755 (executable)
@@ -32,12 +32,12 @@ $EM_CONF[$_EXTKEY] = array(
        'author_company' => '',
        'CGLcompliance' => '',
        'CGLcompliance_note' => '',
-       'version' => '0.0.6',
+       'version' => '0.0.9',
        '_md5_values_when_last_written' => 'a:14:{s:21:"class.tx_t3editor.php";s:4:"bb07";s:12:"ext_icon.gif";s:4:"4cef";s:16:"css/t3editor.css";s:4:"d4f1";s:23:"icons/loader_eeeeee.gif";s:4:"83a4";s:13:"jslib/LICENSE";s:4:"d835";s:14:"jslib/Mochi.js";s:4:"872d";s:24:"jslib/parsejavascript.js";s:4:"5377";s:24:"jslib/parsetyposcript.js";s:4:"7815";s:15:"jslib/select.js";s:4:"6725";s:21:"jslib/stringstream.js";s:4:"e6a5";s:17:"jslib/t3editor.js";s:4:"656c";s:27:"jslib/tokenizejavascript.js";s:4:"1c7a";s:27:"jslib/tokenizetyposcript.js";s:4:"c232";s:13:"jslib/util.js";s:4:"7620";}',
        'constraints' => array(
                'depends' => array(
                        'php' => '4.1.0-0.0.0',
-                       'typo3' => '4.1-0.0.0',
+                       'typo3' => '4.2-0.0.0',
                ),
                'conflicts' => array(
                        'pmktextarea' => '',
index 6f15b37..69fa957 100755 (executable)
 // in many languages it is enough to just look for braces, semicolons,
 // parentheses, etc, and know when you are inside a string or comment.
 var parseTypoScript = function() {
-  // Token types that can be considered to be atoms.
-  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
+       // Token types that can be considered to be atoms.
+       var atomicTypes = {
+               "atom": true,
+               "number": true,
+               "variable": true,
+               "string": true,
+               "regexp": true
+       };
 
-  // Constructor for the lexical context objects.
-  function TSLexical(indented, column, type, align, prev) {
-    // indentation at start of this line
-    this.indented = indented;
-    // column at which this scope was opened
-    this.column = column;
-    // type of scope ('vardef', 'stat' (statement), '[', '{', or '(')
-    this.type = type;
-    // '[', '{', or '(' blocks that have any text after their opening
-    // character are said to be 'aligned' -- any lines below are
-    // indented all the way to the opening character.
-    if (align != null)
-      this.align = align;
-    // Parent scope, if any.
-    this.prev = prev;
-  }
-  // My favourite indentation rules.
-  TSLexical.prototype.indentation = function(firstChar) {
-    var closing = firstChar == this.type;
-       if (this.type == "}")
-      return this.indented + 2;
+       // Constructor for the lexical context objects.
+       function TSLexical(indented, column, type, align, prev) {
+               // indentation at start of this line
+               this.indented = indented;
+               // column at which this scope was opened
+               this.column = column;
+               // type of scope ('vardef', 'stat' (statement), '[', '{', or '(')
+               this.type = type;
+               // '[', '{', or '(' blocks that have any text after their opening
+               // character are said to be 'aligned' -- any lines below are
+               // indented all the way to the opening character.
+               if (align != null) {
+                       this.align = align;
+               }
+               // Parent scope, if any.
+               this.prev = prev;
 
-    else if (this.align)
-      return this.column - (closing ? 1 : 0);
-    else
-      return this.indented + (closing ? 0 : 2);
-  }
+       }
+       // My favourite indentation rules.
+       TSLexical.prototype.indentation = function(firstChar) {
+               var closing = firstChar == this.type;
 
-  // The parser-iterator-producing function itself.
-  return function(input){
-    // Wrap the input in a token stream
-    var tokens = tokenizeTypoScript(input);
-    // The parser state. cc is a stack of actions that have to be
-    // performed to finish the current statement. For example we might
-    // know that we still need to find a closing parenthesis and a
-    // semicolon. Actions at the end of the stack go first. It is
-    // initialized with an infinitely looping action that consumes
-    // whole statements.
-    var cc = [statements];
-    // Context contains information about the current local scope, the
-    // variables defined in that, and the scopes above it.
-    var context = null;
-    // The lexical scope, used mostly for indentation.
-    var lexical = new TSLexical(-2, 0, "block", false);
-    // Current column, and the indentation at the start of the current
-    // line. Used to create lexical scope objects.
-    var column = 0;
-    var indented = 0;
-    // Variables which are used by the mark, cont, and pass functions
-    // below to communicate with the driver loop in the 'next'
-    // function.
-    var consume, marked;
-  
-    // The iterator object.
-    var parser = {next: next, copy: copy};
+               if (this.type == "}") {
+                       return this.indented + 2;
+               } else if (this.align) {
+                       return this.column - (closing ? 1: 0);
+               } else {
+                       return this.indented + (closing ? 0: 2);
+               }
+       }
 
-    function next(){
-      // Start by performing any 'lexical' actions (adjusting the
-      // lexical variable), or the operations below will be working
-      // with the wrong lexical state.
-      while(cc[cc.length - 1].lex)
-        cc.pop()();
+       // The parser-iterator-producing function itself.
+       return function(input) {
+               // Wrap the input in a token stream
+               var tokens = tokenizeTypoScript(input);
+               // The parser state. cc is a stack of actions that have to be
+               // performed to finish the current statement. For example we might
+               // know that we still need to find a closing parenthesis and a
+               // semicolon. Actions at the end of the stack go first. It is
+               // initialized with an infinitely looping action that consumes
+               // whole statements.
+               var cc = [statements];
+               // Context contains information about the current local scope, the
+               // variables defined in that, and the scopes above it.
+               var context = null;
+               // The lexical scope, used mostly for indentation.
+               var lexical = new TSLexical( - 2, 0, "block", false);
+               // Current column, and the indentation at the start of the current
+               // line. Used to create lexical scope objects.
+               var column = 0;
+               var indented = 0;
+               // Variables which are used by the mark, cont, and pass functions
+               // below to communicate with the driver loop in the 'next'
+               // function.
+               var consume,
+               marked;
 
-      // Fetch a token.
-      var token = tokens.next();
-      // Adjust column and indented.
-      if (token.type == "whitespace" && column == 0)
-        indented = token.value.length;
-      column += token.value.length;
-      if (token.type == "newline"){
-        indented = column = 0;
-       // If the lexical scope's align property is still undefined at
-       // the end of the line, it is an un-aligned scope.
-        if (!("align" in lexical))
-          lexical.align = false;
-       // Newline tokens get a lexical context associated with them,
-       // which is used for indentation.
-        token.lexicalContext = lexical;
-      }
-      // No more processing for meaningless tokens.
-      if (token.type == "whitespace" || token.type == "newline" || token.type == "comment")
-        return token;
-      // When a meaningful token is found and the lexical scope's
-      // align is undefined, it is an aligned scope.
-      if (!("align" in lexical))
-        lexical.align = true;
+               // The iterator object.
+               var parser = {
+                       next: next,
+                       copy: copy
+               };
 
-      // Execute actions until one 'consumes' the token and we can
-      // return it. Marked is used to 
-      while(true){
-        consume = marked = false;
-       // Take and execute the topmost action.
-        cc.pop()(token.type, token.name);
-        if (consume){
-         // Marked is used to change the style of the current token.
-          if (marked)
-            token.style = marked;
+               function next() {
+                       // Start by performing any 'lexical' actions (adjusting the
+                       // lexical variable), or the operations below will be working
+                       // with the wrong lexical state.
+                       while (cc[cc.length - 1].lex) {
+                               cc.pop()();
+                       }
 
-          return token;
-        }
-      }
-    }
+                       // Fetch a token.
+                       var token = tokens.next();
+                       // Adjust column and indented.
+                       if (token.type == "whitespace" && column == 0) {
+                               indented = token.value.length;
+                       }
+                       column += token.value.length;
+                       if (token.type == "newline") {
+                               indented = column = 0;
+                               // If the lexical scope's align property is still undefined at
+                               // the end of the line, it is an un-aligned scope.
+                               if (! ("align" in lexical)) {
+                                       lexical.align = false;
+                               }
+                               // Newline tokens get a lexical context associated with them,
+                               // which is used for indentation.
+                               token.lexicalContext = lexical;
+                       }
+                       // No more processing for meaningless tokens.
+                       if (token.type == "whitespace" || token.type == "newline" || token.type == "comment") {
+                               return token;
+                       }
+                       // When a meaningful token is found and the lexical scope's
+                       // align is undefined, it is an aligned scope.
+                       if (! ("align" in lexical)) {
+                               lexical.align = true;
+                       }
+                       // Execute actions until one 'consumes' the token and we can
+                       // return it. Marked is used to 
+                       while (true) {
+                               consume = marked = false;
+                               // Take and execute the topmost action.
+                               cc.pop()(token.type, token.name);
+                               if (consume) {
+                                       // Marked is used to change the style of the current token.
+                                       if (marked) {
+                                               token.style = marked;
+                                       }
+                                       return token;
+                               }
+                       }
+               }
 
-    // This makes a copy of the parser state. It stores all the
-    // stateful variables in a closure, and returns a function that
-    // will restore them when called with a new input stream. Note
-    // that the cc array has to be copied, because it is contantly
-    // being modified. Lexical objects are not mutated, and context
-    // objects are not mutated in a harmful way, so they can be shared
-    // between runs of the parser.
-    function copy(){
-      var _context = context, _lexical = lexical, _cc = cc.concat([]), _regexp = tokens.regexp, _comment = tokens.inComment;
-  
-      return function(input){
-        context = _context;
-        lexical = _lexical;
-        cc = _cc.concat([]); // copies the array
-        column = indented = 0;
-        tokens = tokenizeTypoScript(input);
-        tokens.regexp = _regexp;
-        tokens.inComment = _comment;
-        return parser;
-      };
-    }
+               // This makes a copy of the parser state. It stores all the
+               // stateful variables in a closure, and returns a function that
+               // will restore them when called with a new input stream. Note
+               // that the cc array has to be copied, because it is contantly
+               // being modified. Lexical objects are not mutated, and context
+               // objects are not mutated in a harmful way, so they can be shared
+               // between runs of the parser.
+               function copy() {
+                       var _context = context,
+                       _lexical = lexical,
+                       _cc = cc.concat([]),
+                       _regexp = tokens.regexp,
+                       _comment = tokens.inComment;
 
-    // Helper function for pushing a number of actions onto the cc
-    // stack in reverse order.
-    function push(fs){
-      for (var i = fs.length - 1; i >= 0; i--)
-        cc.push(fs[i]);
-    }
-    // cont and pass are used by the action functions to add other
-    // actions to the stack. cont will cause the current token to be
-    // consumed, pass will leave it for the next action.
-    function cont(){
-      push(arguments);
-      consume = true;
-    }
-    function pass(){
-      push(arguments);
-      consume = false;
-    }
-    // Used to change the style of the current token.
-    function mark(style){
-      marked = style;
-    }
+                       return function(input) {
+                               context = _context;
+                               lexical = _lexical;
+                               cc = _cc.concat([]);
+                               // copies the array
+                               column = indented = 0;
+                               tokens = tokenizeTypoScript(input);
+                               tokens.regexp = _regexp;
+                               tokens.inComment = _comment;
+                               return parser;
+                       };
+               }
 
-    // Push a new scope. Will automatically link the the current
-    // scope.
-    function pushcontext(){
-      context = {prev: context, vars: {"this": true, "arguments": true}};
-    }
-    // Pop off the current scope.
-    function popcontext(){
-      context = context.prev;
-    }
-    // Register a variable in the current scope.
-    function register(varname){
-      if (context){
-        mark("variabledef");
-        context.vars[varname] = true;
-      }
-    }
+               // Helper function for pushing a number of actions onto the cc
+               // stack in reverse order.
+               function push(fs) {
+                       for (var i = fs.length - 1; i >= 0; i--) {
+                               cc.push(fs[i]);
+                       }
+               }
+               
+               // cont and pass are used by the action functions to add other
+               // actions to the stack. cont will cause the current token to be
+               // consumed, pass will leave it for the next action.
+               function cont() {
+                       push(arguments);
+                       consume = true;
+               }
+               
+               function pass() {
+                       push(arguments);
+                       consume = false;
+               }
+               
+               // Used to change the style of the current token.
+               function mark(style) {
+                       marked = style;
+               }
 
-  
-    // Push a new lexical context of the given type.
-    function pushlex(type){
-      var result = function(){
-        lexical = new TSLexical(indented, column, type, null, lexical)
-      };
-      result.lex = true;
-      return result;
-    }
-    // Pop off the current lexical context.
-    function poplex(){
-      lexical = lexical.prev;
-    }
-    poplex.lex = true;
-    // The 'lex' flag on these actions is used by the 'next' function
-    // to know they can (and have to) be ran before moving on to the
-    // next token.
-  
-    // Creates an action that discards tokens until it finds one of
-    // the given type.
-    function expect(wanted){
-      return function(type){
-        if (type == wanted) cont();
-        else cont(arguments.callee);
-      };
-    }
+               // Push a new scope. Will automatically link the the current
+               // scope.
+               function pushcontext() {
+                       context = {
+                               prev: context,
+                               vars: {
+                                       "this": true,
+                                       "arguments": true
+                               }
+                       };
+               }
+               
+               // Pop off the current scope.
+               function popcontext() {
+                       context = context.prev;
+               }
+               
+               // Register a variable in the current scope.
+               function register(varname) {
+                       if (context) {
+                               mark("variabledef");
+                               context.vars[varname] = true;
+                       }
+               }
 
-    // Looks for a statement, and then calls itself.
-    function statements(type){
-      return pass(statement, statements);
-    }
-    // Dispatches various types of statements based on the type of the
-    // current token.
-    function statement(type){
-         if (type == "{")              cont(pushlex("{"), block, poplex);
-         // else if (type == "[")              cont(pushlex("]"), condition, poplex);
-      else cont();
-    }
-       
-    // Dispatch expression types.
-    function expression(type){
-      if (atomicTypes.hasOwnProperty(type)) cont(maybeoperator);
-      else if (type == "function")                     cont(functiondef);
-      else if (type == "keyword c")            cont(expression);
-      else if (type == "(")                            cont(pushlex(")"), expression, expect(")"), poplex);
-      else if (type == "operator")                     cont(expression);
-      else if (type == "[")                            cont(pushlex("]"), commasep(expression), expect("]"), poplex);
-      else if (type == "{")                            cont(pushlex("}"), commasep(objprop), expect("}"), poplex);
-    }
-    // Called for places where operators, function calls, or
-    // subscripts are valid. Will skip on to the next action if none
-    // is found.
-    function maybeoperator(type){
-      if (type == "operator") cont(expression);
-      else if (type == "(") cont(pushlex(")"), expression, commasep(expression), expect(")"), poplex);
-      else if (type == ".") cont(property, maybeoperator);
-      else if (type == "[") cont(pushlex("]"), expression, expect("]"), poplex);
-    }
-    // When a statement starts with a variable name, it might be a
-    // label. If no colon follows, it's a regular statement.
-    function maybelabel(type){
-      if (type == ":") cont(poplex, statement);
-      else pass(maybeoperator, expect(";"), poplex);
-    }
-    // Property names need to have their style adjusted -- the
-    // tokenizer think they are variables.
-    function property(type){
-      if (type == "variable") {mark("property"); cont();}
-    }
-    // This parses a property and its value in an object literal.
-    function objprop(type){
-      if (type == "variable") mark("property");
-      if (atomicTypes.hasOwnProperty(type)) cont(expect(":"), expression);
-    }
-    // Parses a comma-separated list of the things that are recognized
-    // by the 'what' argument.
-    function commasep(what){
-      function proceed(type) {
-        if (type == ",") cont(what, proceed);
-      };
-      return function() {
-        pass(what, proceed);
-      };
-    }
-       
-    // Look for statements until a closing brace is found.
-    function block(type){
-         if (type == "}") cont();
-      else pass(statement, block);
-    }
-       
-    // Look for statements until a closing brace is found.
-    function condition(type){
-      if (type == "]") cont();
-      else pass(statement, block);
-    }
-       
-       
-    // Variable definitions are split into two actions -- 1 looks for
-    // a name or the end of the definition, 2 looks for an '=' sign or
-    // a comma.
-    function vardef1(type, value){
-      if (type == "variable"){register(value); cont(vardef2);}
-      else cont();
-    }
-    function vardef2(type){
-      if (type == "operator") cont(expression, vardef2);
-      else if (type == ",") cont(vardef1);
-    }
-    // For loops.
-    function forspec1(type, value){
-      if (type == "var") cont(vardef1, forspec2);
-      else cont(expression, forspec2);
-    }
-    function forspec2(type){
-      if (type == ",") cont(forspec1);
-      if (type == ";") cont(expression, expect(";"), expression);
-    }
-    // A function definition creates a new context, and the variables
-    // in its argument list have to be added to this context.
-    function functiondef(type, value){
-      if (type == "variable"){register(value); cont(functiondef);}
-      else if (type == "(") cont(pushcontext, commasep(funarg), expect(")"), statement, popcontext);
-    }
-    function funarg(type, value){
-      if (type == "variable"){register(value); cont();}
-    }
-  
-    return parser;
-  }
-}();
+               // Push a new lexical context of the given type.
+               function pushlex(type) {
+                       var result = function() {
+                               lexical = new TSLexical(indented, column, type, null, lexical)
+                       };
+                       result.lex = true;
+                       return result;
+               }
+               
+               // Pop off the current lexical context.
+               function poplex() {
+                       lexical = lexical.prev;
+               }
+               
+               poplex.lex = true;
+               // The 'lex' flag on these actions is used by the 'next' function
+               // to know they can (and have to) be ran before moving on to the
+               // next token.
+
+               // Creates an action that discards tokens until it finds one of
+               // the given type.
+               function expect(wanted) {
+                       return function(type) {
+                               if (type == wanted) {
+                                       cont();
+                               } else {
+                                       cont(arguments.callee);
+                               }
+                       };
+               }
+
+               // Looks for a statement, and then calls itself.
+               function statements(type) {
+                       return pass(statement, statements);
+               }
+               // Dispatches various types of statements based on the type of the
+               // current token.
+               function statement(type) {
+                       if (type == "{") {
+                               cont(pushlex("{"), block, poplex);
+                       } else {
+                               cont();
+                       }
+               }
+
+               // Dispatch expression types.
+               function expression(type) {
+                       if (atomicTypes.hasOwnProperty(type)) {
+                               cont(maybeoperator);
+                       
+                       } else if (type == "function") {
+                               cont(functiondef);
+                       
+                       } else if (type == "keyword c") {
+                               cont(expression);
+                       
+                       } else if (type == "(") {
+                               cont(pushlex(")"), expression, expect(")"), poplex);
+                       
+                       } else if (type == "operator") {
+                               cont(expression);
+                       
+                       } else if (type == "[") {
+                               cont(pushlex("]"), commasep(expression), expect("]"), poplex);
+                       
+                       } else if (type == "{") {
+                               cont(pushlex("}"), commasep(objprop), expect("}"), poplex);
+                       }
+               }
+               
+               // Called for places where operators, function calls, or
+               // subscripts are valid. Will skip on to the next action if none
+               // is found.
+               function maybeoperator(type) {
+                       if (type == "operator") {
+                               cont(expression);
+                       
+                       } else if (type == "(") {
+                               cont(pushlex(")"), expression, commasep(expression), expect(")"), poplex);
+                       
+                       } else if (type == ".") {
+                               cont(property, maybeoperator);
+                       
+                       } else if (type == "[") {
+                               cont(pushlex("]"), expression, expect("]"), poplex);
+                       } 
+               }
+               
+               // When a statement starts with a variable name, it might be a
+               // label. If no colon follows, it's a regular statement.
+               function maybelabel(type) {
+                       if (type == ":") {
+                               cont(poplex, statement);
+                       } else {
+                               pass(maybeoperator, expect(";"), poplex);
+                       }
+               }
+               
+               // Property names need to have their style adjusted -- the
+               // tokenizer think they are variables.
+               function property(type) {
+                       if (type == "variable") {
+                               mark("property");
+                               cont();
+                       }
+               }
+               
+               // This parses a property and its value in an object literal.
+               function objprop(type) {
+                       if (type == "variable") {
+                               mark("property");
+                       }
+                       if (atomicTypes.hasOwnProperty(type)) {
+                               cont(expect(":"), expression);
+                       }
+               }
+
+               // Parses a comma-separated list of the things that are recognized
+               // by the 'what' argument.
+               function commasep(what) {
+                       function proceed(type) {
+                               if (type == ",") {
+                                       cont(what, proceed);
+                               }
+                       };
+                       return function() {
+                               pass(what, proceed);
+                       };
+               }
+
+               // Look for statements until a closing brace is found.
+               function block(type) {
+                       if (type == "}") {
+                               cont();
+                       } else {
+                               pass(statement, block);
+                       }
+               }
+
+               // Look for statements until a closing brace is found.
+               function condition(type) {
+                       if (type == "]") 7
+                               cont();
+                       } else {
+                               pass(statement, block);
+                       }
+               }
+
+               // Variable definitions are split into two actions -- 1 looks for
+               // a name or the end of the definition, 2 looks for an '=' sign or
+               // a comma.
+               function vardef1(type, value) {
+                       if (type == "variable") {
+                               register(value);
+                               cont(vardef2);
+                       } else {
+                               cont();
+                       }
+               }
+               
+               function vardef2(type) {
+                       if (type == "operator") {
+                               cont(expression, vardef2);
+                       } else if (type == ",") {
+                               cont(vardef1);
+                       }
+               }
+               
+               // For loops.
+               function forspec1(type, value) {
+                       if (type == "var") {
+                               cont(vardef1, forspec2);
+                       } else {
+                               cont(expression, forspec2);
+                       }
+               }
+               
+               function forspec2(type) {
+                       if (type == ",") {
+                               cont(forspec1);
+                       }
+                       if (type == ";") {
+                               cont(expression, expect(";"), expression);
+                       }
+               }
+               
+               // A function definition creates a new context, and the variables
+               // in its argument list have to be added to this context.
+               function functiondef(type, value) {
+                       if (type == "variable") {
+                               register(value);
+                               cont(functiondef);
+                       } else if (type == "(") {
+                               cont(pushcontext, commasep(funarg), expect(")"), statement, popcontext);
+                       }
+               }
+               
+               function funarg(type, value) {
+                       if (type == "variable") {
+                               register(value);
+                               cont();
+                       }
+               }
+
+               return parser;
+       }
+} ();
\ No newline at end of file
index 192f9e2..fe9699a 100755 (executable)
 // Namespace object.
 var select = {};
 
-(function() {
-  var ie_selection = document.selection && document.selection.createRangeCollection;
+ (function() {
+       var ie_selection = document.selection && document.selection.createRangeCollection;
 
-  // Find the 'top-level' (defined as 'a direct child of the node
-  // passed as the top argument') node that the given node is
-  // contained in. Return null if the given node is not inside the top
-  // node.
-  function topLevelNodeAt(node, top) {
-    while (node && node.parentNode != top)
-      node = node.parentNode;
-    return node;
-  }
+       // Find the 'top-level' (defined as 'a direct child of the node
+       // passed as the top argument') node that the given node is
+       // contained in. Return null if the given node is not inside the top
+       // node.
+       function topLevelNodeAt(node, top) {
+               while (node && node.parentNode != top) {
+                       node = node.parentNode;
+               }
+               return node;
+       }
+
+       // Find the top-level node that contains the node before this one.
+       function topLevelNodeBefore(node, top) {
+               if (!node) {
+                       return null;
+               }
+               
+               while (!node.previousSibling && node.parentNode != top) {
+                       node = node.parentNode;
+               }
 
-  // Find the top-level node that contains the node before this one.
-  function topLevelNodeBefore(node, top) {
-    if (!node){
-        return null;
-    }
-    while (!node.previousSibling && node.parentNode != top){
-        node = node.parentNode;
-    }
-      
-    return topLevelNodeAt(node.previousSibling, top);
-  }
+               return topLevelNodeAt(node.previousSibling, top);
+       }
 
-  // Most functions are defined in two ways, one for the IE selection
-  // model, one for the W3C one.
-  if (ie_selection) {
-    // Store the current selection in such a way that it can be
-    // restored after we manipulated the DOM tree. For IE, we store
-    // pixel coordinates.
-    select.markSelection = function (win) {
-      var selection = win.document.selection;
-      var start = selection.createRange(), end = start.duplicate();
-      start.collapse(true);
-      end.collapse(false);
+       // Most functions are defined in two ways, one for the IE selection
+       // model, one for the W3C one.
+       if (ie_selection) {
+               // Store the current selection in such a way that it can be
+               // restored after we manipulated the DOM tree. For IE, we store
+               // pixel coordinates.
+               select.markSelection = function(win) {
+                       var selection = win.document.selection;
+                       var start = selection.createRange(),
+                       end = start.duplicate();
+                       start.collapse(true);
+                       end.collapse(false);
 
-      var body = win.document.body;
-      // And we better hope no fool gave this window a padding or a
-      // margin, or all these computations will be in vain.
-      return {start: {x: start.boundingLeft + body.scrollLeft - 1,
-                      y: start.boundingTop + body.scrollTop},
-              end: {x: end.boundingLeft + body.scrollLeft - 1,
-                    y: end.boundingTop + body.scrollTop},
-              window: win};
-    };
+                       var body = win.document.body;
+                       // And we better hope no fool gave this window a padding or a
+                       // margin, or all these computations will be in vain.
+                       return {
+                               start: {
+                                       x: start.boundingLeft + body.scrollLeft - 1,
+                                       y: start.boundingTop + body.scrollTop
+                               },
+                               end: {
+                                       x: end.boundingLeft + body.scrollLeft - 1,
+                                       y: end.boundingTop + body.scrollTop
+                               },
+                               window: win
+                       };
+               };
 
-    // Restore a stored selection.
-    select.selectMarked = function(sel) {
-      if (!sel)
-       return;
-      var range1 = sel.window.document.body.createTextRange(), range2 = range1.duplicate();
-      range1.moveToPoint(sel.start.x, sel.start.y);
-      range2.moveToPoint(sel.end.x, sel.end.y);
-      range1.setEndPoint("EndToStart", range2);
-      range1.select();
-    };
+               // Restore a stored selection.
+               select.selectMarked = function(sel) {
+                       if (!sel) {
+                               return;
+                       }
+                       var range1 = sel.window.document.body.createTextRange(),
+                       range2 = range1.duplicate();
+                       range1.moveToPoint(sel.start.x, sel.start.y);
+                       range2.moveToPoint(sel.end.x, sel.end.y);
+                       range1.setEndPoint("EndToStart", range2);
+                       range1.select();
+               };
 
-    // Not needed in IE model -- see W3C model.
-    select.replaceSelection = function(){};
+               // Not needed in IE model -- see W3C model.
+               select.replaceSelection = function() {};
 
-    // A Cursor object represents a top-level node that the cursor is
-    // currently in or after. It is not possible to reliably get more
-    // detailed information, but just this node is enough for most
-    // purposes.
-    select.Cursor = function(container) {
-        this.container = container;
-        this.doc = container.ownerDocument;
-        var selection = this.doc.selection;
-        this.valid = !!selection;
-        if (this.valid) {
-            var range = selection.createRange();
-            range.collapse(false);
-            var around = range.parentElement();
-            if (around && isAncestor(container, around)) {
-                  this.start = topLevelNodeAt(around, container);
-            }
-            else {
-                range.pasteHTML("<span id='// temp //'></span>");
-                var temp = this.doc.getElementById("// temp //");
-                this.start = topLevelNodeBefore(temp, container);
-                if (temp)
-                    removeElement(temp);
-            }
-        }
-    };
+               // A Cursor object represents a top-level node that the cursor is
+               // currently in or after. It is not possible to reliably get more
+               // detailed information, but just this node is enough for most
+               // purposes.
+               select.Cursor = function(container) {
+                       this.container = container;
+                       this.doc = container.ownerDocument;
+                       var selection = this.doc.selection;
+                       this.valid = !!selection;
+                       if (this.valid) {
+                               var range = selection.createRange();
+                               range.collapse(false);
+                               var around = range.parentElement();
+                               if (around && isAncestor(container, around)) {
+                                       this.start = topLevelNodeAt(around, container);
+                               } else {
+                                       range.pasteHTML("<span id='// temp //'></span>");
+                                       var temp = this.doc.getElementById("// temp //");
+                                       this.start = topLevelNodeBefore(temp, container);
+                                       if (temp) {
+                                               removeElement(temp);
+                                       }
+                               }
+                       }
+               };
 
-    // Place the cursor after this.start. This is only useful when
-    // manually moving the cursor instead of restoring it to its old
-    // position.
-    select.Cursor.prototype.focus = function () {
-      var range = this.doc.body.createTextRange();
-      range.moveToElementText(this.start || this.container);
-      range.collapse(!this.start);
-      range.select();
-    };
+               // Place the cursor after this.start. This is only useful when
+               // manually moving the cursor instead of restoring it to its old
+               // position.
+               select.Cursor.prototype.focus = function() {
+                       var range = this.doc.body.createTextRange();
+                       range.moveToElementText(this.start || this.container);
+                       range.collapse(!this.start);
+                       range.select();
+               };
 
+               // Used to normalize the effect of the enter key, since browsers
+               // do widely different things when pressing enter in designMode.
+               select.insertNewlineAtCursor = function(window) {
+                       var selection = window.document.selection;
+                       if (selection) {
+                               var range = selection.createRange();
+                               range.pasteHTML("<br/>");
+                               range.collapse(false);
+                               range.select();
+                       }
+               };
 
-    // Used to normalize the effect of the enter key, since browsers
-    // do widely different things when pressing enter in designMode.
-    select.insertNewlineAtCursor = function(window) {
-      var selection = window.document.selection;
-      if (selection) {
-       var range = selection.createRange();
-       range.pasteHTML("<br/>");
-       range.collapse(false);
-       range.select();
-      }
-    };
+               // Insert a custom string at current cursor position (added for t3editor)
+               select.insertTextAtCursor = function(window, text) {
+                       var selection = window.document.selection;
+                       if (selection) {
+                               var range = selection.createRange();
+                               range.pasteHTML(text);
+                               range.collapse(false);
+                               range.select();
+                       }
+               };
+       }
        
-       // Insert a custom string at current cursor position (added for t3editor)
-    select.insertTextAtCursor = function(window,text) {
-      var selection = window.document.selection;
-      if (selection) {
-        var range = selection.createRange();
-        range.pasteHTML(text);
-        range.collapse(false);
-       range.select();
-      }
-       };
-         
-  }
-  // W3C model
-  else {
-    // Well, Opera isn't even supported at the moment, but it almost
-    // is, and this is used to fix an issue with getting the scroll
-    // position.
-    var opera_scroll = !window.scrollX && !window.scrollY;
+       // W3C model
+       else {
+               // Well, Opera isn't even supported at the moment, but it almost
+               // is, and this is used to fix an issue with getting the scroll
+               // position.
+               var opera_scroll = !window.scrollX && !window.scrollY;
 
-    // Store start and end nodes, and offsets within these, and refer
-    // back to the selection object from those nodes, so that this
-    // object can be updated when the nodes are replaced before the
-    // selection is restored.
-    select.markSelection = function (win) {
-      var selection = win.getSelection();
-      if (!selection || selection.rangeCount == 0)
-       return null;
-      var range = selection.getRangeAt(0);
+               // Store start and end nodes, and offsets within these, and refer
+               // back to the selection object from those nodes, so that this
+               // object can be updated when the nodes are replaced before the
+               // selection is restored.
+               select.markSelection = function(win) {
+                       var selection = win.getSelection();
+                       if (!selection || selection.rangeCount == 0) {
+                               return null;
+                       }
+                       var range = selection.getRangeAt(0);
 
-      var result = {start: {node: range.startContainer, offset: range.startOffset},
-                    end: {node: range.endContainer, offset: range.endOffset},
-                    window: win,
-                    scrollX: opera_scroll && win.document.body.scrollLeft,
-                    scrollY: opera_scroll && win.document.body.scrollTop};
+                       var result = {
+                               start: {
+                                       node: range.startContainer,
+                                       offset: range.startOffset
+                               },
+                               end: {
+                                       node: range.endContainer,
+                                       offset: range.endOffset
+                               },
+                               window: win,
+                               scrollX: opera_scroll && win.document.body.scrollLeft,
+                               scrollY: opera_scroll && win.document.body.scrollTop
+                       };
 
-      // We want the nodes right at the cursor, not one of their
-      // ancestors with a suitable offset. This goes down the DOM tree
-      // until a 'leaf' is reached (or is it *up* the DOM tree?).
-      function normalize(point){
-       while (point.node.nodeType != 3 && point.node.nodeName != "BR") {
-          var newNode = point.node.childNodes[point.offset] || point.node.nextSibling;
-          point.offset = 0;
-          while (!newNode && point.node.parentNode) {
-            point.node = point.node.parentNode;
-            newNode = point.node.nextSibling;
-          }
-          point.node = newNode;
-          if (!newNode)
-            break;
-       }
-      }
+                       // We want the nodes right at the cursor, not one of their
+                       // ancestors with a suitable offset. This goes down the DOM tree
+                       // until a 'leaf' is reached (or is it *up* the DOM tree?).
+                       function normalize(point) {
+                               while (point.node.nodeType != 3 && point.node.nodeName != "BR") {
+                                       var newNode = point.node.childNodes[point.offset] || point.node.nextSibling;
+                                       point.offset = 0;
+                                       while (!newNode && point.node.parentNode) {
+                                               point.node = point.node.parentNode;
+                                               newNode = point.node.nextSibling;
+                                       }
+                                       point.node = newNode;
+                                       if (!newNode) {
+                                               break;
+                                       }
+                               }
+                       }
 
-      normalize(result.start);
-      normalize(result.end);
-      // Make the links back to the selection object (see
-      // replaceSelection).
-      if (result.start.node)
-       result.start.node.selectStart = result.start;
-      if (result.end.node)
-       result.end.node.selectEnd = result.end;
+                       normalize(result.start);
+                       normalize(result.end);
+                       
+                       // Make the links back to the selection object (see
+                       // replaceSelection).
+                       if (result.start.node) {
+                               result.start.node.selectStart = result.start;
+                       }
+                       if (result.end.node) {
+                               result.end.node.selectEnd = result.end;
+                       }
+                       return result;
+               };
 
-      return result;
-    };
+               // Helper for selecting a range object.
+               function selectRange(range, window) {
+                       var selection = window.getSelection();
+                       if (selection) {
+                               selection.removeAllRanges();
+                               selection.addRange(range);
+                       }
+               };
 
-    // Helper for selecting a range object.
-    function selectRange(range, window) {
-      var selection = window.getSelection();
-      selection.removeAllRanges();
-      selection.addRange(range);
-    };
+               select.selectMarked = function(sel) {
+                       if (!sel) {
+                               return;
+                       }
+                       var win = sel.window;
+                       var range = win.document.createRange();
 
-    select.selectMarked = function (sel) {
-      if (!sel)
-       return;
-      var win = sel.window;
-      var range = win.document.createRange();
+                       function setPoint(point, which) {
+                               if (point.node) {
+                                       // Remove the link back to the selection.
+                                       delete point.node["select" + which];
+                                       // Some magic to generalize the setting of the start and end
+                                       // of a range.
+                                       if (point.offset == 0) {
+                                               range["set" + which + "Before"](point.node);
+                                       } else {
+                                               range["set" + which](point.node, point.offset);
+                                       }
+                               } else {
+                                       range.setStartAfter(win.document.body.lastChild || win.document.body);
+                               }
+                       }
 
-      function setPoint(point, which) {
-       if (point.node) {
-         // Remove the link back to the selection.
-          delete point.node["select" + which];
-         // Some magic to generalize the setting of the start and end
-         // of a range.
-          if (point.offset == 0)
-            range["set" + which + "Before"](point.node);
-          else
-            range["set" + which](point.node, point.offset);
-       }
-       else {
-          range.setStartAfter(win.document.body.lastChild || win.document.body);
-       }
-      }
+                       // Have to restore the scroll position of the frame in Opera.
+                       if (opera_scroll) {
+                               sel.window.document.body.scrollLeft = sel.scrollX;
+                               sel.window.document.body.scrollTop = sel.scrollY;
+                       }
+                       
+                       try {
+                               setPoint(sel.start, "Start");
+                               setPoint(sel.end, "End");
+                               selectRange(range, win);
+                       } catch(e) {}
+               };
 
-      // Have to restore the scroll position of the frame in Opera.
-      if (opera_scroll){
-       sel.window.document.body.scrollLeft = sel.scrollX;
-       sel.window.document.body.scrollTop = sel.scrollY;
-      }
-         try {
-        setPoint(sel.start, "Start");
-        setPoint(sel.end, "End");
-        selectRange(range, win);
-         } catch(e) {}
-    };
+               // This is called by the code in codemirror.js whenever it is
+               // replacing a part of the DOM tree. The function sees whether the
+               // given oldNode is part of the current selection, and updates
+               // this selection if it is. Because nodes are often only partially
+               // replaced, the length of the part that gets replaced has to be
+               // taken into account -- the selection might stay in the oldNode
+               // if the newNode is smaller than the selection's offset. The
+               // offset argument is needed in case the selection does move to
+               // the new object, and the given length is not the whole length of
+               // the new node (part of it might have been used to replace
+               // another node).
+               select.replaceSelection = function(oldNode, newNode, length, offset) {
+                       function replace(which) {
+                               var selObj = oldNode["select" + which];
+                               if (selObj) {
+                                       if (selObj.offset > length) {
+                                               selObj.offset -= length;
+                                       } else {
+                                               newNode["select" + which] = selObj;
+                                               delete oldNode["select" + which];
+                                               selObj.node = newNode;
+                                               selObj.offset += (offset || 0);
+                                       }
+                               }
+                       }
+                       replace("Start");
+                       replace("End");
+               };
 
-    // This is called by the code in codemirror.js whenever it is
-    // replacing a part of the DOM tree. The function sees whether the
-    // given oldNode is part of the current selection, and updates
-    // this selection if it is. Because nodes are often only partially
-    // replaced, the length of the part that gets replaced has to be
-    // taken into account -- the selection might stay in the oldNode
-    // if the newNode is smaller than the selection's offset. The
-    // offset argument is needed in case the selection does move to
-    // the new object, and the given length is not the whole length of
-    // the new node (part of it might have been used to replace
-    // another node).
-    select.replaceSelection = function(oldNode, newNode, length, offset) {
-      function replace(which) {
-       var selObj = oldNode["select" + which];
-       if (selObj) {
-          if (selObj.offset > length) {
-            selObj.offset -= length;
-          }
-          else {
-            newNode["select" + which] = selObj;
-            delete oldNode["select" + which];
-            selObj.node = newNode;
-            selObj.offset += (offset || 0);
-          }
-       }
-      }
-      replace("Start");
-      replace("End");
-    };
+               // Finding the top-level node at the cursor in the W3C is, as you
+               // can see, quite an involved process. [Some of this can probably
+               // be simplified, but I'm afraid to touch it now that it finally
+               // works.]
+               select.Cursor = function(container) {
+                       this.container = container;
+                       this.win = container.ownerDocument.defaultView;
+                       var selection = this.win.getSelection();
+                       this.valid = selection && selection.rangeCount > 0;
+                       if (this.valid) {
+                               var range = selection.getRangeAt(0);
+                               var end = range.endContainer;
+                               // For text nodes, we look at the node itself if the cursor is
+                               // inside, or at the node before it if the cursor is at the
+                               // start.
+                               if (end.nodeType == 3) {
+                                       if (range.endOffset > 0) {
+                                               this.start = topLevelNodeAt(end, this.container);
+                                       } else {
+                                               this.start = topLevelNodeBefore(end, this.container);
+                                       }
+                               }
+                               
+                               // Occasionally, browsers will return the HTML node as
+                               // selection (Opera does this all the time, which is the
+                               // reason this editor does not work on that browser). If the
+                               // offset is 0, we take the start of the frame ('after null'),
+                               // otherwise, we take the last node.
+                               else if (end.nodeName == "HTML") {
+                                       this.start = (range.endOffset == 1 ? null: container.lastChild);
+                               }
 
-    // Finding the top-level node at the cursor in the W3C is, as you
-    // can see, quite an involved process. [Some of this can probably
-    // be simplified, but I'm afraid to touch it now that it finally
-    // works.]
-    select.Cursor = function(container) {
-      this.container = container;
-      this.win = container.ownerDocument.defaultView;
-      var selection = this.win.getSelection();
-      this.valid = selection && selection.rangeCount > 0;
-      if (this.valid) {
-       var range = selection.getRangeAt(0);
-       var end = range.endContainer;
-       // For text nodes, we look at the node itself if the cursor is
-       // inside, or at the node before it if the cursor is at the
-       // start.
-    
-       if (end.nodeType == 3){
-          if (range.endOffset > 0)
-            this.start = topLevelNodeAt(end, this.container);
-          else
-            this.start = topLevelNodeBefore(end, this.container);
-       }
-       // Occasionally, browsers will return the HTML node as
-       // selection (Opera does this all the time, which is the
-       // reason this editor does not work on that browser). If the
-       // offset is 0, we take the start of the frame ('after null'),
-       // otherwise, we take the last node.
-       else if (end.nodeName == "HTML") {
-          this.start = (range.endOffset == 1 ? null : container.lastChild);
-       }
-       // If the given node is our 'container', we just look up the
-       // correct node by using the offset.
-       else if (end == container) {
-          if (range.endOffset == 0)
-            this.start = null;
-          else
-            this.start = end.childNodes[range.endOffset - 1];
-       }
-       // In any other case, we have a regular node. If the cursor is
-       // at the end of the node, we use the node itself, if it is at
-       // the start, we use the node before it, and in any other
-       // case, we look up the child before the cursor and use that.
-       else {
-          if (range.endOffset == end.childNodes.length)
-            this.start = topLevelNodeAt(end, this.container);
-          else if (range.endOffset == 0)
-            this.start = topLevelNodeBefore(end, this.container);
-          else
-            this.start = topLevelNodeAt(end.childNodes[range.endOffset - 1], this.container);
-       }
-      }
-    };
+                               // If the given node is our 'container', we just look up the
+                               // correct node by using the offset.
+                               else if (end == container) {
+                                       if (range.endOffset == 0) {
+                                               this.start = null;
+                                       } else {
+                                               this.start = end.childNodes[range.endOffset - 1];
+                                       }
+                               }
+                               
+                               // In any other case, we have a regular node. If the cursor is
+                               // at the end of the node, we use the node itself, if it is at
+                               // the start, we use the node before it, and in any other
+                               // case, we look up the child before the cursor and use that.
+                               else {
+                                       if (range.endOffset == end.childNodes.length) {
+                                               this.start = topLevelNodeAt(end, this.container);
+                                       } else if (range.endOffset == 0) {
+                                               this.start = topLevelNodeBefore(end, this.container);
+                                       } else {
+                                               this.start = topLevelNodeAt(end.childNodes[range.endOffset - 1], this.container);
+                                       }
+                               }
+                       }
+               };
 
-    select.Cursor.prototype.focus = function() {
-        var sel = this.win.getSelection();
-        var range = this.win.document.createRange();
-        range.setStartBefore(this.container.firstChild || this.container);
-        if (this.start)
-            range.setEndAfter(this.start);
-        else
-            range.setEndBefore(this.container.firstChild || this.container);
-                 
-        range.collapse(false);
-        selectRange(range, this.win);
-    };
-       
-       
+               select.Cursor.prototype.focus = function() {
+                       var sel = this.win.getSelection();
+                       var range = this.win.document.createRange();
+                       range.setStartBefore(this.container.firstChild || this.container);
+                       if (this.start) {
+                               range.setEndAfter(this.start);
+                       } else {
+                               range.setEndBefore(this.container.firstChild || this.container);
+                       }
+                       
+                       range.collapse(false);
+                       selectRange(range, this.win);
+               };
 
-    select.insertNewlineAtCursor = function(window) {
-      var selection = window.getSelection();
-      if (selection && selection.rangeCount > 0) {
-       var range = selection.getRangeAt(0);
-       var br = window.document.createElement('br');
-       range.insertNode(br);
-       range.setEndAfter(br);
-       range.collapse(false);
-       selectRange(range, window);
-      }
-    };
-       
-       // added for t3editor
-    select.insertTextAtCursor = function(window,text) {
-      var selection = window.getSelection();
-      if (selection && selection.rangeCount > 0) {
-        var range = selection.getRangeAt(0);
-        // var br = withDocument(window.document, BR);
-        textnode = window.document.createTextNode(text);
-        range.insertNode(textnode);
-        range.setEndAfter(textnode);
-        range.collapse(false);
-        selectRange(range, window);
-      }
-    }; 
-  
-       // added for t3editor
-    select.insertNodeAtCursor = function(window,node) {
-      var selection = window.getSelection();
-      if (selection && selection.rangeCount > 0) {
-        var range = selection.getRangeAt(0);
-        range.insertNode(node);
-        range.setEndAfter(node);
-        range.collapse(false);
-        selectRange(range, window);
-      }
-    }; 
-  }
+               select.insertNewlineAtCursor = function(window) {
+                       var selection = window.getSelection();
+                       if (selection && selection.rangeCount > 0) {
+                               var range = selection.getRangeAt(0);
+                               var br = window.document.createElement('br');
+                               range.insertNode(br);
+                               range.setEndAfter(br);
+                               range.collapse(false);
+                               selectRange(range, window);
+                       }
+               };
+
+               // added for t3editor
+               select.insertTextAtCursor = function(window, text) {
+                       var selection = window.getSelection();
+                       if (selection && selection.rangeCount > 0) {
+                               var range = selection.getRangeAt(0);
+                               // var br = withDocument(window.document, BR);
+                               textnode = window.document.createTextNode(text);
+                               range.insertNode(textnode);
+                               range.setEndAfter(textnode);
+                               range.collapse(false);
+                               selectRange(range, window);
+                       }
+               };
+
+               // added for t3editor
+               select.insertNodeAtCursor = function(window, node) {
+                       var selection = window.getSelection();
+                       if (selection && selection.rangeCount > 0) {
+                               var range = selection.getRangeAt(0);
+                               range.insertNode(node);
+                               range.setEndAfter(node);
+                               range.collapse(false);
+                               selectRange(range, window);
+                       }
+               };
+       }
 
-  // Search backwards through the top-level nodes until the next BR or
-  // the start of the frame.
-  select.Cursor.prototype.startOfLine = function() {
-    var start = this.start || this.container.firstChild;
-    while (start && start.nodeName != "BR")
-      start = start.previousSibling;
-    return start;
-  };
-}());
+       // Search backwards through the top-level nodes until the next BR or
+       // the start of the frame.
+       select.Cursor.prototype.startOfLine = function() {
+               var start = this.start || this.container.firstChild;
+               while (start && start.nodeName != "BR") {
+                       start = start.previousSibling;
+               }
+               return start;
+       };
+} ());
\ No newline at end of file
index 3052e57..ed16b3d 100644 (file)
@@ -8,69 +8,86 @@
 // Make a stream out of a single string. Not used by the editor, but
 // very useful for testing your parser.
 function singleStringStream(string) {
-  var pos = 0, start = 0;
-  
-  function peek() {
-    if (pos < string.length)
-      return string.charAt(pos);
-    else
-      return null;
-  }
+       var pos = 0,
+       start = 0;
 
-  function next() {
-    if (pos >= string.length)
-      throw StopIteration;
-    return string.charAt(pos++);
-  }
+       function peek() {
+               if (pos < string.length) {
+                       return string.charAt(pos);
+               } else {
+                       return null;
+               }
+       }
 
-  function get() {
-    var result = string.slice(start, pos);
-    start = pos;
-    return result;
-  }
+       function next() {
+               if (pos >= string.length) {
+                       throw StopIteration;
+               }
+               return string.charAt(pos++);
+       }
+
+       function get() {
+               var result = string.slice(start, pos);
+               start = pos;
+               return result;
+       }
+
+       return {
+               peek: peek,
+               next: next,
+               get: get
+       };
 
-  return {peek: peek, next: next, get: get};
 }
 
 // Make a string stream out of an iterator that returns strings. This
 // is applied to the result of traverseDOM (see codemirror.js), and
 // the resulting stream is fed to the parser.
-function multiStringStream(source){
-  // source = iter(source);
-  var current = "", pos = 0;
-  var peeked = null, accum = "";
-  var result = {peek: peek, next: next, get: get};
-
-  function peek(){
-    if (!peeked)
-      peeked = nextOr(result, null);
-    return peeked;
-  }
-  function next(){
-    if (peeked){
-      var temp = peeked;
-      peeked = null;
-      return temp;
-    }
-    while (pos == current.length){
-      accum += current;
-      current = ""; // In case source.next() throws
-      pos = 0;
-      current = source.next();
-    }
-    return current.charAt(pos++);
-  }
-  function get(){
-    var temp = accum;
-    var realPos = peeked ? pos - 1 : pos;
-    accum = "";
-    if (realPos > 0){
-      temp += current.slice(0, realPos);
-      current = current.slice(realPos);
-      pos = peeked ? 1 : 0;
-    }
-    return temp;
-  }
+function multiStringStream(source) {
+       // source = iter(source);
+       var current = "",
+       pos = 0;
+       var peeked = null,
+       accum = "";
+       var result = {
+               peek: peek,
+               next: next,
+               get: get
+       };
 
-  return result;
+       function peek() {
+               if (!peeked) {
+                       peeked = nextOr(result, null);
+               }
+               return peeked;
+       }
+       
+       function next() {
+               if (peeked) {
+                       var temp = peeked;
+                       peeked = null;
+                       return temp;
+               }
+               while (pos == current.length) {
+                       accum += current;
+                       current = "";
+                       // In case source.next() throws
+                       pos = 0;
+                       current = source.next();
+               }
+               return current.charAt(pos++);
+       }
+       
+       function get() {
+               var temp = accum;
+               var realPos = peeked ? pos - 1: pos;
+               accum = "";
+               if (realPos > 0) {
+                       temp += current.slice(0, realPos);
+                       current = current.slice(realPos);
+                       pos = peeked ? 1: 0;
+               }
+               return temp;
+       }
+       return result;
 }
index 93d4319..fb78964 100755 (executable)
 
 
 
-/**
- * Browser checks
- *  inspired by tinyMCE
- */
-var ua = navigator.userAgent;
-var isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-var isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
-var isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
-var isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
-var isGecko = ua.indexOf('Gecko') != -1; // Will also be true on Safari
-var isSafari = ua.indexOf('Safari') != -1;
-var isOpera = window['opera'] && opera.buildNumber ? true : false;
-var isMac = ua.indexOf('Mac') != -1;
-var isNS7 = ua.indexOf('Netscape/7') != -1;
-var isNS71 = ua.indexOf('Netscape/7.1') != -1;
-
-
 
 // collection of all t3editor instances on the current page
 var t3e_instances = {};
@@ -85,279 +68,293 @@ var t3eOptions = window.t3eOptions || {};
 //   code to 'freeze' the browser for noticeable intervals.
 // passDelay gives the amount of milliseconds between colouring passes
 var t3eOptions = {
-               safeKeys:       { "KEY_ARROW_UP":true, 
-                                         "KEY_ARROW_DOWN":true, 
-                                         "KEY_ARROW_LEFT":true, 
-                                         "KEY_ARROW_RIGHT":true, 
-                                         "KEY_END":true, 
-                                         "KEY_HOME":true,
-                                         "KEY_PAGE_UP":true, 
-                                         "KEY_PAGE_DOWN":true, 
-                                         "KEY_SHIFT":true, 
-                                         "KEY_CTRL":true, 
-                                         "KEY_ALT":true, 
-                                         "KEY_SELECT":true
-               },
-               reindentKeys: {"KEY_TAB":true},
-               reindentAfterKeys: {"KEY_RIGHT_SQUARE_BRACKET":true},
-               stylesheet: PATH_t3e+"css/t3editor.css",
-               parser: parseTypoScript,
-               linesPerPass: 10,
-               passDelay: 200,
-               autoComplete: true,
-               acWords:5
-       };
+       safeKeys: {
+               "KEY_ARROW_UP": true,
+               "KEY_ARROW_DOWN": true,
+               "KEY_ARROW_LEFT": true,
+               "KEY_ARROW_RIGHT": true,
+               "KEY_END": true,
+               "KEY_HOME": true,
+               "KEY_PAGE_UP": true,
+               "KEY_PAGE_DOWN": true,
+               "KEY_SHIFT": true,
+               "KEY_CTRL": true,
+               "KEY_ALT": true,
+               "KEY_SELECT": true
+       },
+       stylesheet: PATH_t3e + "css/t3editor.css",
+       parser: parseTypoScript,
+       linesPerPass: 10,
+       passDelay: 200,
+       autoComplete: true,
+       acWords: 5
+
+};
 // These default options can be overridden by passing a set of options
 // to a specific CodeMirror constructor.
 
-var t3editor = function(){
-  // The HTML elements whose content should be suffixed by a newline
-  // when converting them to flat text.
-  var newlineElements = {"P":true, "DIV":true, "LI":true};
-
-  // Helper function for traverseDOM. Flattens an arbitrary DOM node
-  // into an array of textnodes and <br> tags.
-  function simplifyDOM(root) {
-    var doc = root.ownerDocument;
-    var result = [];
-    var leaving = false;
-
-    function simplifyNode(node) {
-      leaving = false;
-
-      if (node.nodeType == 3) {
-        node.nodeValue = node.nodeValue.replace(/[\n\r]/g, "").replace(/[\t ]/g, nbsp);
-        result.push(node);
-      }
-      else if (node.nodeName == "BR" && node.childNodes.length == 0) {
-        result.push(node);
-      }
-      else {
-        // forEach(node.childNodes, simplifyNode);
-        $A(node.childNodes).each(simplifyNode);
-        if (!leaving && newlineElements.hasOwnProperty(node.nodeName)) {
-          leaving = true;
-          el = new Element('SPAN');            
-                 result.push(new Element('BR'));   
-        }
-      }
-    }
-
-    simplifyNode(root);
-    return result;
-  }
-
-  // Creates a MochiKit-style iterator that goes over a series of DOM
-  // nodes. The values it yields are strings, the textual content of
-  // the nodes. It makes sure that all nodes up to and including the
-  // one whose text is being yielded have been 'normalized' to be just
-  // <span> and <br> elements.
-  // See the story.html file for some short remarks about the use of
-  // continuation-passing style in this iterator.
-  function traverseDOM(start){
-    function yield(value, c){cc = c; return value;}
-    function push(fun, arg, c){return function(){return fun(arg, c);};}
-    function stop(){cc = stop; throw StopIteration;};
-    var cc = push(scanNode, start, stop);
-    var owner = start.ownerDocument;
-
-    // Create a function that can be used to insert nodes after the
-    // one given as argument.
-    function pointAt(node){
-      var parent = node.parentNode;
-      var next = node.nextSibling;
-      if (next)
-        return function(newnode){parent.insertBefore(newnode, next);};
-      else
-        return function(newnode){parent.appendChild(newnode);};
-    }
-    var point = null;
-
-    // Insert a normalized node at the current point. If it is a text
-    // node, wrap it in a <span>, and give that span a currentText
-    // property -- this is used to cache the nodeValue, because
-    // directly accessing nodeValue is horribly slow on some browsers.
-    // The dirty property is used by the highlighter to determine
-    // which parts of the document have to be re-highlighted.
-    function insertPart(part){
-      var text = "\n";
-      if (part.nodeType == 3) {
-        text = part.nodeValue;
-        
-        newpart = new Element('SPAN',{"class": "part"});
-        newpart.appendChild(part);
-        part = newpart;
-        part.currentText = text;
-      }
-      part.dirty = true;
-      point(part);
-      return text;
-    }
-
-    // Extract the text and newlines from a DOM node, insert them into
-    // the document, and yield the textual content. Used to replace
-    // non-normalized nodes.
-    function writeNode(node, c){
-      var toYield = [];
-      var simdom = simplifyDOM(node);
+var t3editor = function() {
+       // The HTML elements whose content should be suffixed by a newline
+       // when converting them to flat text.
+       var newlineElements = {
+               "P": true,
+               "DIV": true,
+               "LI": true
+       };
+
+       // Helper function for traverseDOM. Flattens an arbitrary DOM node
+       // into an array of textnodes and <br> tags.
+       function simplifyDOM(root) {
+               var doc = root.ownerDocument;
+               var result = [];
+               var leaving = false;
+
+               function simplifyNode(node) {
+                       leaving = false;
+
+                       if (node.nodeType == 3) {
+                               node.nodeValue = node.nodeValue.replace(/[\n\r]/g, "").replace(/[\t ]/g, nbsp);
+                               result.push(node);
+                       } else if (node.nodeName == "BR" && node.childNodes.length == 0) {
+                               result.push(node);
+                       } else {
+                               // forEach(node.childNodes, simplifyNode);
+                               $A(node.childNodes).each(simplifyNode);
+                               if (!leaving && newlineElements.hasOwnProperty(node.nodeName)) {
+                                       leaving = true;
+                                       el = new Element('SPAN');
+                                       result.push(new Element('BR'));
+                               }
+                       }
+               }
+
+               simplifyNode(root);
+               return result;
+       }
+
+       // Creates a MochiKit-style iterator that goes over a series of DOM
+       // nodes. The values it yields are strings, the textual content of
+       // the nodes. It makes sure that all nodes up to and including the
+       // one whose text is being yielded have been 'normalized' to be just
+       // <span> and <br> elements.
+       // See the story.html file for some short remarks about the use of
+       // continuation-passing style in this iterator.
+       function traverseDOM(start) {
+               function yield(value, c) {
+                       cc = c;
+                       return value;
+               }
+               function push(fun, arg, c) {
+                       return function() {
+                               return fun(arg, c);
+                       };
+               }
+               function stop() {
+                       cc = stop;
+                       throw StopIteration;
+               }
+               var cc = push(scanNode, start, stop);
+               var owner = start.ownerDocument;
+
+               // Create a function that can be used to insert nodes after the
+               // one given as argument.
+               function pointAt(node) {
+                       var parent = node.parentNode;
+                       var next = node.nextSibling;
+                       if (next) {
+                               return function(newnode) {
+                                       parent.insertBefore(newnode, next);
+                               };
+                       }
+                       else {
+                               return function(newnode) {
+                                       parent.appendChild(newnode);
+                               };
+                       }
+               }
+               var point = null;
+
+               // Insert a normalized node at the current point. If it is a text
+               // node, wrap it in a <span>, and give that span a currentText
+               // property -- this is used to cache the nodeValue, because
+               // directly accessing nodeValue is horribly slow on some browsers.
+               // The dirty property is used by the highlighter to determine
+               // which parts of the document have to be re-highlighted.
+               function insertPart(part) {
+                       var text = "\n";
+                       if (part.nodeType == 3) {
+                               text = part.nodeValue;
+
+                               newpart = new Element('SPAN', {
+                                       "class": "part"
+                               });
+                               newpart.appendChild(part);
+                               part = newpart;
+                               part.currentText = text;
+                       }
+                       part.dirty = true;
+                       point(part);
+                       return text;
+               }
+
+               // Extract the text and newlines from a DOM node, insert them into
+               // the document, and yield the textual content. Used to replace
+               // non-normalized nodes.
+               function writeNode(node, c) {
+                       var toYield = [];
+                       var simdom = simplifyDOM(node);
                        simdom.each(
                                function(part) {
                                        toYield.push(insertPart(part));
                                }
                        );
 
-      return yield(toYield.join(""), c);
-    }
-
-    // Check whether a node is a normalized <span> element.
-    function partNode(node){
-      if (node.nodeName == "SPAN" && node.childNodes.length == 1 && node.firstChild.nodeType == 3){
-        node.currentText = node.firstChild.nodeValue;
-        return true;
-      }
-      return false;
-    }
-
-    // Handle a node. Add its successor to the continuation if there
-    // is one, find out whether the node is normalized. If it is,
-    // yield its content, otherwise, normalize it (writeNode will take
-    // care of yielding).
-    function scanNode(node, c){
-      if (node.nextSibling)
-        c = push(scanNode, node.nextSibling, c);
-
-      if (partNode(node)){
-        return yield(node.currentText, c);
-      }
-      else if (node.nodeName == "BR") {
-        return yield("\n", c);
-      }
-      else {
-        point = pointAt(node);
-        Element.remove(node);
-        return writeNode(node, c);
-      }
-    }
-
-    // MochiKit iterators are objects with a next function that
-    // returns the next value or throws StopIteration when there are
-    // no more values.
-    return {next: function(){return cc();}};
-  } // traverseDOM
-
-  var nbspRegexp = new RegExp(nbsp, "g");
-
-
-
-  function t3editor(theTextarea, index, options) {
-   
-   // Use passed options, if any, to override defaults.
-    this.options = options || t3eOptions; // {}
-    for (var lo in options) {
-               this.options[lo] = options[lo];
-       }
-       
-    //History Array
-    this.history = [];
-    //Max History Size
-    this.historySize = 100;
-    //Init history position
-    this.currHistoryPosition = -1;
-
-       // memorize the textarea
-       this.textarea = $(theTextarea);
-    
-       this.documentname = this.textarea.readAttribute('alt');
-       
-       // count index (helpful if more than one editor is on the page)
-       this.index = index;
-
-    // create the wrapping div
-    this.outerdiv = new Element("div", {
-                               "class":        "t3e_outerdiv",
-                               "id":           "t3e_"+this.textarea.getAttribute('id')
+                       return yield(toYield.join(""), c);
+               }
+
+               // Check whether a node is a normalized <span> element.
+               function partNode(node) {
+                       if (node.nodeName == "SPAN" 
+                         && node.childNodes.length == 1 
+                         && node.firstChild.nodeType == 3) {
+                               node.currentText = node.firstChild.nodeValue;
+                               return true;
                        }
-               );
+                       return false;
+               }
 
-       // place the div before the textarea
-    this.textarea.parentNode.insertBefore(this.outerdiv,$(this.textarea));
+               // Handle a node. Add its successor to the continuation if there
+               // is one, find out whether the node is normalized. If it is,
+               // yield its content, otherwise, normalize it (writeNode will take
+               // care of yielding).
+               function scanNode(node, c) {
+                       if (node.nextSibling) {
+                               c = push(scanNode, node.nextSibling, c);
+                       }
+                       if (partNode(node)) {
+                               return yield(node.currentText, c);
+                       } else if (node.nodeName == "BR") {
+                               return yield("\n", c);
+                       } else {
+                               point = pointAt(node);
+                               Element.remove(node);
+                               return writeNode(node, c);
+                       }
+               }
 
-       // an overlay that covers the whole editor
-               this.modalOverlay = new Element("DIV", {
-                               "class":        "t3e_modalOverlay",
-                               "id":           "t3e_modalOverlay_wait"
+               // MochiKit-like iterators are objects with a next function that
+               // returns the next value or throws StopIteration when there are
+               // no more values.
+               return {
+                       next: function() {
+                               return cc();
                        }
-               );
-    this.modalOverlay.hide();
-    this.modalOverlay.setStyle(this.outerdiv.getDimensions());
-    this.modalOverlay.setStyle({opacity: 0.5});
-    this.outerdiv.appendChild(this.modalOverlay);
-       
+               };
+       } // traverseDOM
+
+       var nbspRegexp = new RegExp(nbsp, "g");
+
+       function t3editor(theTextarea, index, options) {
+
+               // Use passed options, if any, to override defaults.
+               this.options = options || t3eOptions;
+
+               for (var lo in options) {
+                       this.options[lo] = options[lo];
+               }
+
+               // memorize the textarea
+               this.textarea = $(theTextarea);
+
+               this.documentname = this.textarea.readAttribute('alt');
+
+               // count index (helpful if more than one editor is on the page)
+               this.index = index;
+
+               // create the wrapping div
+               this.outerdiv = new Element("div", {
+                       "class": "t3e_outerdiv",
+                       "id": "t3e_" + this.textarea.getAttribute('id')
+               });
+
+               // place the div before the textarea
+               this.textarea.parentNode.insertBefore(this.outerdiv, $(this.textarea));
+
+               // an overlay that covers the whole editor
+               this.modalOverlay = new Element("DIV", {
+                       "class": "t3e_modalOverlay",
+                       "id": "t3e_modalOverlay_wait"
+               });
+               
+               this.modalOverlay.hide();
+               this.modalOverlay.setStyle(this.outerdiv.getDimensions());
+               this.modalOverlay.setStyle({
+                       opacity: 0.5
+               });
+               this.outerdiv.appendChild(this.modalOverlay);
+
                this.helpOverlay = new Element("DIV", {
-                               "class":        "t3e_modalOverlay",
-                               "id":           "t3e_modalOverlay_help"
-                       }
-               );
-                       // TODO: fill with senseful content, make it dynamic
-    this.helpOverlay.innerHTML = "<h2>t3editor</h2>"+
-                                                                       "<p>put some helpful text here</p><br/><br/>"+
-                                                                       "<p>Hotkeys:</p>"+
-                                                                       "<p>"+
-                                                                       "<strong>CTRL-S</strong> send code to server<br/>"+
-                                                                       "<strong>CTRL-F11</strong> toggle fullscreen mode<br/>"+
-                                                                       "<strong>CTRL-SPACE</strong> auto-complete (based on letters at current cursor-position)<br/>"+
-                                                                       "<strong>CTRL-Z</strong> undo<br/>"+
-                                                                       "<strong>CTRL-Y</strong> redo<br/>"+
-                                                                       "</p><br/>"+
-                                                                       "<p><a href='javascript:void(0)' onclick='t3e_instances["+this.index+"].toggleHelp();'>click here to close this help window</a></p>"+
-                                                                       "";
-    this.helpOverlay.hide();
-       this.outerdiv.appendChild(this.helpOverlay);
-    
+                       "class": "t3e_modalOverlay",
+                       "id": "t3e_modalOverlay_help"
+               });
+               
+               // TODO: fill with senseful content, make it dynamic
+               this.helpOverlay.innerHTML = 
+               "<div class='closedok_icon'>"+
+                "<a href='javascript:void(0)' onclick='t3e_instances[" + this.index + "].toggleHelp();'>"+
+                "<img src='"+PATH_t3e+"../t3skin/icons/gfx/closedok.gif' alt='click here to close this help window' title='click here to close this help window' />"+
+                "</a></div>" +
+               "<h2>t3editor</h2>" + 
+               "<p>'t3editor' is a javascript-driven code editor with syntax highlighting for TypoScript</p><br/>" +
+               "<p>It's based on the 'Codemirror' editor.</p><br/><br/>" + 
+               "<p>Hotkeys:</p>" + 
+               "<p>" + 
+               "<strong>CTRL-S</strong> save/send code to server<br/>" + 
+               "<strong>CTRL-F11</strong> toggle fullscreen mode<br/>" + 
+               "<strong>CTRL-SPACE</strong> auto-complete (based on letters at current cursor-position)<br/>" + 
+               "</p><br/>" +
+               "";
+               this.helpOverlay.hide();
+               this.outerdiv.appendChild(this.helpOverlay);
+
                // wrapping the linenumbers
                this.linenum_wrap = new Element("DIV", {
-                               "class":        "t3e_linenum_wrap"
-                       }
-               );
+                       "class": "t3e_linenum_wrap"
+               });
                // the "linenumber" list itself
                this.linenum = new Element("DL", {
-                               "class":        "t3e_linenum"
-                       }
-               );
-    this.linenum_wrap.appendChild(this.linenum);
-    this.outerdiv.appendChild(this.linenum_wrap);
-    
-    //autocomplete box
-               this.autoCompleteBox = new Element("DIV",{
-                               "class":        "t3e_autoCompleteBox"
-                       }
-               );
+                       "class": "t3e_linenum"
+               });
+               this.linenum_wrap.appendChild(this.linenum);
+               this.outerdiv.appendChild(this.linenum_wrap);
+
+               //autocomplete box
+               this.autoCompleteBox = new Element("DIV", {
+                       "class": "t3e_autoCompleteBox"
+               });
                this.autoCompleteBox.hide();
                this.outerdiv.appendChild(this.autoCompleteBox);
 
                // wrapping the iframe
                this.iframe_wrap = new Element("DIV", {
-                               "class":        "t3e_iframe_wrap"
-                       }
-               );
+                       "class": "t3e_iframe_wrap"
+               });
 
                // the iframe (the actual "editor")
                // display: block occasionally suppresses some Firefox bugs, so we
                // always add it, redundant as it sounds.
                this.iframe = new Element("IFRAME", {
-                               "style":        "border: 0; display: block;",
-                               "class":        "t3e_iframe" 
-                       }
-               );
+                       "style": "border: 0; display: block;",
+                       "class": "t3e_iframe"
+               });
 
-    this.iframe_wrap.appendChild(this.iframe);
-    this.outerdiv.appendChild(this.iframe_wrap);
-    
-       // wrapping the footer/statusline
+               this.iframe_wrap.appendChild(this.iframe);
+               this.outerdiv.appendChild(this.iframe_wrap);
+
+               // wrapping the footer/statusline
                this.footer_wrap = new Element("DIV", {
-                               "class":        "t3e_footer_wrap"
-                       }
-               );
+                       "class": "t3e_footer_wrap"
+               });
                this.outerdiv.appendChild(this.footer_wrap);
 
                // footer item: show help Window
@@ -367,17 +364,15 @@ var t3editor = function(){
 
                // footer item: options menu
                this.fitem_options_overlay = new Element("DIV", {
-                               "class":        "t3e_footer_overlay",
-                               "id":           "t3e_footer_overlay_options"
-                       }
-               );
+                       "class": "t3e_footer_overlay",
+                       "id": "t3e_footer_overlay_options"
+               });
 
                // TODO make this more flexible! And get rid of inline css and unsed options!
-               this.fitem_options_overlay.innerHTML = '<ul>'+
+               this.fitem_options_overlay.innerHTML = '<ul>' + 
                        // '<li style="color:grey"><input type="checkbox" disabled="disabled" /> Syntax highlighting</li>'+ 
-                       '<li><input type="checkbox" onclick="t3e_instances['+this.index+'].fitem_options_overlay.hide();t3e_instances['+this.index+'].toggleAutoComplete();" id="t3e_autocomplete" checked="checked" /><label for="t3e_autocomplete">AutoCompletion</label></li>'+
-                       '<li><span onclick="t3e_instances['+this.index+'].fitem_options_overlay.hide();t3e_instances['+this.index+'].footeritem_demo_click();">Test snippets</span></li>'+
-                       '<li><input type="checkbox" onclick="t3e_instances['+this.index+'].fitem_options_overlay.hide();t3e_instances['+this.index+'].toggleFullscreen();" id="t3e_fullscreen" /> <label for="t3e_fullscreen">Fullscreen</label></li>'+
+                       '<li><input type="checkbox" onclick="t3e_instances[' + this.index + '].fitem_options_overlay.hide();t3e_instances[' + this.index + '].toggleAutoComplete();" id="t3e_autocomplete" checked="checked" /><label for="t3e_autocomplete">AutoCompletion</label></li>' + 
+                       '<li><input type="checkbox" onclick="t3e_instances[' + this.index + '].fitem_options_overlay.hide();t3e_instances[' + this.index + '].toggleFullscreen();" id="t3e_fullscreen" /> <label for="t3e_fullscreen">Fullscreen</label></li>' + 
                        // '<li style="color:grey"><input type="checkbox" disabled="disabled" /> other fancy stuff</li>'+
                        '</ul>';
                this.fitem_options_overlay.hide();
@@ -402,10 +397,10 @@ var t3editor = function(){
 
                this.doc.open();
                this.doc.write(
-                       "<html><head>"+
+                       "<html><head>" + 
                        "<link rel=\"stylesheet\" type=\"text/css\" href=\"" + 
-                        t3eOptions.stylesheet + 
-                       "\"/></head>" +
+                       t3eOptions.stylesheet + 
+                       "\"/></head>" + 
                        "<body class=\"editbox\" spellcheck=\"false\"></body></html>");
                this.doc.close();
 
@@ -414,9 +409,8 @@ var t3editor = function(){
                this.dirty = [];
 
                // dimensions
-               this.width   = $(this.textarea).getDimensions().width;
-               this.height  = $(this.textarea).getDimensions().height;
-
+               this.width = $(this.textarea).getDimensions().width;
+               this.height = $(this.textarea).getDimensions().height;
                var content = this.textarea.value;
 
                // hide the textarea
@@ -424,28 +418,36 @@ var t3editor = function(){
 
                // Some browsers immediately produce a <body> in a new <iframe>,
                // others only do so later and fire an onload event when they do.
-               if (this.doc.body)      {
+               if (this.doc.body) {
                        this.init(content);
-               } else  {
+
+               } else {
                        // connect(this.iframe, "onload", bind(function(){disconnectAll(this.iframe, "onload"); this.init(content);}, this));
-                       Event.observe(this.iframe, "load", function(){ this.init(content);}.bindAsEventListener(this));
+                       Event.observe(this.iframe, "load", 
+                       function() {
+                               this.init(content);
+                       }.bindAsEventListener(this));
                }
-  }
+       }
+
 
+       /**
+        * define t3editor methods
+        */
+       t3editor.prototype = {
 
+               textModified: false,
+               // editor-content has been modified
+               saveAjaxEvent: null,
+               // Event for save code with ajax        
 
-  t3editor.prototype = {
+               // Called after we are sure that our frame has a body
+               init: function(code) {
+                       this.container = this.doc.body;
 
-       textModified: false,    // editor-content has been modified
-       saveAjaxEvent: null,    // Event for save code with ajax        
-       
-    // Called after we are sure that our frame has a body
-    init: function (code) {
-      this.container = this.doc.body;
-      
-         // fetch key press events
+                       // fetch key press events
                        Event.observe(this.doc, "keydown", this.keyDown.bindAsEventListener(this));
-                       Event.observe(this.doc, "keyup",   this.keyUp.bindAsEventListener(this));
+                       Event.observe(this.doc, "keyup", this.keyUp.bindAsEventListener(this));
 
                        // fetch scroll events for updateing line numbers
                        Event.observe(this.doc, "scroll", this.scroll.bindAsEventListener(this));
@@ -461,1125 +463,1095 @@ var t3editor = function(){
                        // initialize ajax saving events
                        this.saveAjaxEvent = this.saveAjax.bind(this);
                        this.saveButtons.each(function(button) {
-                               Event.observe(button,'click',this.saveAjaxEvent);
+                               Event.observe(button, 'click', this.saveAjaxEvent);
                        }.bind(this));
 
-         // resize the editor
-      this.resize(this.width, this.height);
-         
-      //Import code to editor. If code is empty the method importCode put a BR or SPAN into the codewindow - dependence on browser
-      this.importCode(code);
-         
-         // set focus
-         this.win.focus();
-        var cursor = new select.Cursor(this.container);
-       cursor.focus();
-    
-    },
-       
-       // for demonstation only!
-       footeritem_demo_click: function() {
-               // insertNewlineAtCursor(this.win);
-        
-        // focus editor and cursor
-        this.win.focus();
-        var cursor = new select.Cursor(this.container);
-        cursor.start = this.cursorObj;
-        cursor.focus();
-
-               select.insertTextAtCursor(this.win, "page = PAGE");select.insertNewlineAtCursor(this.win);
-               select.insertTextAtCursor(this.win, "page {");     select.insertNewlineAtCursor(this.win);
-               select.insertTextAtCursor(this.win, "  10 = TEXT");select.insertNewlineAtCursor(this.win);
-               select.insertTextAtCursor(this.win, "  10.value = Hello World!");               select.insertNewlineAtCursor(this.win);
-               select.insertTextAtCursor(this.win, "}");                       select.insertNewlineAtCursor(this.win);
-               
-               this.markCursorDirty();
-               this.scheduleHighlight();
-       },
-       
-    // toggle between the textarea and t3editor
-       toggleView: function(checkboxEnabled)   {
-               if (checkboxEnabled) {
-                       this.textarea.value = this.getCode();
-                       this.outerdiv.hide();
-                       this.textarea.show();
-                       this.saveButtons.each(function(button) {
-                       Event.stopObserving(button,'click',this.saveAjaxEvent);
-               }.bind(this));
-               } else {
-                       this.importCode(this.textarea.value);
-                       this.textarea.hide();
-                       this.outerdiv.show();
+                       // get the form object (needed for Ajax saving)
+                       var form = $(this.textarea.form)
+                       this.saveButtons = form.getInputs('image', 'submit');
+
+                       // initialize ajax saving events
+                       this.saveAjaxEvent = this.saveAjax.bind(this);
                        this.saveButtons.each(function(button) {
-                       Event.observe(button,'click',this.saveAjaxEvent);
-               }.bind(this));
-               }
-       },
+                               Event.observe(button, 'click', this.saveAjaxEvent);
+                       }.bind(this));
 
-       // create an item for the footer line and connect an event
-    createFooterItem: function(title, mouseover, clickAction)  {
+                       // resize the editor
+                       this.resize(this.width, this.height);
+
+                       //Import code to editor. If code is empty the method importCode put a BR or SPAN into the codewindow - dependence on browser
+                       this.importCode(code);
+
+                       // set focus
+                       this.win.focus();
+                       var cursor = new select.Cursor(this.container);
+                       cursor.focus();
+               },
+
+               // toggle between the textarea and t3editor
+               toggleView: function(checkboxEnabled) {
+                       if (checkboxEnabled) {
+                               this.textarea.value = this.getCode();
+                               this.outerdiv.hide();
+                               this.textarea.show();
+                               this.saveButtons.each(function(button) {
+                                       Event.stopObserving(button, 'click', this.saveAjaxEvent);
+                               }.bind(this));
+
+                       } else {
+                               this.importCode(this.textarea.value);
+                               this.textarea.hide();
+                               this.outerdiv.show();
+                               this.saveButtons.each(function(button) {
+                                       Event.observe(button, 'click', this.saveAjaxEvent);
+                               }.bind(this));
+                       }
+               },
+
+               // create an item for the footer line and connect an event
+               createFooterItem: function(title, mouseover, clickAction) {
                        var item = new Element("DIV", {
-                                       "class":        "t3e_footer_item"
+                               "class": "t3e_footer_item"
+                       });
+                       item.innerHTML = title;
+
+                       if (mouseover) {
+                               item.addClassName('t3e_clickable');
+                               Event.observe(item, "mouseover", 
+                                       function(e) {
+                                               Event.element(e).addClassName('t3e_footeritem_active');
+                                       });
+                               Event.observe(item, "mouseout", 
+                                       function(e) {
+                                               Event.element(e).removeClassName('t3e_footeritem_active');
+                                       });
+                       }
+                       if (typeof clickAction == 'object') {
+                               // display an overlay
+                               Event.observe(item, "click", 
+                                       function(e) {
+                                               clickAction.toggle();
+                                       });
+
+                       } else if (typeof clickAction == 'string' && clickAction != '') {
+                               // execute a method
+                               Event.observe(item, "click", 
+                                       function(e) {
+                                               eval(clickAction);
+                                       }.bindAsEventListener(this));
+                       }
+                       return item;
+               },
+
+               // resize the editor
+               resize: function(width, height) {
+                       if (this.outerdiv) {
+                               newheight = (height - 1);
+                               newwidth = (width + 11);
+                               if (Prototype.Browser.IE) newwidth = newwidth + 8;
+                               $(this.outerdiv).setStyle({
+                                       height: newheight + 'px',
+                                       width: newwidth + 'px'
+                               });
+
+                               this.linenum_wrap.setStyle({
+                                       height: (height - 22) + 'px'    // less footer height
+                               });
+
+                               numwwidth = this.linenum_wrap.getWidth();
+                               if (Prototype.Browser.IE) numwwidth = numwwidth - 17;
+                               if (!Prototype.Browser.IE) numwwidth = numwwidth - 11;
+
+                               this.iframe.setStyle({
+                                       height: (height - 22) + 'px',   // less footer height (TODO)
+                                       width: (width - numwwidth) + 'px'
+                               });
+
+                               this.modalOverlay.setStyle(this.outerdiv.getDimensions());
+                       }
+               },
+
+               // toggle between normal view and fullscreen mode
+               toggleFullscreen: function() {
+                       if (this.outerdiv.hasClassName('t3e_fullscreen')) {
+                               // turn fullscreen off
+
+                               // unhide the scrollbar of the body
+                               this.outerdiv.offsetParent.setStyle({
+                                       overflow: ''
+                               });
+
+                               this.outerdiv.removeClassName('t3e_fullscreen');
+                               h = this.textarea.getDimensions().height;
+                               w = this.textarea.getDimensions().width;
+
+                       } else {
+                               // turn fullscreen on
+                               this.outerdiv.addClassName('t3e_fullscreen');
+                               h = this.outerdiv.offsetParent.getHeight();
+                               w = this.outerdiv.offsetParent.getWidth();
+
+                               // less scrollbar width
+                               w = w - 13;
+
+                               // hide the scrollbar of the body
+                               this.outerdiv.offsetParent.setStyle({
+                                       overflow: 'hidden'
+                               });
+                       }
+                       this.resize(w, h);
+               },
+
+               toggleHelp: function() {
+                       this.modalOverlay.toggle();
+                       this.helpOverlay.toggle();
+               },
+
+               // toggle AutoCompletion beetwen on and off
+               toggleAutoComplete: function() {
+                       this.options.autoComplete = (this.options.autoComplete) ? false: true;
+               },
+
+               // autocomplete box
+               autoComplete: function() {
+                       this.clicked = false;
+                       //get lastword into this.lastWord
+                       this.getLastWord();
+                       // init vars for up/down moving in word list
+                       this.ac_up = 0;
+                       this.ac_down = this.options.acWords - 1;
+
+                       //refresh cursorObj
+                       var cursor = new select.Cursor(this.container);
+                       this.cursorObj = cursor.start;
+
+                       //init currWord, used in word list. Contain selected word
+                       this.currWord = -1;
+
+                       // If lastword is not empty and not space - continue
+                       if (this.lastWord != '&nbsp;' && this.lastWord) {
+                               // get list of words
+                               this.words = this.getCompleteWordsByTrigger(this.lastWord.toLowerCase());
+                               // if words are found - show box
+                               if (this.words.length > 0) {
+                                       // make UL list of completation words
+                                       var html = '<ul>';
+                                       for (i = 0; i < this.words.length; i++) {
+                                               html += '<li style="height:16px;vertical-align:middle;" ' + 
+                                                       'id="ac_word_' + i + '" ' +
+                                                       'onclick="t3e_instances[' + this.index + '].clicked=true; ' +
+                                                        't3e_instances[' + this.index + '].insertCurrWordAtCursor();" ' +
+                                                       'onmouseover="t3e_instances[' + this.index + '].highlightCurrWord(' + i + ');">' +
+                                                       '<span class="word_' + this.words[i].type + '">' + 
+                                                       this.words[i].word + 
+                                                       '</span></li>';
+                                       }
+                                       html += '</ul>';
+                                       
+                                       //put HTML and show box
+                                       this.autoCompleteBox.innerHTML = html;
+                                       this.autoCompleteBox.show();
+                                       this.autoCompleteBox.scrollTop = 0;
+                                       
+                                       //  init styles
+                                       if (this.words.length > this.options.acWords) {
+                                               this.autoCompleteBox.style.overflowY = 'scroll';
+                                               if (Prototype.Browser.Gecko) {
+                                                       this.autoCompleteBox.style.height = (this.options.acWords * ($("ac_word_0").offsetHeight)) + 'px';
+                                               } else {
+                                                       this.autoCompleteBox.style.height = (this.options.acWords * ($("ac_word_0").offsetHeight)) + 4 + 'px';
+                                                       this.autoCompleteBox.style.width = this.autoCompleteBox.offsetWidth + 20 + 'px';
+                                               }
+                                       } else {
+                                               this.autoCompleteBox.setStyle({
+                                                       overflowY: 'auto',
+                                                       height: 'auto',
+                                                       width: 'auto'
+                                               });
+                                       }
+                                       
+                                       // positioned box to word
+                                       this.autoCompleteBox.setStyle({
+                                               left: (Position.cumulativeOffset(this.iframe)[0]
+                                                    - Position.cumulativeOffset(this.outerdiv)[0]
+                                                    + Position.cumulativeOffset(cursor.start)[0]
+                                                    + cursor.start.offsetWidth) + 'px',
+                                               top: (Position.cumulativeOffset(this.iframe)[1]
+                                                    - Position.cumulativeOffset(this.outerdiv)[1]
+                                                    + Position.cumulativeOffset(cursor.start)[1]
+                                                    + cursor.start.offsetHeight
+                                                    - this.container.scrollTop) + 'px'
+                                       });
+                                       
+                                       // set flag to 1 - needed for continue typing word. 
+                                       this.ac = 1;
+                                       // highlight first word in list
+                                       this.highlightCurrWord(0);
                                }
-                       );
-       item.innerHTML = title;
-       
-       if (mouseover) {
-                       item.addClassName('t3e_clickable');
-               Event.observe(item, "mouseover", function(e){Event.element(e).addClassName('t3e_footeritem_active');} );
-               Event.observe(item, "mouseout",  function(e){Event.element(e).removeClassName('t3e_footeritem_active');} );
-               }
-               if (typeof clickAction == 'object') { // display an overlay
-                       Event.observe(item, "click",  function(e){ clickAction.toggle(); } );
-               
-               } else if (typeof clickAction == 'string' && clickAction != '') {       // execute a method
-                       Event.observe(item, "click",  function(e){ eval(clickAction); }.bindAsEventListener(this) );
-               }
+                       }
+               },
                
-       return item;
-    },
-    
-       // resize the editor
-    resize: function(width, height)    {
-               if (this.outerdiv) {
-                       
-                       // TODO: make it more flexible, get rid of "hardcoded" numbers!
-                       
-                       newheight = (height - 1);
-                       newwidth  = (width + 11);
-                       if (isMSIE) newwidth = newwidth + 8;
+               // Get word where cursor focused
+               getLastWord: function() {
+                       var cursor = new select.Cursor(this.container);
+                       if (cursor.start) {
+                               this.lastTrigger = this.lastWord;
+                               this.lastWord = (cursor.start.innerHTML) ? cursor.start.innerHTML: '';
+                       }
+               },
 
-                       this.outerdiv.setStyle({
-                                       height: newheight,
-                       width: newwidth
-                });
+               // highlightIng word in autocomplete box by id
+               highlightCurrWord: function(id) {
+                       if (this.currWord != -1) {
+                               $('ac_word_' + this.currWord).className = '';
+                       }
+                       $('ac_word_' + id).className = 'active';
+                       this.currWord = id;
+               },
 
-                       this.linenum_wrap.setStyle({
-                               height: (height - 22)   // less footer height (TODO)
-                       });
+               // insert selected word into text from autocompletebox
+               insertCurrWordAtCursor: function() {
+                       var trigger = this.lastWord;
+                       var insertText = this.words[this.currWord].word;
+                       // if MSIE and select word my mouse click
+                       var cursor = new select.Cursor(this.container);
+                       if (Prototype.Browser.IE && this.clicked) {
+                               if (trigger.length > 0) {
+                                       this.cursorObj.innerHTML = insertText;
+                                       this.win.focus();
+                                       cursor.start = this.cursorObj;
+                                       cursor.focus();
+                                       this.highlightAtCursor(cursor);
+                               }
+                       }
+                       // if Safari browser
+                       else if (Prototype.Browser.WebKit) {
+                               if (trigger.length > 0) {
+                                       this.cursorObj.innerHTML = insertText;
+                                       if (this.clicked) {
+                                               this.win.focus();
+                                       }
+                                       cursor.start = this.cursorObj;
+                                       cursor.focus();
+                                       this.highlightAtCursor(cursor);
+                               }
+                       }
+                       // for all others times
+                       else {
+                               if (trigger.length > 0) {
+                                       cursor.start.innerHTML = '';
+                               }
+                               select.insertTextAtCursor(this.win, insertText);
+                               if (this.clicked) {
+                                       this.win.focus();
+                               }
+                               cursor.focus();
+                               this.highlightAtCursor(cursor);
+                       }
+                       // set ac flag to 0 - autocomplete is finish
+                       this.ac = 0;
+                       // hide box
+                       this.autoCompleteBox.hide();
 
-                       numwwidth = this.linenum_wrap.getWidth();
-                       if (isMSIE)  numwwidth = numwwidth - 17;
-                       if (!isMSIE) numwwidth = numwwidth - 11;        
+               },
+               
+               // return words for autocomplete by trigger (part of word)
+               getCompleteWordsByTrigger: function(trigger) {
+                       result = [];
+
+                       for (word in typoscriptWords) {
+                               lword = word.toLowerCase();
+                               if (lword.indexOf(trigger) === 0) {
+                                       var wordObj = new Object();
+                                       wordObj.word = word;
+                                       wordObj.type = typoscriptWords[word];
+                                       result.push(wordObj);
+                               }
+                       }
+                       return result;
+               },
 
-                       this.iframe.setStyle({
-                   height: (height - 22),      // less footer height (TODO)
-                               width:  (width - numwwidth)
-                       });
+               // move cursor in autcomplete box up
+               autoCompleteBoxMoveUpCursor: function() {
+                       // if previous position was first - then move cursor to last word if not than position --
+                       if (this.currWord == 0) {
+                               var id = this.words.length - 1;
+                       } else {
+                               var id = this.currWord - 1;
+                       }
+                       // hightlight new cursor position
+                       this.highlightCurrWord(id);
+                       // update id of first and last showing words and scroll box
+                       if (this.currWord < this.ac_up || this.currWord == (this.words.length - 1)) {
+                               this.ac_up = this.currWord;
+                               this.ac_down = this.currWord + (this.options.acWords - 1);
+                               if (this.ac_up === this.words.length - 1) {
+                                       this.ac_down = this.words.length - 1;
+                                       this.ac_up = this.ac_down - (this.options.acWords - 1);
+                               }
+                               this.autoCompleteBox.scrollTop = this.ac_up * 16;
+                       }
+               },
+               
+               //move cursor in autocomplete box down
+               autoCompleteBoxMoveDownCursor: function() {
+                       // if previous position was last word in list - then move cursor to first word if not than  position ++
+                       if (this.currWord == this.words.length - 1) {
+                               var id = 0;
+                       } else {
+                               var id = this.currWord + 1;
+                       }
+                       // highlight new cursor position
+                       this.highlightCurrWord(id);
                        
-                       this.modalOverlay.setStyle(this.outerdiv.getDimensions());
-               }
-       },
+                       // update id of first and last showing words and scroll box
+                       if (this.currWord > this.ac_down || this.currWord == 0) {
+                               this.ac_down = this.currWord;
+                               this.ac_up = this.currWord - (this.options.acWords - 1);
+                               if (this.ac_down == 0) {
+                                       this.ac_up = 0;
+                                       this.ac_down = this.options.acWords - 1;
+                               }
+                               this.autoCompleteBox.scrollTop = this.ac_up * 16;
+                       }
+               },
 
-       // toggle between normal view and fullscreen mode
-       toggleFullscreen : function()   {
-               if (this.outerdiv.hasClassName('t3e_fullscreen')) {
-                       // turn fullscreen off
-                       this.outerdiv.removeClassName('t3e_fullscreen');
-                       h = this.textarea.getDimensions().height;
-                       w = this.textarea.getDimensions().width;
-                       
-                       // hide the scrollbar of the body
-                       $$('body')[0].setStyle({overflow : ''});
-                       
-               } else {
-                       // turn fullscreen on
-                       this.outerdiv.addClassName('t3e_fullscreen');
-                       h = window.innerHeight ? window.innerHeight : $$('body')[0].getHeight();
-                       w = window.innerWidth ? window.innerWidth : $$('body')[0].getWidth();
-                       
-                       // TODO: proof if this is needed anymore
-                       w = w - 13;
-                       
-                       // hide the scrollbar of the body
-                       $$('body')[0].setStyle({overflow : 'hidden'});
-               }
+               // update the line numbers
+               updateLinenum: function() {
+                       var theMatch = this.container.innerHTML.match(/<br/gi);
 
-               this.resize(w,h);
-       },
-       
-       toggleHelp: function()  {
-               this.modalOverlay.toggle();
-               this.helpOverlay.toggle();
-       },
+                       if (!theMatch) {
+                               theMatch = [1];
+                       } else if (Prototype.Browser.IE) {
+                               theMatch.push('1');
+                       }
 
-    
-    //toggle AutoCompletation beetwen on and off
-    toggleAutoComplete : function() {
-        this.options.autoComplete = (this.options.autoComplete)?false:true;
-    },
-    
-    //autocomplete box
-    autoComplete : function() {
-        this.clicked = false;
-        //get lastword into this.lastWord
-        this.getLastWord();
-        // init vars for up/down moving in word list
-        this.ac_up = 0;
-        this.ac_down = this.options.acWords-1;
-        
-        //refresh cursorObj
-        var cursor = new select.Cursor(this.container);
-        this.cursorObj = cursor.start;
-        //init currWord, used in word list. Contain selected word
-        this.currWord = -1;
-        
-        // If lastword is not empty and not space - continue
-        if (this.lastWord!='&nbsp;' && this.lastWord){
-            // get list of words
-            this.words = this.getCompleteWordsByTrigger(this.lastWord.toLowerCase());
-            // if words are found - show box
-            if (this.words.length > 0){
-                // make UL list of completation words
-                var html = '<ul>';
-                for (i=0;i<this.words.length;i++){
-                    html+= '<li style="height:16px;vertical-align:middle;" id="ac_word_'+i+'" onclick="t3e_instances['+this.index+'].clicked=true;t3e_instances['+this.index+'].insertCurrWordAtCursor();" onmouseover="t3e_instances['+this.index+'].highlightCurrWord('+i+');"><span class="word_'+this.words[i].type+'">'+this.words[i].word+'</span></li>';
-                }
-                html+='</ul>';
-                //put HTML and show box
-                this.autoCompleteBox.innerHTML = html;
-                this.autoCompleteBox.show();
-                this.autoCompleteBox.scrollTop = 0;
-                //  init styles
-                if (this.words.length > this.options.acWords){
-                    this.autoCompleteBox.style.overflowY = 'scroll';
-                    if (isGecko){
-                        this.autoCompleteBox.style.height = (this.options.acWords*($("ac_word_0").offsetHeight))+'px';
-                    }else{
-                        this.autoCompleteBox.style.height = (this.options.acWords*($("ac_word_0").offsetHeight))+4+'px';
-                        this.autoCompleteBox.style.width = this.autoCompleteBox.offsetWidth+20+'px';
-                    }
-                    
-                }else{
-                    this.autoCompleteBox.style.overflowY = 'auto';
-                    this.autoCompleteBox.style.height = 'auto';
-                    this.autoCompleteBox.style.width = 'auto'; // '0px';
-                }
-                
-                // positioned box to word
-                this.autoCompleteBox.style.left = Position.cumulativeOffset(this.iframe)[0]-Position.cumulativeOffset(this.outerdiv)[0]+Position.cumulativeOffset(cursor.start)[0]+cursor.start.offsetWidth;
-                this.autoCompleteBox.style.top = Position.cumulativeOffset(this.iframe)[1]-Position.cumulativeOffset(this.outerdiv)[1]+Position.cumulativeOffset(cursor.start)[1]+cursor.start.offsetHeight-this.container.scrollTop;
-                // set flag to 1 - needed for continue typing word. 
-                this.ac = 1;    
-                //highlight first word in list
-                this.highlightCurrWord(0);
-            } 
-        }
-    },
-    // Get word where cursor focused
-    getLastWord : function (){
-        var cursor = new select.Cursor(this.container);
-        if (cursor.start){
-            this.lastTrigger = this.lastWord;
-            this.lastWord = (cursor.start.innerHTML)?cursor.start.innerHTML:'';
-        }
-    },
-    
-    // highlighitng word in autocomplete box by id
-    highlightCurrWord : function (id) {
-        if (this.currWord!=-1){
-            $('ac_word_'+this.currWord).className = '';
-        }
-        $('ac_word_'+id).className = 'active';
-        this.currWord = id;
-    },
-    
-    //insert selected word into text from autocompletebox
-    insertCurrWordAtCursor: function (){
-        var trigger = this.lastWord;
-        var insertText = this.words[this.currWord].word;
-        //if MSIE and select word my mouse click
-        var cursor = new select.Cursor(this.container);
-        if (isMSIE && this.clicked){
-            if (trigger.length > 0){
-                this.cursorObj.innerHTML = insertText;
-                this.win.focus();
-                cursor.start = this.cursorObj;
-                cursor.focus();
-                this.highlightAtCursor(cursor);
-            }
-        }
-        // if Safari browser
-        else if (isSafari){
-             if (trigger.length > 0){
-                this.cursorObj.innerHTML = insertText;
-                if (this.clicked){
-                   this.win.focus();
-                }
-                cursor.start = this.cursorObj;
-                cursor.focus();
-                this.highlightAtCursor(cursor);            
-            }
-        }
-        //for all others times
-        else{
-            if (trigger.length > 0){
-                cursor.start.innerHTML = '';
-            }
-            select.insertTextAtCursor (this.win,insertText);
-            if (this.clicked){
-                this.win.focus();    
-            }
-            cursor.focus();
-            this.highlightAtCursor(cursor);
-        }
-        // set ac flag to 0 - autocomplete is finish
-        this.ac = 0;
-        //hide box
-        this.autoCompleteBox.hide();
-    },
-    //return words for autocomplete by trigger (part of word)
-    getCompleteWordsByTrigger : function (trigger){
-        result = [];
-        
-        for(word in typoscriptWords){
-            lword = word.toLowerCase();
-            if (lword.indexOf(trigger) === 0){
-                var wordObj = new Object();
-                wordObj.word = word;
-                wordObj.type = typoscriptWords[word];
-                result.push(wordObj);
-            }
-        }        
-        return result;
-    },
-    
-    //move cursor in autcomplete box up
-    autoCompleteBoxMoveUpCursor : function () {
-        // if previous position was first - then move cursor to last word if not than position --
-        if (this.currWord == 0){
-            var id = this.words.length-1;
-        }else{
-            var id = this.currWord-1;
-        }
-        // hightlight new cursor position
-        this.highlightCurrWord (id);
-        //update id of first and last showing words and scroll box
-        if (this.currWord < this.ac_up || this.currWord == (this.words.length-1)){
-            this.ac_up = this.currWord;
-            this.ac_down = this.currWord+(this.options.acWords-1);
-            if (this.ac_up === this.words.length-1){
-                this.ac_down = this.words.length-1;
-                this.ac_up = this.ac_down-(this.options.acWords-1);
-            }
-            this.autoCompleteBox.scrollTop = this.ac_up*16;
-        }
-    },
-    //move cursor in autocomplete box down
-    autoCompleteBoxMoveDownCursor : function () {
-        // if previous position was last word in list - then move cursor to first word if not than  position ++
-        if (this.currWord == this.words.length-1){
-            var id = 0;
-        }else{
-            var id = this.currWord+1;
-        }
-        // hightlight new cursor position
-        this.highlightCurrWord (id);
-         //update id of first and last showing words and scroll box
-        if (this.currWord > this.ac_down || this.currWord==0){
-            this.ac_down = this.currWord;
-            this.ac_up = this.currWord-(this.options.acWords-1);
-            if (this.ac_down == 0){
-                this.ac_up = 0;
-                this.ac_down = this.options.acWords-1;
-            }
-            this.autoCompleteBox.scrollTop = this.ac_up*16;
-        }
-    },
-    // put code to history
-    pushToHistory:function () {
-        var obj = {};
-        //create SPAN mark of cursor
-        var cursorEl  = this.win.document.createElement("SPAN");
-        cursorEl.id = "cursor";       
-        this.refreshCursorObj();
-        // added mark to code
-        if (this.initable){
-            if (!this.cursorObj){
-                if (this.container.firstChild){
-                   this.win.document.body.insertBefore(cursorEl,this.container.firstChild);
-                }
-            }else{
-                this.win.document.body.insertBefore(cursorEl,this.cursorObj);
-            }
-        }else{
-            this.win.document.body.appendChild(cursorEl);
-        }
-        //save code and text to history object
-        obj.code = this.container.innerHTML;
-       
-       // TODO
-       /// obj.text = this.getCode();
-       
-        // check if was undo/redo than refresh history array
-        if (this.currHistoryPosition+1 < this.history.length){
-            this.history = this.history.slice (0,this.currHistoryPosition+1);
-            this.currHistoryPosition = this.history.length-1;
-        }
-        //push history oject to history array
-        this.history.push(obj);
-        this.currHistoryPosition++;
-        //check limit of history size
-        if (this.currHistoryPosition > this.historySize){
-            this.history = this.history.slice ((this.history.length-this.historySize-1));
-            this.currHistoryPosition = this.history.length-1;
-        }
-    },
-    
-    //undo function
-    undo: function () {
-        //check if position in history not first
-        if (this.currHistoryPosition > 0){
-            this.currHistoryPosition--;
-            var obj = this.history[this.currHistoryPosition];
-            if (!obj){return ;}
-            //insert code from history
-            this.container.innerHTML = obj.code;
-            //focus cursor to next el of marked span
-            var cursor = new select.Cursor(this.container);
-            var cursorEl = this.win.document.getElementById('cursor');
-            if (cursorEl){
-                cursor.start = cursorEl.nextSibling;
-                cursor.focus();
-            }
-        }
-        
-    },
-    
-    //redo function
-    redo: function () {
-        //check if position in history not last
-        if (this.currHistoryPosition < this.history.length){
-            this.currHistoryPosition++;
-            var obj = this.history[this.currHistoryPosition];
-            if (!obj){return ;}
-            //insert code from history
-            this.container.innerHTML = obj.code;
-            //focus cursor to next el of marked span
-            var cursor = new select.Cursor(this.container);
-            var cursorEl = this.win.document.getElementById('cursor');
-            if (cursorEl){
-                cursor.start = cursorEl.nextSibling;
-                cursor.focus();
-            }
-        }
-        
-    },
-    // check changes in history
-    checkHistoryChanges:function () {
-        
-        var code = this.container.innerHTML;
-        if (this.undoable == 1){
-            this.undoable = 0;
-            return ;
-        }
-        if (this.redoable == 1){
-            this.redoable = 0;
-            return ;
-        }
-        if (!this.history[this.currHistoryPosition]){
-            this.pushToHistory();
-            return ;
-        }
-        if (code != this.history[this.currHistoryPosition].code){
-            this.pushToHistory();
-        }
-        
-    },
-
-       // update the line numbers
-    updateLinenum: function()      {
-               var theMatch = this.container.innerHTML.match(/<br/gi);
-        if (!theMatch) {
-            theMatch = '1';
-        } else if (isMSIE) { 
-                       theMatch.push('1');
-               }
+                       var bodyContentLineCount = theMatch.length;
+                       disLineCount = this.linenum.childNodes.length;
+                       while (disLineCount != bodyContentLineCount) {
+                               if (disLineCount > bodyContentLineCount) {
+                                       this.linenum.removeChild(this.linenum.lastChild);
+                                       disLineCount--;
+                               } else if (disLineCount < bodyContentLineCount) {
+                                       ln = $(document.createElement('dt'));
+                                       ln.update(disLineCount + 1 + '.');
+                                       ln.addClassName(disLineCount % 2 == 1 ? 'even': 'odd');
+                                       ln.setAttribute('id', 'ln' + (disLineCount + 1));
+                                       this.linenum.appendChild(ln);
+                                       disLineCount++;
+                               }
+                       }
 
-        var bodyContentLineCount = theMatch.length;
-        disLineCount = this.linenum.childNodes.length;
-        while (disLineCount != bodyContentLineCount)    {
-               if (disLineCount > bodyContentLineCount)        {
-                   this.linenum.removeChild(this.linenum.lastChild);
-                   disLineCount--;
-               } else if (disLineCount < bodyContentLineCount) {
-                   ln = $(document.createElement('dt'));
-                   ln.update(disLineCount+1+'.');
-                   ln.addClassName(disLineCount%2==1?'even':'odd');
-                   ln.setAttribute('id','ln'+(disLineCount+1));
-                   this.linenum.appendChild(ln);
-                   disLineCount++;
-               }
-        }
-
-               this.fitem_status.update(bodyContentLineCount + ' lines');
-               this.fitem_name.update(this.documentname + (this.textModified?' <span alt="document has been modified">*</span>':''));
-    },
-
-       // scroll the line numbers
-    scroll: function()  {
-               var scrOfX = 0, scrOfY = 0;
-               if( typeof( this.win.pageYOffset ) == 'number' ) {
-                   // Netscape compliant
-                   scrOfY = this.win.pageYOffset;
-                   scrOfX = this.win.pageXOffset;
-               } else if( this.doc.body && ( this.doc.body.scrollLeft || this.doc.body.scrollTop ) ) {
-                   // DOM compliant
-                   scrOfY = this.doc.body.scrollTop;
-                   scrOfX = this.doc.body.scrollLeft;
-               } else if( this.doc.documentElement && ( this.doc.documentElement.scrollLeft || this.doc.documentElement.scrollTop ) ) {
-                   // IE6 standards compliant mode
-                   scrOfY = this.doc.documentElement.scrollTop;
-                   scrOfX = this.doc.documentElement.scrollLeft;
-               }
-        this.linenum_wrap.scrollTop = scrOfY;
-    },
-    
-    // click event. Refresh cursor object. if autocomplete is not finish - finish it and hide box
-    click: function()  {
-        if (this.ac === 1){this.ac = 0;this.autoCompleteBox.hide();}
-        this.refreshCursorObj();
-        this.checkBracketAtCursor();
-    },
-
-    // Split a chunk of code into lines, put them in the frame, and
-    // schedule them to be coloured.
-    importCode: function(code) {
-               while ((child = this.container.firstChild)) {
+                       this.fitem_status.update(bodyContentLineCount + ' lines');
+                       this.fitem_name.update(
+                               this.documentname + 
+                               (this.textModified ? ' <span alt="document has been modified">*</span>': ''));
+               },
+
+               // scroll the line numbers
+               scroll: function() {
+                       var scrOfX = 0,
+                       scrOfY = 0;
+                       if (typeof(this.win.pageYOffset) == 'number') {
+                               // Netscape compliant
+                               scrOfY = this.win.pageYOffset;
+                               scrOfX = this.win.pageXOffset;
+                       } else if (this.doc.body && (this.doc.body.scrollLeft || this.doc.body.scrollTop)) {
+                               // DOM compliant
+                               scrOfY = this.doc.body.scrollTop;
+                               scrOfX = this.doc.body.scrollLeft;
+                       } else if (this.doc.documentElement 
+                         && (this.doc.documentElement.scrollLeft 
+                         || this.doc.documentElement.scrollTop)) {
+                               // IE6 standards compliant mode
+                               scrOfY = this.doc.documentElement.scrollTop;
+                               scrOfX = this.doc.documentElement.scrollLeft;
+                       }
+                       this.linenum_wrap.scrollTop = scrOfY;
+               },
+
+               // click event. Refresh cursor object. if autocomplete is not finish - finish it and hide box
+               click: function() {
+                       if (this.ac === 1) {
+                               this.ac = 0;
+                               this.autoCompleteBox.hide();
+                       }
+                       this.refreshCursorObj();
+                       this.checkBracketAtCursor();
+               },
+
+               // Split a chunk of code into lines, put them in the frame, and
+               // schedule them to be coloured.
+               importCode: function(code) {
+                       while ((child = this.container.firstChild)) {
                                this.container.removeChild(child);
                        }
 
-      if (code == "\n" || code == "\r\n" || code == "\r"){code = '';}
-      var lines = code.replace(/[ \t]/g, nbsp).replace(/\r\n?/g, "\n").split("\n");
-
-      for (var i = 0; i != lines.length; i++) {
-        if (i > 0)
-          this.container.appendChild(this.win.document.createElement('BR'));
-        var line = lines[i];
-        if (line.length > 0)
-          this.container.appendChild(this.doc.createTextNode(line));
-      }
-      if (code == "") {
-        var empty = this.win.document.createElement('BR');//(isGecko && !isSafari)?this.win.document.createElement('BR'):this.win.document.createElement('SPAN');
-       this.container.appendChild(empty);
-      }
-
-      if (this.container.firstChild){
-               this.addDirtyNode(this.container.firstChild);
-        this.scheduleHighlight(); // this.highlightDirty();
-      }
-         this.updateLinenum();
-    },
-
-    // Extract the code from the editor.
-    getCode: function() {
-      if (!this.container.firstChild)
-        return "";
-
-      var accum = [];
-      
+                       if (code == "\n" || code == "\r\n" || code == "\r") {
+                               code = '';
+                       }
+                       var lines = code.replace(/[ \t]/g, nbsp).replace(/\r\n?/g, "\n").split("\n");
+
+                       for (var i = 0; i != lines.length; i++) {
+                               if (i > 0) {
+                                       this.container.appendChild(this.win.document.createElement('BR'));
+                               }
+                               var line = lines[i];
+                               if (line.length > 0) {
+                                       this.container.appendChild(this.doc.createTextNode(line));
+                               }
+                       }
+                       if (i > 0) {
+                               this.container.appendChild(this.win.document.createElement('BR'));
+                       }
+                       if (code == "") {
+                               this.container.appendChild(this.win.document.createElement('SPAN'));
+                               this.container.appendChild(
+                                       (Prototype.Browser.Gecko && !Prototype.Browser.WebKit) ? 
+                                        this.win.document.createElement('BR') : 
+                                        this.win.document.createElement('SPAN'));
+                       }
+
+                       if (this.container.firstChild) {
+                               var cursor = new select.Cursor(this.container);
+                               cursor.start = (this.container.firstChild);
+                               cursor.focus();
+                               this.addDirtyNode(this.container.firstChild);
+                               this.highlightDirty();
+                       }
+                       this.updateLinenum();
+               },
+
+               // Extract the code from the editor.
+               getCode: function() {
+                       if (!this.container.firstChild) {
+                               return "";
+                       }
+                       var accum = [];
+
                        tdom = traverseDOM(this.container.firstChild);
-                       try     {
+                       try {
                                while (tmp = tdom.next()) {
                                        accum.push(tmp);
                                }
-                       } catch(e)      {
-                               if (e != StopIteration) throw e;
+                       } catch(e) {
+                               if (e != StopIteration) throw e;
                        }
-      return accum.join("").replace(nbspRegexp, " ");
-    },
-
-    // Intercept enter and any keys that are specified to re-indent
-    // the current line.
-    keyDown: function(event) {
-      var keycode = event.keyCode;
-      if (keycode == Event.KEY_RETURN) {
-            event.stop();
-                       if (this.ac === 1)      {
-               this.insertCurrWordAtCursor();
-            } else if (!isMac) {
-                select.insertNewlineAtCursor(this.win);
-                   this.indentAtCursor();
-            }
-            this.updateLinenum();
-                       
-         } else if (keycode == 83      && event.ctrlKey) {     // CTRL-S   save via ajax request
-               this.saveAjax();
-               event.stop();
-               return;
-                       
-      } else if (keycode == 122        && event.ctrlKey)       {       // CTRL-F11 toogle fullscreen mode
-               this.toggleFullscreen();
-               event.stop();
-               return;
-                       
-                       // TODO
-      } else if (keycode == 32 && event.ctrlKey && this.options.autoComplete){ // CTRL-Space  call autocomplete if autocomplete turn on
-        this.autoComplete();
-        event.stop();
-      } else if (keycode == 38 && this.ac == 1){ // arrow up:  move up cursor in autocomplete box
-        event.stop();
-        window.setTimeout('t3e_instances['+this.index+'].autoCompleteBoxMoveUpCursor()',100);
-      } else if (keycode == 40 && this.ac == 1){ // Arrow down: move down cursor in autocomplete box
-        event.stop();
-        window.setTimeout('t3e_instances['+this.index+'].autoCompleteBoxMoveDownCursor();',100);
-      } else if (keycode == 27 && this.ac === 1){ // Esc: if autocomplete box is showing. by ESC press it's hide and autocomplete is finish
-            this.ac = 0;
-            this.autoCompleteBox.hide();
-      } else if (keycode == 90 && event.ctrlKey){
-         this.undoable = 1;
-         this.undo();
-         event.stop();
-      } else if (keycode == 89 && event.ctrlKey){
-         this.redoable = 1;
-         this.redo();
-         event.stop();
-      }
-    },
-
-    // Re-indent when a key in options.reindentAfterKeys is released,
-    // mark the node at the cursor dirty when a non-safe key is
-    // released.
-    keyUp: function(event) {
-      // var name = event.key().string;
-      var keycode = event.keyCode;
-      
-      // TODO
-      /*
-      if (this.options.reindentAfterKeys.hasOwnProperty(name))
-        this.indentAtCursor();
-      else */ 
-      // TODO 
-      if (
-               keycode != 37 
-                       && keycode != 38 
-                       && keycode != 39
-                       && keycode != 40 
-                       && keycode != 35 
-                       && keycode != 36
-                       && keycode != 33
-                       && keycode != 34 
-                       && keycode != 16 
-                       && keycode != 17 
-                       && keycode != 18 
-                       && !event.ctrlKey) {
-        this.markCursorDirty();
-        this.checkTextModified();
-        window.setTimeout('t3e_instances['+this.index+'].checkHistoryChanges();',100);
-      }
-         
-       if (this.ac===1){ // if autocomplete now is not finish, but started and continue typing - refresh autocomplete box
-            this.getLastWord();
-            if (this.lastTrigger!=this.lastWord){
-                this.autoCompleteBox.hide();
-                this.ac = 0;
-                this.autoComplete();     
-            }
-       } 
-      
-      if (keycode == Event.KEY_RETURN
-                        || keycode == Event.KEY_BACKSPACE
-                        || keycode == Event.KEY_DELETE )       {
-          this.updateLinenum();
-      }
-       
-      this.refreshCursorObj();
-      this.checkBracketAtCursor();
-    },
-       
-    refreshCursorObj: function () {
-        var cursor = new select.Cursor(this.container);
-        this.cursorObj = cursor.start;
-    },
-
-
-       // check if code in editor has been modified since last saving
-    checkTextModified: function() {
-         if (!this.textModified) {
-       this.textModified = true;
-               this.updateLinenum();
-      }
-    },
-
-
-       // send ajax request to save the code
-       saveAjax: function(event) {
-               if (event) {
-                       // event = new Event(event);
-                       Event.stop(event);
-               }
-               
-               this.modalOverlay.show();
-               this.textarea.value = this.getCode();
-               
-               /* erst ab prototype 1.5.1
-               Form.request($(this.textarea.form),{
-                       onComplete: function(){ alert('Form data saved!'); }
-               });
-               */
+                       return accum.join("").replace(nbspRegexp, " ");
+               },
+
+               // Intercept enter and any keys that are specified to re-indent
+               // the current line.
+               keyDown: function(event) {
+                       var keycode = event.keyCode;
+                       if (keycode == Event.KEY_RETURN) {
+                               event.stop();
+                               if (this.ac === 1) {
+                                       this.insertCurrWordAtCursor();
+                               } else if (! (navigator.userAgent.indexOf('Mac') != -1)) {      // isMac
+                                       select.insertNewlineAtCursor(this.win);
+                                       this.indentAtCursor();
+                               }
+                               this.updateLinenum();
+
+                       } else if (keycode == 83 && event.ctrlKey) {
+                               // CTRL-S   save via ajax request
+                               this.saveAjax();
+                               event.stop();
+                               return;
+
+                       } else if (keycode == 122 && event.ctrlKey) {
+                               // CTRL-F11 toogle fullscreen mode
+                               this.toggleFullscreen();
+                               event.stop();
+                               return;
+
+                       } else if (keycode == 32 && event.ctrlKey && this.options.autoComplete) {
+                               // CTRL-Space  call autocomplete if autocomplete turn on
+                               this.autoComplete();
+                               event.stop();
+
+                       } else if (keycode == 38 && this.ac == 1) {
+                               // arrow up:  move up cursor in autocomplete box
+                               event.stop();
+                               window.setTimeout('t3e_instances[' + this.index + '].autoCompleteBoxMoveUpCursor()', 100);
+
+                       } else if (keycode == 40 && this.ac == 1) {
+                               // Arrow down: move down cursor in autocomplete box
+                               event.stop();
+                               window.setTimeout('t3e_instances[' + this.index + '].autoCompleteBoxMoveDownCursor();', 100);
+
+                       } else if (keycode == 27 && this.ac === 1) {
+                               // Esc: if autocomplete box is showing. by ESC press it's hide and autocomplete is finish
+                               this.ac = 0;
+                               this.autoCompleteBox.hide();
+
+                       }
+               },
                
-               formdata = "submitAjax=1&" + Form.serialize($(this.textarea.form));
+               // mark the node at the cursor dirty when a non-safe key is
+               // released.
+               keyUp: function(event) {
+                       var keycode = event.keyCode;
+
+                       if (
+                               keycode != 37
+                               && keycode != 38
+                               && keycode != 39
+                               && keycode != 40
+                               && keycode != 35
+                               && keycode != 36
+                               && keycode != 33
+                               && keycode != 34
+                               && keycode != 16
+                               && keycode != 17
+                               && keycode != 18
+                               && !event.ctrlKey) {
+                               this.markCursorDirty();
+                               this.checkTextModified();
+                       }
+
+                       if (this.ac === 1) {
+                               // if autocomplete now is not finish, but started and continue typing - refresh autocomplete box
+                               this.getLastWord();
+                               if (this.lastTrigger != this.lastWord) {
+                                       this.autoCompleteBox.hide();
+                                       this.ac = 0;
+                                       this.autoComplete();
+                               }
+                       }
+
+                       if (keycode == Event.KEY_RETURN
+                         || keycode == Event.KEY_BACKSPACE
+                         || keycode == Event.KEY_DELETE) {
+                               this.updateLinenum();
+                       }
+
+                       this.refreshCursorObj();
+                       this.checkBracketAtCursor();
+               },
 
-               var myAjax = new Ajax.Request(
-                       $(this.textarea.form).action, 
-                       { method: "post",
-                         parameters: formdata, 
-                         onComplete: this.saveAjaxOnSuccess.bind(this)
+               refreshCursorObj: function() {
+                       var cursor = new select.Cursor(this.container);
+                       this.cursorObj = cursor.start;
+               },
+
+               // check if code in editor has been modified since last saving
+               checkTextModified: function() {
+                       if (!this.textModified) {
+                               this.textModified = true;
+                               this.updateLinenum();
+                       }
+               },
+
+               // send ajax request to save the code
+               saveAjax: function(event) {
+                       if (event) {
+                               Event.stop(event);
+                       }
+
+                       this.modalOverlay.show();
+                       this.textarea.value = this.getCode();
+                       $('submitAjax').value = '1';
+                       Form.request($(this.textarea.form), {
+                               onComplete: this.saveAjaxOnSuccess.bind(this)
                        });
-       },
+               },
 
-       // callback if ajax saving was successful
-       saveAjaxOnSuccess: function(ajaxrequest) {
-               if (ajaxrequest.status == 200
-                       && ajaxrequest.responseText == "OK") {
-                       this.textModified = false;
-                       this.updateLinenum();
-               } else {
-                       // TODO: handle if session is timed out
-                       alert("An error occured while saving the data.");
-               };
-               this.modalOverlay.hide();
-               
-       },
+               // callback if ajax saving was successful
+               saveAjaxOnSuccess: function(ajaxrequest) {
+                       if (ajaxrequest.status == 200
+                         && ajaxrequest.responseText == "OK") {
+                               this.textModified = false;
+                               this.updateLinenum();
+                       } else {
+                               alert("An error occured while saving the data.");
+                       };
+                       $('submitAjax').value = '0';
+                       this.modalOverlay.hide();
+               },
 
 
-    // Ensure that the start of the line the cursor is on is parsed
-    // and coloured properly, so that the correct indentation can be
-    // computed.
-    highlightAtCursor: function(cursor) {
-      if (cursor.valid) {
-        var node = cursor.start || this.container.firstChild;
-        if (node) {
-         // If the node is a text node, it will be recognized as
-         // dirty anyway, and some browsers do not allow us to add
-         // properties to text nodes.
-          if (node.nodeType != 3)
-            node.dirty = true;
-         // Store selection, highlight, restore selection.
-          var sel = select.markSelection(this.win);
-          this.highlight(node);
-          select.selectMarked(sel);
-         // Cursor information is probably no longer valid after
-         // highlighting.
-          cursor = new select.Cursor(this.container);
-        }
-      }
-      return cursor;
-    },
-
-       checkBracketAtCursor: function()        {
-               var cursor = new select.Cursor(this.container);
-        this.cursorObj = cursor.start;
-        
-               // remove current highlights
-               Selector.findChildElements(this.doc,$A(['.highlight-bracket','.error-bracket'])).each(function(item) {
-                       item.className = item.className.replace(' highlight-bracket','');
-                       item.className = item.className.replace(' error-bracket','');
-               });
-               
-               if (!cursor.start || !cursor.start.className) return;
-               
-               // if cursor is behint an bracket, we search for the matching one
-               
-               // we have an opening bracket, search forward for a closing bracket
-               if (cursor.start.className.indexOf('curly-bracket-open') != -1) {
-                       var maybeMatch = cursor.start.nextSibling;
-                       var skip = 0;
-                       while(maybeMatch) {
-                               if (maybeMatch.className.indexOf('curly-bracket-open') != -1) {
-                                       skip++;
+               // Ensure that the start of the line the cursor is on is parsed
+               // and coloured properly, so that the correct indentation can be
+               // computed.
+               highlightAtCursor: function(cursor) {
+                       if (cursor.valid) {
+                               var node = cursor.start || this.container.firstChild;
+                               if (node) {
+                                       // If the node is a text node, it will be recognized as
+                                       // dirty anyway, and some browsers do not allow us to add
+                                       // properties to text nodes.
+                                       if (node.nodeType != 3) {
+                                               node.dirty = true;
+                                       }
+                                       // Store selection, highlight, restore selection.
+                                       var sel = select.markSelection(this.win);
+                                       this.highlight(node);
+                                       select.selectMarked(sel);
+                                       // Cursor information is probably no longer valid after
+                                       // highlighting.
+                                       cursor = new select.Cursor(this.container);
                                }
-                               if (maybeMatch.className.indexOf('curly-bracket-close') != -1) {
-                                       if (skip > 0) {
-                                               skip--;
-                                       } else {
-                                               maybeMatch.className += ' highlight-bracket';
-                                               cursor.start.className += ' highlight-bracket';
-                                               break;
+                       }
+                       return cursor;
+               },
+
+               checkBracketAtCursor: function() {
+                       var cursor = new select.Cursor(this.container);
+                       this.cursorObj = cursor.start;
+
+                       // remove current highlights
+                       Selector.findChildElements(this.doc, 
+                               $A(['.highlight-bracket', '.error-bracket'])
+                       ).each(function(item) {
+                               item.className = item.className.replace(' highlight-bracket', '');
+                               item.className = item.className.replace(' error-bracket', '');
+                       });
+
+                       if (!cursor.start || !cursor.start.className) {
+                               return;
+                       }
+
+                       // if cursor is behind an bracket, we search for the matching one
+
+                       // we have an opening bracket, search forward for a closing bracket
+                       if (cursor.start.className.indexOf('curly-bracket-open') != -1) {
+                               var maybeMatch = cursor.start.nextSibling;
+                               var skip = 0;
+                               while (maybeMatch) {
+                                       if (maybeMatch.className.indexOf('curly-bracket-open') != -1) {
+                                               skip++;
+                                       }
+                                       if (maybeMatch.className.indexOf('curly-bracket-close') != -1) {
+                                               if (skip > 0) {
+                                                       skip--;
+                                               } else {
+                                                       maybeMatch.className += ' highlight-bracket';
+                                                       cursor.start.className += ' highlight-bracket';
+                                                       break;
+                                               }
                                        }
+                                       maybeMatch = maybeMatch.nextSibling;
                                }
-                               maybeMatch = maybeMatch.nextSibling;
                        }
-               }
-               // we have a closing bracket, search backward for an opening bracket
-               if (cursor.start.className.indexOf('curly-bracket-close') != -1) {
-                       var maybeMatch = cursor.start.previousSibling;
-                       var skip = 0;
-                       while(maybeMatch) {
-                               if (maybeMatch.className.indexOf('curly-bracket-close') != -1) {
-                                       skip++;
+                       
+                       // we have a closing bracket, search backward for an opening bracket
+                       if (cursor.start.className.indexOf('curly-bracket-close') != -1) {
+                               var maybeMatch = cursor.start.previousSibling;
+                               var skip = 0;
+                               while (maybeMatch) {
+                                       if (maybeMatch.className.indexOf('curly-bracket-close') != -1) {
+                                               skip++;
+                                       }
+                                       if (maybeMatch.className.indexOf('curly-bracket-open') != -1) {
+                                               if (skip > 0) {
+                                                       skip--;
+                                               } else {
+                                                       maybeMatch.className += ' highlight-bracket';
+                                                       cursor.start.className += ' highlight-bracket';
+                                                       break;
+                                               }
+                                       }
+                                       maybeMatch = maybeMatch.previousSibling;
                                }
-                               if (maybeMatch.className.indexOf('curly-bracket-open') != -1) {
-                                       if (skip > 0) {
-                                               skip--;
+                       }
+
+                       if (cursor.start.className.indexOf('curly-bracket-') != -1
+                         && maybeMatch == null) {
+                               cursor.start.className += ' error-bracket';
+                       }
+               },
+
+               autoCloseBracket: function(prevNode) {
+                       if (prevNode && prevNode.className.indexOf('curly-bracket-open') != -1) {
+                               select.insertNodeAtCursor(this.win, new Element('BR'));
+                               select.insertTextAtCursor(this.win, "}");
+                       }
+               },
+
+               // Adjust the amount of whitespace at the start of the line that
+               // the cursor is on so that it is indented properly.
+               indentAtCursor: function() {
+                       var cursor = new select.Cursor(this.container);
+
+                       // The line has to have up-to-date lexical information, so we
+                       // highlight it first.
+                       cursor = this.highlightAtCursor(cursor);
+                       // If we couldn't determine the place of the cursor, there's
+                       // nothing to indent.
+                       if (!cursor.valid) {
+                               return;
+                       }
+
+                       // start is the <br> before the current line, or null if this is
+                       // the first line.
+                       var start = cursor.startOfLine();
+                       this.autoCloseBracket(start.previousSibling);
+
+                       // whiteSpace is the whitespace span at the start of the line,
+                       // or null if there is no such node.
+                       var whiteSpace = start ? start.nextSibling: this.container.lastChild;
+                       if (whiteSpace && !hasClass(whiteSpace, "whitespace")) {
+                               whiteSpace = null;
+                       }
+
+                       // Sometimes the first character on a line can influence the
+                       // correct indentation, so we retrieve it.
+                       var firstText = whiteSpace ? 
+                                         whiteSpace.nextSibling : 
+                                         start ? 
+                                           start.nextSibling : 
+                                           this.container.firstChild;
+                       var firstChar = (start && firstText && firstText.currentText) ? 
+                                       firstText.currentText.charAt(0) : 
+                                       "";
+
+                       // Ask the lexical context for the correct indentation, and
+                       // compute how much this differs from the current indentation.
+                       var indent = start ? start.lexicalContext.indentation(firstChar) : 0;
+                       var indentDiff = indent - (whiteSpace ? whiteSpace.currentText.length: 0);
+
+                       // If there is too much, this is just a matter of shrinking a span.
+                       if (indentDiff < 0) {
+                               whiteSpace.currentText = repeatString(nbsp, indent);
+                               whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
+                       }
+                       // Not enough...
+                       else if (indentDiff > 0) {
+                               // If there is whitespace, we grow it.
+                               if (whiteSpace) {
+                                       whiteSpace.currentText += repeatString(nbsp, indentDiff);
+                                       whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
+                               }
+                               // Otherwise, we have to add a new whitespace node.
+                               else {
+                                       whiteSpace = new Element('SPAN', {
+                                               "class": "whitespace part"
+                                       });
+                                       whiteSpace.innerHTML = repeatString(nbsp, indentDiff);
+                                       if (start) {
+                                               insertAfter(whiteSpace, start);
                                        } else {
-                                               maybeMatch.className += ' highlight-bracket';
-                                               cursor.start.className += ' highlight-bracket';
-                                               break;
+                                               insertAtStart(whiteSpace, this.container);
                                        }
                                }
-                               maybeMatch = maybeMatch.previousSibling;
+                               // If the cursor is at the start of the line, move it to after
+                               // the whitespace.
+                               if (cursor.start == start) {
+                                       cursor.start = whiteSpace;
+                               }
+                       }
+
+                       if (cursor.start == whiteSpace) {
+                               cursor.focus();
+                       }
+               },
+
+               // highlight is a huge function defined below.
+               highlight: highlight,
+
+               // Find the node that the cursor is in, mark it as dirty, and make
+               // sure a highlight pass is scheduled.
+               markCursorDirty: function() {
+                       var cursor = new select.Cursor(this.container);
+                       if (cursor.valid) {
+                               var node = cursor.start || this.container.firstChild;
+                               if (node) {
+                                       this.addDirtyNode(node);
+                                       this.scheduleHighlight();
+                               }
                        }
+               },
+
+               // Add a node to the set of dirty nodes, if it isn't already in
+               // there.
+               addDirtyNode: function(node) {
+                       if (this.dirty.indexOf(node) == -1) {
+                               if (node.nodeType != 3) {
+                                       node.dirty = true;
+                               }
+                               this.dirty.push(node);
+                       }
+               },
+
+               // Cause a highlight pass to happen in options.passDelay
+               // milliseconds. Clear the existing timeout, if one exists. This
+               // way, the passes do not happen while the user is typing, and
+               // should as unobtrusive as possible.
+               scheduleHighlight: function() {
+                       if (this.highlightTimeout) {
+                               clearTimeout(this.highlightTimeout);
+                       }
+                       this.highlightTimeout = setTimeout(this.highlightDirty.bind(this), this.options.passDelay);
+               },
+
+               // Fetch one dirty node, and remove it from the dirty set.
+               getDirtyNode: function() {
+                       while (this.dirty.length > 0) {
+                               var found = this.dirty.pop();
+                               // If the node has been coloured in the meantime, or is no
+                               // longer in the document, it should not be returned.
+                               if ((found.dirty || found.nodeType == 3) && found.parentNode) {
+                                       return found;
+                               }
+                       }
+                       return null;
+               },
+
+               // Pick dirty nodes, and highlight them, until
+               // options.linesPerPass lines have been highlighted. The highlight
+               // method will continue to next lines as long as it finds dirty
+               // nodes. It returns an object indicating the amount of lines
+               // left, and information about the place where it stopped. If
+               // there are dirty nodes left after this function has spent all
+               // its lines, it shedules another highlight to finish the job.
+               highlightDirty: function() {
+                       var lines = this.options.linesPerPass;
+                       var sel = select.markSelection(this.win);
+                       var start;
+                       while (lines > 0 && (start = this.getDirtyNode())) {
+                               var result = this.highlight(start, lines);
+                               if (result) {
+                                       lines = result.left;
+                                       if (result.node && result.dirty) {
+                                               this.addDirtyNode(result.node);
+                                       }
+                               }
+                       }
+                       select.selectMarked(sel);
+                       if (start) {
+                               this.scheduleHighlight();
+                       }
+
+                       this.checkBracketAtCursor();
+               }
+       } // t3editor.prototype
+
+       // The function that does the actual highlighting/colouring (with
+       // help from the parser and the DOM normalizer). Its interface is
+       // rather overcomplicated, because it is used in different
+       // situations: ensuring that a certain line is highlighted, or
+       // highlighting up to X lines starting from a certain point. The
+       // 'from' argument gives the node at which it should start. If this
+       // is null, it will start at the beginning of the frame. When a
+       // number of lines is given with the 'lines' argument, it will colour
+       // no more than that amount. If at any time it comes across a
+       // 'clean' line (no dirty nodes), it will stop.
+       function highlight(from, lines) {
+               var container = this.container;
+               var document = this.doc;
+
+               if (!container.firstChild) {
+                       return;
                }
                
-               if (cursor.start.className.indexOf('curly-bracket-') != -1
-                     && maybeMatch == null) {
-                       cursor.start.className += ' error-bracket';
+               // Backtrack to the first node before from that has a partial
+               // parse stored.
+               while (from && !from.parserFromHere) {
+                       from = from.previousSibling;
                }
                
-       },
-       
-       autoCloseBracket: function(prevNode) {
-      if (prevNode && prevNode.className.indexOf('curly-bracket-open') != -1) {
-               select.insertNodeAtCursor(this.win, new Element('BR'));
-               select.insertTextAtCursor(this.win, "}");
-      }
-       },
-       
-    // Adjust the amount of whitespace at the start of the line that
-    // the cursor is on so that it is indented properly.
-    indentAtCursor: function() {
-      var cursor = new select.Cursor(this.container);
-      
-      // The line has to have up-to-date lexical information, so we
-      // highlight it first.
-      cursor = this.highlightAtCursor(cursor);
-      // If we couldn't determine the place of the cursor, there's
-      // nothing to indent.
-      if (!cursor.valid)
-        return;
-
-      // start is the <br> before the current line, or null if this is
-      // the first line.
-      var start = cursor.startOfLine();
-      
-      this.autoCloseBracket(start.previousSibling);
-      
-      // whiteSpace is the whitespace span at the start of the line,
-      // or null if there is no such node.
-      var whiteSpace = start ? start.nextSibling : this.container.lastChild;
-      if (whiteSpace && !hasClass(whiteSpace, "whitespace"))
-        whiteSpace = null;
-
-      // Sometimes the first character on a line can influence the
-      // correct indentation, so we retrieve it.
-      var firstText = whiteSpace ? whiteSpace.nextSibling : start ? start.nextSibling : this.container.firstChild;
-      var firstChar = (start && firstText && firstText.currentText) ? firstText.currentText.charAt(0) : "";
-
-      // Ask the lexical context for the correct indentation, and
-      // compute how much this differs from the current indentation.
-     
-         var indent = start ? start.lexicalContext.indentation(firstChar) : 0;
-      var indentDiff = indent - (whiteSpace ? whiteSpace.currentText.length : 0);
-
-      // If there is too much, this is just a matter of shrinking a span.
-      if (indentDiff < 0) {
-        whiteSpace.currentText = repeatString(nbsp, indent);
-        whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
-      }
-      // Not enough...
-      else if (indentDiff > 0) {
-       // If there is whitespace, we grow it.
-        if (whiteSpace) {
-          whiteSpace.currentText += repeatString(nbsp, indentDiff);
-          whiteSpace.firstChild.nodeValue = whiteSpace.currentText;
-        }
-       // Otherwise, we have to add a new whitespace node.
-        else {
-             whiteSpace = new Element('SPAN',{"class": "whitespace part"});
-                       whiteSpace.innerHTML = repeatString(nbsp, indentDiff);
-          if (start)
-            insertAfter(whiteSpace, start);
-          else
-            insertAtStart(whiteSpace, this.containter);
-        }
-       // If the cursor is at the start of the line, move it to after
-       // the whitespace.
-        if (cursor.start == start)
-          cursor.start = whiteSpace;
-      }
-         
-         if (cursor.start == whiteSpace)
-        cursor.focus();
-    },
-
-    // highlight is a huge function defined below.
-    highlight: highlight,
-
-    // Find the node that the cursor is in, mark it as dirty, and make
-    // sure a highlight pass is scheduled.
-    markCursorDirty: function() {
-      var cursor = new select.Cursor(this.container);
-      if (cursor.valid) {
-        var node = cursor.start || this.container.firstChild;
-        if (node) {
-          this.addDirtyNode(node);
-                 this.scheduleHighlight();
-        }
-      }
-    },
-
-    // Add a node to the set of dirty nodes, if it isn't already in
-    // there.
-    addDirtyNode: function(node) {
-      if (this.dirty.indexOf(node) == -1) {
-        if (node.nodeType != 3)
-          node.dirty = true;
-        this.dirty.push(node);
-      }
-    },
-
-    // Cause a highlight pass to happen in options.passDelay
-    // milliseconds. Clear the existing timeout, if one exists. This
-    // way, the passes do not happen while the user is typing, and
-    // should as unobtrusive as possible.
-    scheduleHighlight: function() {
-         if (this.highlightTimeout) clearTimeout(this.highlightTimeout);
-         this.highlightTimeout = setTimeout(this.highlightDirty.bind(this), this.options.passDelay);
-         
-    },
-
-    // Fetch one dirty node, and remove it from the dirty set.
-    getDirtyNode: function() {
-      while (this.dirty.length > 0) {
-        var found = this.dirty.pop();
-       // If the node has been coloured in the meantime, or is no
-       // longer in the document, it should not be returned.
-        if ((found.dirty || found.nodeType == 3) && found.parentNode)
-          return found;
-      }
-      return null;
-    },
-
-    // Pick dirty nodes, and highlight them, until
-    // options.linesPerPass lines have been highlighted. The highlight
-    // method will continue to next lines as long as it finds dirty
-    // nodes. It returns an object indicating the amount of lines
-    // left, and information about the place where it stopped. If
-    // there are dirty nodes left after this function has spent all
-    // its lines, it shedules another highlight to finish the job.
-    highlightDirty: function() {
-         var lines = this.options.linesPerPass;
-      var sel = select.markSelection(this.win);
-      var start;
-      while (lines > 0 && (start = this.getDirtyNode())){
-        var result = this.highlight(start, lines);
-        if (result) {
-          lines = result.left;
-          if (result.node && result.dirty)
-            this.addDirtyNode(result.node);
-        }
-      }
-      select.selectMarked(sel);
-         if (start)
-        this.scheduleHighlight();
-      
-      this.checkBracketAtCursor();
-    }
-  }
-
-  // The function that does the actual highlighting/colouring (with
-  // help from the parser and the DOM normalizer). Its interface is
-  // rather overcomplicated, because it is used in different
-  // situations: ensuring that a certain line is highlighted, or
-  // highlighting up to X lines starting from a certain point. The
-  // 'from' argument gives the node at which it should start. If this
-  // is null, it will start at the beginning of the frame. When a
-  // number of lines is given with the 'lines' argument, it will colour
-  // no more than that amount. If at any time it comes across a
-  // 'clean' line (no dirty nodes), it will stop.
-  function highlight(from, lines){
-    var container = this.container;
-    var document = this.doc;
-//     this.updateLinenum();
-
-    if (!container.firstChild)
-      return;
-    // Backtrack to the first node before from that has a partial
-    // parse stored.
-    while (from && !from.parserFromHere)
-      from = from.previousSibling;
-    // If we are at the end of the document, do nothing.
-    if (from && !from.nextSibling)
-      return;
-
-    // Check whether a part (<span> node) and the corresponding token
-    // match.
-    function correctPart(token, part){
-      return !part.reduced && part.currentText == token.value && hasClass(part, token.style);
-    }
-    // Shorten the text associated with a part by chopping off
-    // characters from the front. Note that only the currentText
-    // property gets changed. For efficiency reasons, we leave the
-    // nodeValue alone -- we set the reduced flag to indicate that
-    // this part must be replaced.
-    function shortenPart(part, minus){
-      part.currentText = part.currentText.substring(minus);
-      part.reduced = true;
-    }
-    // Create a part corresponding to a given token.
-    function tokenPart(token){
-      var part = new Element('SPAN',{"class": "part " + token.style});
-               part.update(token.value);
-               part.currentText = token.value;
-               part.innerHTML = token.value;
-      return part;
-    }
-
-    // Get the token stream. If from is null, we start with a new
-    // parser from the start of the frame, otherwise a partial parse
-    // is resumed.
-    var parsed = from ? from.parserFromHere(multiStringStream(traverseDOM(from.nextSibling)))
-      : this.options.parser(multiStringStream(traverseDOM(container.firstChild)));
-
-    // parts is a wrapper that makes it possible to 'delay' going to
-    // the next DOM node until we are completely done with the one
-    // before it. This is necessary because we are constantly poking
-    // around in the DOM tree, and if the next node is fetched to
-    // early it might get replaced before it is used.
-    var parts = {
-      current: null,
-      forward: false,
-      // Get the current part.
-      get: function(){
-        if (!this.current)
-          this.current = from ? from.nextSibling : container.firstChild;
-        else if (this.forward)
-          this.current = this.current.nextSibling;
-        this.forward = false;
-        return this.current;
-      },
-      // Advance to the next part (do not fetch it yet).
-      next: function(){
-        if (this.forward)
-          this.get();
-        this.forward = true;
-      },
-      // Remove the current part from the DOM tree, and move to the
-      // next.
-      remove: function(){
-        this.current = this.get().previousSibling;
-        container.removeChild(this.current ? this.current.nextSibling : container.firstChild);
-        this.forward = true;
-      },
-      // Advance to the next part that is not empty, discarding empty
-      // parts.
-      nextNonEmpty: function(){
-        var part = this.get();
-        while (part.nodeName == "SPAN" && part.currentText == ""){
-          var old = part;
-          this.remove();
-          part = this.get();
-         // Adjust selection information, if any. See select.js for
-         // details.
-          select.replaceSelection(old.firstChild, part.firstChild || part, 0, 0);
-        }
-        return part;
-      }
-    };
-
-    var lineDirty = false;
-
-    // This forEach loops over the tokens from the parsed stream, and
-    // at the same time uses the parts object to proceed through the
-    // corresponding DOM nodes.
-               try     {
-                       while (true)    { // stopped by StopIteration
+               // If we are at the end of the document, do nothing.
+               if (from && !from.nextSibling) {
+                       return;
+               }
+               
+               // Check whether a part (<span> node) and the corresponding token
+               // match.
+               function correctPart(token, part) {
+                       return ! part.reduced 
+                               && part.currentText == token.value 
+                               && hasClass(part, token.style);
+               }
+               // Shorten the text associated with a part by chopping off
+               // characters from the front. Note that only the currentText
+               // property gets changed. For efficiency reasons, we leave the
+               // nodeValue alone -- we set the reduced flag to indicate that
+               // this part must be replaced.
+               function shortenPart(part, minus) {
+                       part.currentText = part.currentText.substring(minus);
+                       part.reduced = true;
+               }
+               
+               // Create a part corresponding to a given token.
+               function tokenPart(token) {
+                       var part = new Element('SPAN', {
+                               "class": "part " + token.style
+                       });
+                       part.update(token.value);
+                       part.currentText = token.value;
+                       part.innerHTML = token.value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+                       return part;
+               }
+
+               // Get the token stream. If from is null, we start with a new
+               // parser from the start of the frame, otherwise a partial parse
+               // is resumed.
+               var parsed = from ? 
+                       from.parserFromHere(multiStringStream(traverseDOM(from.nextSibling))) : 
+                       this.options.parser(multiStringStream(traverseDOM(container.firstChild)));
+
+               // parts is a wrapper that makes it possible to 'delay' going to
+               // the next DOM node until we are completely done with the one
+               // before it. This is necessary because we are constantly poking
+               // around in the DOM tree, and if the next node is fetched to
+               // early it might get replaced before it is used.
+               var parts = {
+                       current: null,
+                       forward: false,
+                       
+                       // Get the current part.
+                       get: function() {
+                               if (!this.current) {
+                                       this.current = from ? from.nextSibling: container.firstChild;
+                               } else if (this.forward) {
+                                       this.current = this.current.nextSibling;
+                               }
+                               this.forward = false;
+                               return this.current;
+                       },
+                       
+                       // Advance to the next part (do not fetch it yet).
+                       next: function() {
+                               if (this.forward) {
+                                       this.get();
+                               }
+                               this.forward = true;
+                       },
+                       
+                       // Remove the current part from the DOM tree, and move to the
+                       // next.
+                       remove: function() {
+                               this.current = this.get().previousSibling;
+                               container.removeChild(this.current ? this.current.nextSibling: container.firstChild);
+                               this.forward = true;
+                       },
+                       
+                       // Advance to the next part that is not empty, discarding empty
+                       // parts.
+                       nextNonEmpty: function() {
+                               var part = this.get();
+                               while (part.nodeName == "SPAN" && part.currentText == "") {
+                                       var old = part;
+                                       this.remove();
+                                       part = this.get();
+                                       // Adjust selection information, if any. See select.js for
+                                       // details.
+                                       select.replaceSelection(old.firstChild, part.firstChild || part, 0, 0);
+                               }
+                               return part;
+                       }
+               }; // var parts
+
+               var lineDirty = false;
+
+               // This forEach loops over the tokens from the parsed stream, and
+               // at the same time uses the parts object to proceed through the
+               // corresponding DOM nodes.
+               try {
+                       while (true) {
+                               // stopped by StopIteration
+                               
                                token = parsed.next();
-      var part = parts.nextNonEmpty();
-      if (token.value == "\n"){
-       // The idea of the two streams actually staying synchronized
-       // is such a long shot that we explicitly check.
-        if (part.nodeName != "BR")
-          throw "Parser out of sync. Expected BR.";
-        if (part.dirty || !part.lexicalContext)
-          lineDirty = true;
-       // Every <br> gets a copy of the parser state and a lexical
-       // context assigned to it. The first is used to be able to
-       // later resume parsing from this point, the second is used
-       // for indentation.
-        part.parserFromHere = parsed.copy();
-        part.lexicalContext = token.lexicalContext;
-        part.dirty = false;
-       // A clean line means we are done. Throwing a StopIteration is
-       // the way to break out of a MochiKit forEach loop.
-        if ((lines !== undefined && --lines <= 0) || !lineDirty)
-          throw StopIteration;
-        lineDirty = false;
-        parts.next();
-      }
-      else {
-        if (part.nodeName != "SPAN")
-          throw "Parser out of sync. Expected SPAN.";
-        if (part.dirty)
-          lineDirty = true;
-
-       // If the part matches the token, we can leave it alone.
-        if (correctPart(token, part)){
-          part.dirty = false;
-          parts.next();
-        }
-       // Otherwise, we have to fix it.
-        else {
-          lineDirty = true;
-         // Insert the correct part.
-          var newPart = tokenPart(token);
-          container.insertBefore(newPart, part);
-          var tokensize = token.value.length;
-          var offset = 0;
-         // Eat up parts until the text for this token has been
-         // removed, adjusting the stored selection info (see
-         // select.js) in the process.
-          while (tokensize > 0) {
-            part = parts.get();
-            var partsize = part.currentText.length;
-            select.replaceSelection(part.firstChild, newPart.firstChild, tokensize, offset);
-            if (partsize > tokensize){
-              shortenPart(part, tokensize);
-              tokensize = 0;
-            }
-            else {
-              tokensize -= partsize;
-              offset += partsize;
-              parts.remove();
-            }
-          }
-        }
-      }
-     }// while
-    } catch (e) {
-       if (e != StopIteration) {
-               throw e;
-       }
+                               var part = parts.nextNonEmpty();
+                               
+                               if (token.value == "\n") {
+                                       // The idea of the two streams actually staying synchronized
+                                       // is such a long shot that we explicitly check.
+                                       if (part.nodeName != "BR") {
+                                               throw "Parser out of sync. Expected BR.";
+                                       }
+                                       if (part.dirty || !part.lexicalContext) {
+                                               lineDirty = true;
+                                       }
+                                       // Every <br> gets a copy of the parser state and a lexical
+                                       // context assigned to it. The first is used to be able to
+                                       // later resume parsing from this point, the second is used
+                                       // for indentation.
+                                       part.parserFromHere = parsed.copy();
+                                       part.lexicalContext = token.lexicalContext;
+                                       part.dirty = false;
+                                       // A clean line means we are done. Throwing a StopIteration is
+                                       // the way to break out of a MochiKit forEach loop.
+                                       if ((lines !== undefined && --lines <= 0) || !lineDirty) {
+                                               throw StopIteration;
+                                       }
+                                       lineDirty = false;
+                                       parts.next();
+                               } else {
+                                       if (part.nodeName != "SPAN") {
+                                               throw "Parser out of sync. Expected SPAN.";
+                                       }
+                                       if (part.dirty) {
+                                               lineDirty = true;
+                                       }
+                                       // If the part matches the token, we can leave it alone.
+                                       if (correctPart(token, part)) {
+                                               part.dirty = false;
+                                               parts.next();
+                                       }
+                                       // Otherwise, we have to fix it.
+                                       else {
+                                               lineDirty = true;
+                                               // Insert the correct part.
+                                               var newPart = tokenPart(token);
+                                               container.insertBefore(newPart, part);
+                                               var tokensize = token.value.length;
+                                               var offset = 0;
+                                               // Eat up parts until the text for this token has been
+                                               // removed, adjusting the stored selection info (see
+                                               // select.js) in the process.
+                                               while (tokensize > 0) {
+                                                       part = parts.get();
+                                                       var partsize = part.currentText.length;
+                                                       select.replaceSelection(part.firstChild, newPart.firstChild, tokensize, offset);
+                                                       if (partsize > tokensize) {
+                                                               shortenPart(part, tokensize);
+                                                               tokensize = 0;
+                                                       } else {
+                                                               tokensize -= partsize;
+                                                               offset += partsize;
+                                                               parts.remove();
+                                                       }
+                                               }
+                                       }
+                               }
+                       } // while
+               } catch(e) {
+                       if (e != StopIteration) {
+                               throw e;
+                       }
+               }
+               this.refreshCursorObj();
+               this.initable = 1;
+
+               // The function returns some status information that is used by
+               // hightlightDirty to determine whether and where it has to
+               // continue.
+               return {
+                       left: lines,
+                       node: parts.get(),
+                       dirty: lineDirty
+               };
        }
-    this.refreshCursorObj();
-    this.initable = 1;
-    
-    // window.setTimeout('t3e_instances['+this.index+'].checkHistoryChanges();',100);
-    
-    // The function returns some status information that is used by
-    // hightlightDirty to determine whether and where it has to
-    // continue.
-    return {left: lines,
-            node: parts.get(),
-            dirty: lineDirty};
-  }
-
-  return t3editor;
-}();
 
+       return t3editor;
+} ();
 
-// ------------------------------------------------------------------------
 
+// ------------------------------------------------------------------------
 
 
-function t3editor_toggleEditor(checkbox,index) {
+/**
+ * toggle between enhanced editor (t3editor) and simple textarea
+ */
+function t3editor_toggleEditor(checkbox, index) {
        if (index == undefined) {
                $$('textarea.t3editor').each(
-                       function(textarea,i) {
-                               t3editor_toggleEditor(checkbox,i);
-                       }
-               );      
+               function(textarea, i) {
+                       t3editor_toggleEditor(checkbox, i);
+               });
        } else {
                if (t3e_instances[index] != undefined) {
                        var t3e = t3e_instances[index];
@@ -1588,22 +1560,24 @@ function t3editor_toggleEditor(checkbox,index) {
                        var t3e = new t3editor($$('textarea.t3editor')[index], index);
                        t3e_instances[index] = t3e;
                }
-       }       
+       }
 }
 
 // ------------------------------------------------------------------------
 
 
-/**
- * everything ready: turn textareas into fancy editors
- */
-Event.observe(window,'load',function() {
-       $$('textarea.t3editor').each(
-               function(textarea,i) {
-                       if ($('t3editor_disableEditor_'+(i+1)+'_checkbox') && !$('t3editor_disableEditor_'+(i+1)+'_checkbox').checked) {
-                               var t3e = new t3editor(textarea,i);
-                               t3e_instances[i] = t3e;
-                       }
+// everything ready: turn textarea's into fancy editors
+if (!Prototype.Browser.MobileSafari) {
+       Event.observe(window, 'load', 
+               function() {
+                       $$('textarea.t3editor').each(
+                               function(textarea, i) {
+                                       if ($('t3editor_disableEditor_' + (i + 1) + '_checkbox') && !$('t3editor_disableEditor_' + (i + 1) + '_checkbox').checked) {
+                                               var t3e = new t3editor(textarea, i);
+                                               t3e_instances[i] = t3e;
+                                       }
+                               }
+                       );
                }
        );
-});
+}
index 58c25ee..8813b59 100755 (executable)
 
 // List of "reserved" word in typoscript and a css-class
 var typoscriptWords = {
-       '_CSS_DEFAULT_STYLE'    : 'keyword',
-       '_DEFAULT_PI_VARS'              : 'keyword',
-       '_GIFBUILDER'                   : 'keyword',
-       '_LOCAL_LANG'                   : 'keyword',
-       'CARRAY'                                : 'keyword',
-       'CASE'                                  : 'keyword',
-       'CLEARGIF'                              : 'keyword',
-       'COA'                                   : 'keyword',
-       'COA_INT'                               : 'keyword',
-       'COBJ_ARRAY'                    : 'keyword',
-       'COLUMNS'                               : 'keyword',
-       'CONFIG'                                : 'keyword',
-       'CONSTANTS'                             : 'keyword',
-       'CONTENT'                               : 'keyword',
-       'CTABLE'                                : 'keyword',
-       'CType'                                 : 'keyword',
-       'DB'                                    : 'keyword',
-       'DOCUMENT_BODY'                 : 'keyword',
-       'EDITPANEL'                             : 'keyword',
-       'EFFECT'                                : 'keyword',
-       'FE_DATA'                               : 'keyword',
-       'FE_TABLE'                              : 'keyword',
-       'FEData'                                : 'keyword',
-       'FILE'                                  : 'keyword',
-       'FORM'                                  : 'keyword',
-       'FRAME'                                 : 'keyword',
-       'FRAMESET'                              : 'keyword',
-       'GIFBUILDER'                    : 'keyword',
-       'global'                                : 'keyword',
-       'globalString'                  : 'keyword',
-       'globalVar'                             : 'keyword',
-       'GMENU'                                 : 'keyword',
-       'GMENU_FOLDOUT'                 : 'keyword',
-       'GMENU_LAYERS'                  : 'keyword',
-       'GP'                                    : 'keyword',
-       'HMENU'                                 : 'keyword',
-       'HRULER'                                : 'keyword',
-       'HTML'                                  : 'keyword',
-       'IENV'                                  : 'keyword',
-       'IMAGE'                                 : 'keyword',
-       'IMG_RESOURCE'                  : 'keyword',
-       'IMGMENU'                               : 'keyword',
-       'IMGMENUITEM'                   : 'keyword',
-       'IMGTEXT'                               : 'keyword',
-       'INCLUDE_TYPOSCRIPT'    : 'keyword',
-       'includeLibs'                   : 'keyword',
-       'JSMENU'                                : 'keyword',
-       'JSMENUITEM'                    : 'keyword',
-       'LIT'                                   : 'keyword',
-       'LOAD_REGISTER'                 : 'keyword',
-       'META'                                  : 'keyword',
-       'MULTIMEDIA'                    : 'keyword',
-       'OTABLE'                                : 'keyword',
-       'PAGE'                                  : 'keyword',
-       'PAGE_TARGET'                   : 'keyword',
-       'PAGE_TSCONFIG_ID'              : 'keyword',
-       'PAGE_TSCONFIG_IDLIST'  : 'keyword',
-       'PAGE_TSCONFIG_STR'             : 'keyword',
-       'PHP_SCRIPT'                    : 'keyword',
-       'PHP_SCRIPT_EXT'                : 'keyword',
-       'PHP_SCRIPT_INT'                : 'keyword',
-       'RECORDS'                               : 'keyword',
-       'REMOTE_ADDR'                   : 'keyword',
-       'RESTORE_REGISTER'              : 'keyword',
-       'RTE'                                   : 'keyword',
-       'SEARCHRESULT'                  : 'keyword',
-       'SHARED'                                : 'keyword',
-       'TCAdefaults'                   : 'keyword',
-       'TCEFORM'                               : 'keyword',
-       'TCEMAIN'                               : 'keyword',
-       'TEMPLATE'                              : 'keyword',
-       'TEXT'                                  : 'keyword',
-       'TMENU'                                 : 'keyword',
-       'TMENU_LAYERS'                  : 'keyword',
-       'TMENUITEM'                             : 'keyword',
-       'TSFE'                                  : 'keyword',
-       'USER'                                  : 'keyword',
-       'USER_INT'                              : 'keyword',
-       'userFunc'                              : 'keyword',
-       
-       '_offset'                               : 'reserved',
-       'absRefPrefix'  : 'reserved',
-       'accessibility' : 'reserved',
-       'accessKey'     : 'reserved',
-       'addAttributes' : 'reserved',
-       'addExtUrlsAndShortCuts'        : 'reserved',
-       'addItems'      : 'reserved',
-       'additionalHeaders'     : 'reserved',
-       'additionalParams'      : 'reserved',
-       'addParams'     : 'reserved',
-       'addQueryString'        : 'reserved',
-       'adjustItemsH'  : 'reserved',
-       'adjustSubItemsH'       : 'reserved',
-       'adminPanelStyles'      : 'reserved',
-       'after' : 'reserved',
-       'afterImg'      : 'reserved',
-       'afterImgLink'  : 'reserved',
-       'afterImgTagParams'     : 'reserved',
-       'afterROImg'    : 'reserved',
-       'afterWrap'     : 'reserved',
-       'age'   : 'reserved',
-       'alertPopups'   : 'reserved',
-       'align' : 'reserved',
-       'allow' : 'reserved',
-       'allowCaching'  : 'reserved',
-       'allowedAttribs'        : 'reserved',
-       'allowedClasses'        : 'reserved',
-       'allowedCols'   : 'reserved',
-       'allowEdit'     : 'reserved',
-       'allowedNewTables'      : 'reserved',
-       'allowNew'      : 'reserved',
-       'allowTags'     : 'reserved',
-       'allowTVlisting'        : 'reserved',
-       'allSaveFunctions'      : 'reserved',
-       'allStdWrap'    : 'reserved',
-       'allWrap'       : 'reserved',
-       'alternateBgColors'     : 'reserved',
-       'alternativeSortingField'       : 'reserved',
-       'alternativeTempPath'   : 'reserved',
-       'altImgResource'        : 'reserved',
-       'altLabels'     : 'reserved',
-       'altTarget'     : 'reserved',
-       'altText'       : 'reserved',
-       'altUrl'        : 'reserved',
-       'altUrl_noDefaultParams'        : 'reserved',
-       'altWrap'       : 'reserved',
-       'always'        : 'reserved',
-       'alwaysActivePIDlist'   : 'reserved',
-       'alwaysLink'    : 'reserved',
-       'alwaysShowClickMenuInTopFrame' : 'reserved',
-       'andWhere'      : 'reserved',
-       'angle' : 'reserved',
-       'antiAlias'     : 'reserved',
-       'append'        : 'reserved',
-       'applyTotalH'   : 'reserved',
-       'applyTotalW'   : 'reserved',
-       'archive'       : 'reserved',
-       'archiveTypoLink'       : 'reserved',
-       'arrayReturnMode'       : 'reserved',
-       'arrowACT'      : 'reserved',
-       'arrowImgParams'        : 'reserved',
-       'arrowNO'       : 'reserved',
-       'ATagAfterWrap' : 'reserved',
-       'ATagBeforeWrap'        : 'reserved',
-       'ATagParams'    : 'reserved',
-       'ATagTitle'     : 'reserved',
-       'attribute'     : 'reserved',
-       'autoInsertPID' : 'reserved',
-       'autoLevels'    : 'reserved',
-       'autonumber'    : 'reserved',
-       'backColor'     : 'reserved',
-       'background'    : 'reserved',
-       'badMess'       : 'reserved',
-       'baseURL'       : 'reserved',
-       'before'        : 'reserved',
-       'beforeImg'     : 'reserved',
-       'beforeImgLink' : 'reserved',
-       'beforeImgTagParams'    : 'reserved',
-       'beforeROImg'   : 'reserved',
-       'beforeWrap'    : 'reserved',
-       'begin' : 'reserved',
-       'beLoginLinkIPList'     : 'reserved',
-       'beLoginLinkIPList_login'       : 'reserved',
-       'beLoginLinkIPList_logout'      : 'reserved',
-       'bgCol' : 'reserved',
-       'bgImg' : 'reserved',
-       'blankStrEqFalse'       : 'reserved',
-       'blur'  : 'reserved',
-       'bm'    : 'reserved',
-       'bodyTag'       : 'reserved',
-       'bodyTagAdd'    : 'reserved',
-       'bodyTagCObject'        : 'reserved',
-       'bodyTagMargins'        : 'reserved',
-       'bodytext'      : 'reserved',
-       'border'        : 'reserved',
-       'borderCol'     : 'reserved',
-       'bordersWithin' : 'reserved',
-       'borderThick'   : 'reserved',
-       'bottomBackColor'       : 'reserved',
-       'bottomContent' : 'reserved',
-       'bottomHeight'  : 'reserved',
-       'bottomImg'     : 'reserved',
-       'bottomImg_mask'        : 'reserved',
-       'br'    : 'reserved',
-       'brTag' : 'reserved',
-       'bullet'        : 'reserved',
-       'bulletlist'    : 'reserved',
-       'bytes' : 'reserved',
-       'cache_clearAtMidnight' : 'reserved',
-       'cache_period'  : 'reserved',
-       'caption'       : 'reserved',
-       'caption_stdWrap'       : 'reserved',
-       'captionAlign'  : 'reserved',
-       'captionHeader' : 'reserved',
-       'captionSplit'  : 'reserved',
-       'case'  : 'reserved',
-       'casesensitiveComp'     : 'reserved',
-       'cellpadding'   : 'reserved',
-       'cellspacing'   : 'reserved',
-       'centerImgACT'  : 'reserved',
-       'centerImgCUR'  : 'reserved',
-       'centerImgNO'   : 'reserved',
-       'centerLeftImgACT'      : 'reserved',
-       'centerLeftImgCUR'      : 'reserved',
-       'centerLeftImgNO'       : 'reserved',
-       'centerRightImgACT'     : 'reserved',
-       'centerRightImgCUR'     : 'reserved',
-       'centerRightImgNO'      : 'reserved',
-       'char'  : 'reserved',
-       'charcoal'      : 'reserved',
-       'charMapConfig' : 'reserved',
-       'check' : 'reserved',
-       'class' : 'reserved',
-       'classesAnchor' : 'reserved',
-       'classesCharacter'      : 'reserved',
-       'classesImage'  : 'reserved',
-       'classesParagraph'      : 'reserved',
-       'classicPageEditMode'   : 'reserved',
-       'clear' : 'reserved',
-       'clearCache'    : 'reserved',
-       'clearCache_disable'    : 'reserved',
-       'clearCache_pageGrandParent'    : 'reserved',
-       'clearCache_pageSiblingChildren'        : 'reserved',
-       'clearCacheCmd' : 'reserved',
-       'clearCacheLevels'      : 'reserved',
-       'clearCacheOfPages'     : 'reserved',
-       'clickMenuTimeOut'      : 'reserved',
-       'clickTitleMode'        : 'reserved',
-       'clipboardNumberPads'   : 'reserved',
-       'cMargins'      : 'reserved',
-       'cObjNum'       : 'reserved',
-       'collapse'      : 'reserved',
-       'color' : 'reserved',
-       'color1'        : 'reserved',
-       'color2'        : 'reserved',
-       'color3'        : 'reserved',
-       'color4'        : 'reserved',
-       'colors'        : 'reserved',
-       'colour'        : 'reserved',
-       'colPos_list'   : 'reserved',
-       'colRelations'  : 'reserved',
-       'cols'  : 'reserved',
-       'colSpace'      : 'reserved',
-       'comment_auto'  : 'reserved',
-       'commentWrap'   : 'reserved',
-       'compensateFieldWidth'  : 'reserved',
-       'compX' : 'reserved',
-       'compY' : 'reserved',
-       'condensedMode' : 'reserved',
-       'conf'  : 'reserved',
-       'constants'     : 'reserved',
-       'content_from_pid_allowOutsideDomain'   : 'reserved',
-       'contextMenu'   : 'reserved',
-       'copyLevels'    : 'reserved',
-       'count_HMENU_MENUOBJ'   : 'reserved',
-       'count_menuItems'       : 'reserved',
-       'count_MENUOBJ' : 'reserved',
-       'create'        : 'reserved',
-       'createFoldersInEB'     : 'reserved',
-       'crop'  : 'reserved',
-       'csConv'        : 'reserved',
-       'CSS_inlineStyle'       : 'reserved',
-       'current'       : 'reserved',
-       'curUid'        : 'reserved',
-       'cWidth'        : 'reserved',
-       'data'  : 'reserved',
-       'dataWrap'      : 'reserved',
-       'date'  : 'reserved',
-       'date_stdWrap'  : 'reserved',
-       'datePrefix'    : 'reserved',
-       'debug' : 'reserved',
-       'debugData'     : 'reserved',
-       'debugFunc'     : 'reserved',
-       'debugItemConf' : 'reserved',
-       'debugRenumberedObject' : 'reserved',
-       'default'       : 'reserved',
-       'defaultAlign'  : 'reserved',
-       'defaultCmd'    : 'reserved',
-       'defaultFileUploads'    : 'reserved',
-       'defaultHeaderType'     : 'reserved',
-       'defaultOutput' : 'reserved',
-       'defaults'      : 'reserved',
-       'defaultType'   : 'reserved',
-       'delete'        : 'reserved',
-       'denyTags'      : 'reserved',
-       'depth' : 'reserved',
-       'DESC'  : 'reserved',
-       'dimensions'    : 'reserved',
-       'directionLeft' : 'reserved',
-       'directionUp'   : 'reserved',
-       'disableAdvanced'       : 'reserved',
-       'disableAllHeaderCode'  : 'reserved',
-       'disableAltText'        : 'reserved',
-       'disableBigButtons'     : 'reserved',
-       'disableCacheSelector'  : 'reserved',
-       'disableCharsetHeader'  : 'reserved',
-       'disableCMlayers'       : 'reserved',
-       'disabled'      : 'reserved',
-       'disableDelete' : 'reserved',
-       'disableDocModuleInAB'  : 'reserved',
-       'disableDocSelector'    : 'reserved',
-       'disableHideAtCopy'     : 'reserved',
-       'disableIconLinkToContextmenu'  : 'reserved',
-       'disableItems'  : 'reserved',
-       'disableNewContentElementWizard'        : 'reserved',
-       'disableNoMatchingValueElement' : 'reserved',
-       'disablePageExternalUrl'        : 'reserved',
-       'disablePrefixComment'  : 'reserved',
-       'disablePrependAtCopy'  : 'reserved',
-       'disableSearchBox'      : 'reserved',
-       'disableSingleTableView'        : 'reserved',
-       'disableTabInTextarea'  : 'reserved',
-       'displayActiveOnLoad'   : 'reserved',
-       'displayContent'        : 'reserved',
-       'displayFieldIcons'     : 'reserved',
-       'displayIcons'  : 'reserved',
-       'displayMessages'       : 'reserved',
-       'displayQueries'        : 'reserved',
-       'displayRecord' : 'reserved',
-       'displayTimes'  : 'reserved',
-       'distributeX'   : 'reserved',
-       'distributeY'   : 'reserved',
-       'DIV'   : 'reserved',
-       'doctype'       : 'reserved',
-       'doctypeSwitch' : 'reserved',
-       'doktype'       : 'reserved',
-       'doNotLinkIt'   : 'reserved',
-       'doNotShowLink' : 'reserved',
-       'doNotStripHTML'        : 'reserved',
-       'dontCheckPid'  : 'reserved',
-       'dontFollowMouse'       : 'reserved',
-       'dontHideOnMouseUp'     : 'reserved',
-       'dontLinkIfSubmenu'     : 'reserved',
-       'dontShowPalettesOnFocusInAB'   : 'reserved',
-       'dontWrapInTable'       : 'reserved',
-       'doubleBrTag'   : 'reserved',
-       'doublePostCheck'       : 'reserved',
-       'dWorkArea'     : 'reserved',
-       'edge'  : 'reserved',
-       'edit_docModuleUplaod'  : 'reserved',
-       'edit_docModuleUpload'  : 'reserved',
-       'edit_RTE'      : 'reserved',
-       'edit_showFieldHelp'    : 'reserved',
-       'edit_wideDocument'     : 'reserved',
-       'editFieldsAtATime'     : 'reserved',
-       'editFormsOnPage'       : 'reserved',
-       'editIcons'     : 'reserved',
-       'editNoPopup'   : 'reserved',
-       'editPanel'     : 'reserved',
-       'elements'      : 'reserved',
-       'emailMeAtLogin'        : 'reserved',
-       'emailMess'     : 'reserved',
-       'emboss'        : 'reserved',
-       'enable'        : 'reserved',
-       'encapsLines'   : 'reserved',
-       'encapsLinesStdWrap'    : 'reserved',
-       'encapsTagList' : 'reserved',
-       'entryLevel'    : 'reserved',
-       'equalH'        : 'reserved',
-       'everybody'     : 'reserved',
-       'excludeDoktypes'       : 'reserved',
-       'excludeUidList'        : 'reserved',
-       'expAll'        : 'reserved',
-       'expand'        : 'reserved',
-       'explode'       : 'reserved',
-       'ext'   : 'reserved',
-       'externalBlocks'        : 'reserved',
-       'extTarget'     : 'reserved',
-       'face'  : 'reserved',
-       'fe_adminLib'   : 'reserved',
-       'field' : 'reserved',
-       'fieldOrder'    : 'reserved',
-       'fieldRequired' : 'reserved',
-       'fields'        : 'reserved',
-       'fieldWrap'     : 'reserved',
-       'file'  : 'reserved',
-       'file1' : 'reserved',
-       'file2' : 'reserved',
-       'file3' : 'reserved',
-       'file4' : 'reserved',
-       'file5' : 'reserved',
-       'filelink'      : 'reserved',
-       'filelist'      : 'reserved',
-       'firstLabel'    : 'reserved',
-       'firstLabelGeneral'     : 'reserved',
-       'fixAttrib'     : 'reserved',
-       'flip'  : 'reserved',
-       'flop'  : 'reserved',
-       'foldSpeed'     : 'reserved',
-       'foldTimer'     : 'reserved',
-       'fontColor'     : 'reserved',
-       'fontFile'      : 'reserved',
-       'fontOffset'    : 'reserved',
-       'fontSize'      : 'reserved',
-       'fontSizeMultiplicator' : 'reserved',
-       'fontTag'       : 'reserved',
-       'forceDisplayFieldIcons'        : 'reserved',
-       'forceDisplayIcons'     : 'reserved',
-       'forceNoPopup'  : 'reserved',
-       'forceTemplateParsing'  : 'reserved',
-       'forceTypeValue'        : 'reserved',
-       'format'        : 'reserved',
-       'frame' : 'reserved',
-       'frameReloadIfNotInFrameset'    : 'reserved',
-       'frameSet'      : 'reserved',
-       'freezeMouseover'       : 'reserved',
-       'ftu'   : 'reserved',
-       'function'      : 'reserved',
-       'gamma' : 'reserved',
-       'gapBgCol'      : 'reserved',
-       'gapLineCol'    : 'reserved',
-       'gapLineThickness'      : 'reserved',
-       'gapWidth'      : 'reserved',
-       'get'   : 'reserved',
-       'getBorder'     : 'reserved',
-       'getLeft'       : 'reserved',
-       'getRight'      : 'reserved',
-       'globalNesting' : 'reserved',
-       'goodMess'      : 'reserved',
-       'gray'  : 'reserved',
-       'group' : 'reserved',
-       'groupBy'       : 'reserved',
-       'groupid'       : 'reserved',
-       'header'        : 'reserved',
-       'header_layout' : 'reserved',
-       'headerComment' : 'reserved',
-       'headerData'    : 'reserved',
-       'headerSpace'   : 'reserved',
-       'headTag'       : 'reserved',
-       'height'        : 'reserved',
-       'helpText'      : 'reserved',
-       'hidden'        : 'reserved',
-       'hiddenFields'  : 'reserved',
-       'hide'  : 'reserved',
-       'hideButCreateMap'      : 'reserved',
-       'hideMenuTimer' : 'reserved',
-       'hideMenuWhenNotOver'   : 'reserved',
-       'hidePStyleItems'       : 'reserved',
-       'hideRecords'   : 'reserved',
-       'hideSubmoduleIcons'    : 'reserved',
-       'highColor'     : 'reserved',
-       'history'       : 'reserved',
-       'hover' : 'reserved',
-       'hoverStyle'    : 'reserved',
-       'HTMLparser'    : 'reserved',
-       'HTMLparser_tags'       : 'reserved',
-       'htmlSpecialChars'      : 'reserved',
-       'htmlTag_dir'   : 'reserved',
-       'htmlTag_langKey'       : 'reserved',
-       'htmlTag_setParams'     : 'reserved',
-       'http'  : 'reserved',
-       'icon'  : 'reserved',
-       'icon_image_ext_list'   : 'reserved',
-       'icon_link'     : 'reserved',
-       'iconCObject'   : 'reserved',
-       'ifEmpty'       : 'reserved',
-       'image' : 'reserved',
-       'image_compression'     : 'reserved',
-       'image_effects' : 'reserved',
-       'image_frames'  : 'reserved',
-       'imageLinkWrap' : 'reserved',
-       'imagePath'     : 'reserved',
-       'images'        : 'reserved',
-       'imageWrapIfAny'        : 'reserved',
-       'imgList'       : 'reserved',
-       'imgMap'        : 'reserved',
-       'imgMapExtras'  : 'reserved',
-       'imgMax'        : 'reserved',
-       'imgNameNotRandom'      : 'reserved',
-       'imgNamePrefix' : 'reserved',
-       'imgObjNum'     : 'reserved',
-       'imgParams'     : 'reserved',
-       'imgPath'       : 'reserved',
-       'imgStart'      : 'reserved',
-       'import'        : 'reserved',
-       'inc'   : 'reserved',
-       'includeCSS'    : 'reserved',
-       'includeLibrary'        : 'reserved',
-       'includeNotInMenu'      : 'reserved',
-       'incT3Lib_htmlmail'     : 'reserved',
-       'index' : 'reserved',
-       'index_descrLgd'        : 'reserved',
-       'index_enable'  : 'reserved',
-       'index_externals'       : 'reserved',
-       'inlineStyle2TempFile'  : 'reserved',
-       'innerStdWrap'  : 'reserved',
-       'innerStdWrap_all'      : 'reserved',
-       'innerWrap'     : 'reserved',
-       'innerWrap2'    : 'reserved',
-       'input' : 'reserved',
-       'inputLevels'   : 'reserved',
-       'insertClassesFromRTE'  : 'reserved',
-       'insertData'    : 'reserved',
-       'insertDmailerBoundaries'       : 'reserved',
-       'intensity'     : 'reserved',
-       'intTarget'     : 'reserved',
-       'intval'        : 'reserved',
-       'invert'        : 'reserved',
-       'IProcFunc'     : 'reserved',
-       'itemArrayProcFunc'     : 'reserved',
-       'itemH' : 'reserved',
-       'items' : 'reserved',
-       'itemsProcFunc' : 'reserved',
-       'iterations'    : 'reserved',
-       'join'  : 'reserved',
-       'JSWindow'      : 'reserved',
-       'JSwindow_params'       : 'reserved',
-       'jumpurl'       : 'reserved',
-       'jumpUrl'       : 'reserved',
-       'jumpurl_enable'        : 'reserved',
-       'jumpurl_mailto_disable'        : 'reserved',
-       'jumpUrl_transferSession'       : 'reserved',
-       'keep'  : 'reserved',
-       'keepEntries'   : 'reserved',
-       'keepNonMatchedTags'    : 'reserved',
-       'key'   : 'reserved',
-       'label' : 'reserved',
-       'labelStdWrap'  : 'reserved',
-       'labelWrap'     : 'reserved',
-       'lang'  : 'reserved',
-       'language'      : 'reserved',
-       'language_alt'  : 'reserved',
-       'languageField' : 'reserved',
-       'layer_menu_id' : 'reserved',
-       'layerStyle'    : 'reserved',
-       'left'  : 'reserved',
-       'leftIcons'     : 'reserved',
-       'leftImgACT'    : 'reserved',
-       'leftImgCUR'    : 'reserved',
-       'leftImgNO'     : 'reserved',
-       'leftjoin'      : 'reserved',
-       'leftOffset'    : 'reserved',
-       'levels'        : 'reserved',
-       'leveluid'      : 'reserved',
-       'limit' : 'reserved',
-       'line'  : 'reserved',
-       'lineColor'     : 'reserved',
-       'lineThickness' : 'reserved',
-       'linkPrefix'    : 'reserved',
-       'linkTitleToSelf'       : 'reserved',
-       'linkVars'      : 'reserved',
-       'linkWrap'      : 'reserved',
-       'listNum'       : 'reserved',
-       'listOnlyInSingleTableView'     : 'reserved',
-       'lm'    : 'reserved',
-       'locale_all'    : 'reserved',
-       'localNesting'  : 'reserved',
-       'locationData'  : 'reserved',
-       'lockFilePath'  : 'reserved',
-       'lockPosition'  : 'reserved',
-       'lockPosition_addSelf'  : 'reserved',
-       'lockPosition_adjust'   : 'reserved',
-       'lockToIP'      : 'reserved',
-       'longdescURL'   : 'reserved',
-       'lowColor'      : 'reserved',
-       'lower' : 'reserved',
-       'LR'    : 'reserved',
-       'mailto'        : 'reserved',
-       'main'  : 'reserved',
-       'mainScript'    : 'reserved',
-       'makelinks'     : 'reserved',
-       'markerWrap'    : 'reserved',
-       'mask'  : 'reserved',
-       'max'   : 'reserved',
-       'maxAge'        : 'reserved',
-       'maxAgeDays'    : 'reserved',
-       'maxChars'      : 'reserved',
-       'maxH'  : 'reserved',
-       'maxHeight'     : 'reserved',
-       'maxItems'      : 'reserved',
-       'maxW'  : 'reserved',
-       'maxWidth'      : 'reserved',
-       'maxWInText'    : 'reserved',
-       'mayNotCreateEditShortcuts'     : 'reserved',
-       'menu_type'     : 'reserved',
-       'menuBackColor' : 'reserved',
-       'menuHeight'    : 'reserved',
-       'menuName'      : 'reserved',
-       'menuOffset'    : 'reserved',
-       'menuWidth'     : 'reserved',
-       'message_page_is_being_generated'       : 'reserved',
-       'message_preview'       : 'reserved',
-       'meta'  : 'reserved',
-       'metaCharset'   : 'reserved',
-       'method'        : 'reserved',
-       'min'   : 'reserved',
-       'minH'  : 'reserved',
-       'minItems'      : 'reserved',
-       'minW'  : 'reserved',
-       'mode'  : 'reserved',
-       'moduleMenuCollapsable' : 'reserved',
-       'MP_defaults'   : 'reserved',
-       'MP_disableTypolinkClosestMPvalue'      : 'reserved',
-       'MP_mapRootPoints'      : 'reserved',
-       'name'  : 'reserved',
-       'navFrameResizable'     : 'reserved',
-       'navFrameWidth' : 'reserved',
-       'nesting'       : 'reserved',
-       'netprintApplicationLink'       : 'reserved',
-       'neverHideAtCopy'       : 'reserved',
-       'newPageWiz'    : 'reserved',
-       'newRecordFromTable'    : 'reserved',
-       'newWindow'     : 'reserved',
-       'newWizards'    : 'reserved',
-       'next'  : 'reserved',
-       'niceText'      : 'reserved',
-       'nicetext'      : 'reserved',
-       'no_cache'      : 'reserved',
-       'no_search'     : 'reserved',
-       'noAttrib'      : 'reserved',
-       'noBlur'        : 'reserved',
-       'noCache'       : 'reserved',
-       'noCols'        : 'reserved',
-       'noCreateRecordsLink'   : 'reserved',
-       'noLink'        : 'reserved',
-       'noLinkUnderline'       : 'reserved',
-       'noMatchingValue_label' : 'reserved',
-       'noMenuMode'    : 'reserved',
-       'nonCachedSubst'        : 'reserved',
-       'nonTypoTagStdWrap'     : 'reserved',
-       'nonTypoTagUserFunc'    : 'reserved',
-       'nonWrappedTag' : 'reserved',
-       'noOrderBy'     : 'reserved',
-       'noPageTitle'   : 'reserved',
-       'noRows'        : 'reserved',
-       'noScaleUp'     : 'reserved',
-       'noStretchAndMarginCells'       : 'reserved',
-       'noThumbsInEB'  : 'reserved',
-       'noThumbsInRTEimageSelect'      : 'reserved',
-       'notification_email_charset'    : 'reserved',
-       'notification_email_encoding'   : 'reserved',
-       'notification_email_urlmode'    : 'reserved',
-       'noTrimWrap'    : 'reserved',
-       'noValueInsert' : 'reserved',
-       'obj'   : 'reserved',
-       'offset'        : 'reserved',
-       'offsetWrap'    : 'reserved',
-       'onlineWorkspaceInfo'   : 'reserved',
-       'onlyCurrentPid'        : 'reserved',
-       'opacity'       : 'reserved',
-       'orderBy'       : 'reserved',
-       'outerWrap'     : 'reserved',
-       'outline'       : 'reserved',
-       'outputLevels'  : 'reserved',
-       'override'      : 'reserved',
-       'overrideAttribs'       : 'reserved',
-       'overrideEdit'  : 'reserved',
-       'overrideId'    : 'reserved',
-       'overridePageModule'    : 'reserved',
-       'overrideWithExtension' : 'reserved',
-       'pageFrameObj'  : 'reserved',
-       'pageGenScript' : 'reserved',
-       'pageTitleFirst'        : 'reserved',
-       'parameter'     : 'reserved',
-       'params'        : 'reserved',
-       'parseFunc'     : 'reserved',
-       'parser'        : 'reserved',
-       'password'      : 'reserved',
-       'path'  : 'reserved',
-       'permissions'   : 'reserved',
-       'pid_list'      : 'reserved',
-       'pidInList'     : 'reserved',
-       'pixelSpaceFontSizeRef' : 'reserved',
-       'plaintextLib'  : 'reserved',
-       'plainTextStdWrap'      : 'reserved',
-       'postCObject'   : 'reserved',
-       'postLineBlanks'        : 'reserved',
-       'postLineChar'  : 'reserved',
-       'postLineLen'   : 'reserved',
-       'postUserFunc'  : 'reserved',
-       'postUserFuncInt'       : 'reserved',
-       'preBlanks'     : 'reserved',
-       'preCObject'    : 'reserved',
-       'prefix'        : 'reserved',
-       'prefixComment' : 'reserved',
-       'prefixLocalAnchors'    : 'reserved',
-       'prefixRelPathWith'     : 'reserved',
-       'preIfEmptyListNum'     : 'reserved',
-       'preLineBlanks' : 'reserved',
-       'preLineChar'   : 'reserved',
-       'preLineLen'    : 'reserved',
-       'prepend'       : 'reserved',
-       'preserveEntities'      : 'reserved',
-       'preUserFunc'   : 'reserved',
-       'prev'  : 'reserved',
-       'previewBorder' : 'reserved',
-       'prevnextToSection'     : 'reserved',
-       'printheader'   : 'reserved',
-       'prioriCalc'    : 'reserved',
-       'proc'  : 'reserved',
-       'processScript' : 'reserved',
-       'properties'    : 'reserved',
-       'protect'       : 'reserved',
-       'protectLvar'   : 'reserved',
-       'publish_levels'        : 'reserved',
-       'QEisDefault'   : 'reserved',
-       'quality'       : 'reserved',
-       'radio' : 'reserved',
-       'radioWrap'     : 'reserved',
-       'range' : 'reserved',
-       'rawUrlEncode'  : 'reserved',
-       'recipient'     : 'reserved',
-       'recursive'     : 'reserved',
-       'recursiveDelete'       : 'reserved',
-       'redirect'      : 'reserved',
-       'redirectToURL' : 'reserved',
-       'reduceColors'  : 'reserved',
-       'register'      : 'reserved',
-       'relativeToParentLayer' : 'reserved',
-       'relativeToTriggerItem' : 'reserved',
-       'relPathPrefix' : 'reserved',
-       'remap' : 'reserved',
-       'remapTag'      : 'reserved',
-       'removeBadHTML' : 'reserved',
-       'removeDefaultJS'       : 'reserved',
-       'removeIfEquals'        : 'reserved',
-       'removeIfFalse' : 'reserved',
-       'removeItems'   : 'reserved',
-       'removeObjectsOfDummy'  : 'reserved',
-       'removePrependedNumbers'        : 'reserved',
-       'removeTags'    : 'reserved',
-       'removeWrapping'        : 'reserved',
-       'renderCharset' : 'reserved',
-       'renderWrap'    : 'reserved',
-       'reset' : 'reserved',
-       'resources'     : 'reserved',
-       'resultObj'     : 'reserved',
-       'returnLast'    : 'reserved',
-       'returnUrl'     : 'reserved',
-       'rightImgACT'   : 'reserved',
-       'rightImgCUR'   : 'reserved',
-       'rightImgNO'    : 'reserved',
-       'rightjoin'     : 'reserved',
-       'rm'    : 'reserved',
-       'rmTagIfNoAttrib'       : 'reserved',
-       'RO_chBgColor'  : 'reserved',
-       'rotate'        : 'reserved',
-       'rows'  : 'reserved',
-       'rowSpace'      : 'reserved',
-       'RTEfullScreenWidth'    : 'reserved',
-       'rules' : 'reserved',
-       'sample'        : 'reserved',
-       'saveClipboard' : 'reserved',
-       'saveDocNew'    : 'reserved',
-       'secondRow'     : 'reserved',
-       'section'       : 'reserved',
-       'sectionIndex'  : 'reserved',
-       'select'        : 'reserved',
-       'select_key'    : 'reserved',
-       'selectFields'  : 'reserved',
-       'separator'     : 'reserved',
-       'set'   : 'reserved',
-       'setContentToCurrent'   : 'reserved',
-       'setCurrent'    : 'reserved',
-       'setfixed'      : 'reserved',
-       'setFixedHeight'        : 'reserved',
-       'setFixedWidth' : 'reserved',
-       'setJS_mouseOver'       : 'reserved',
-       'setJS_openPic' : 'reserved',
-       'setOnly'       : 'reserved',
-       'shadow'        : 'reserved',
-       'sharpen'       : 'reserved',
-       'shear' : 'reserved',
-       'short' : 'reserved',
-       'shortcut'      : 'reserved',
-       'shortcut_onEditId_dontSetPageTree'     : 'reserved',
-       'shortcut_onEditId_keepExistingExpanded'        : 'reserved',
-       'shortcutFrame' : 'reserved',
-       'shortcutGroups'        : 'reserved',
-       'shortcutIcon'  : 'reserved',
-       'show'  : 'reserved',
-       'showAccessRestrictedPages'     : 'reserved',
-       'showActive'    : 'reserved',
-       'showClipControlPanelsDespiteOfCMlayers'        : 'reserved',
-       'showFirst'     : 'reserved',
-       'showHiddenPages'       : 'reserved',
-       'showHiddenRecords'     : 'reserved',
-       'showHistory'   : 'reserved',
-       'showPageIdWithTitle'   : 'reserved',
-       'showTagFreeClasses'    : 'reserved',
-       'simulateDate'  : 'reserved',
-       'simulateStaticDocuments'       : 'reserved',
-       'simulateStaticDocuments_addTitle'      : 'reserved',
-       'simulateStaticDocuments_dontRedirectPathInfoError'     : 'reserved',
-       'simulateStaticDocuments_noTypeIfNoTitle'       : 'reserved',
-       'simulateStaticDocuments_pEnc'  : 'reserved',
-       'simulateStaticDocuments_pEnc_onlyP'    : 'reserved',
-       'simulateUserGroup'     : 'reserved',
-       'singlePid'     : 'reserved',
-       'site_author'   : 'reserved',
-       'site_reserved' : 'reserved',
-       'sitetitle'     : 'reserved',
-       'siteUrl'       : 'reserved',
-       'size'  : 'reserved',
-       'smallFormFields'       : 'reserved',
-       'solarize'      : 'reserved',
-       'sorting'       : 'reserved',
-       'source'        : 'reserved',
-       'space' : 'reserved',
-       'spaceAfter'    : 'reserved',
-       'spaceBefore'   : 'reserved',
-       'spaceBelowAbove'       : 'reserved',
-       'spaceLeft'     : 'reserved',
-       'spaceRight'    : 'reserved',
-       'spacing'       : 'reserved',
-       'spamProtectEmailAddresses'     : 'reserved',
-       'spamProtectEmailAddresses_atSubst'     : 'reserved',
-       'spamProtectEmailAddresses_lastDotSubst'        : 'reserved',
-       'special'       : 'reserved',
-       'splitChar'     : 'reserved',
-       'splitRendering'        : 'reserved',
-       'src'   : 'reserved',
-       'startInTaskCenter'     : 'reserved',
-       'stayFolded'    : 'reserved',
-       'stdheader'     : 'reserved',
-       'stdWrap'       : 'reserved',
-       'stdWrap2'      : 'reserved',
-       'strftime'      : 'reserved',
-       'stripHtml'     : 'reserved',
-       'styles'        : 'reserved',
-       'stylesheet'    : 'reserved',
-       'submenuObjSuffixes'    : 'reserved',
-       'subMenuOffset' : 'reserved',
-       'submit'        : 'reserved',
-       'subst_elementUid'      : 'reserved',
-       'substMarksSeparately'  : 'reserved',
-       'substring'     : 'reserved',
-       'swirl' : 'reserved',
-       'sword' : 'reserved',
-       'sword_noMixedCase'     : 'reserved',
-       'SWORD_PARAMS'  : 'reserved',
-       'sword_standAlone'      : 'reserved',
-       'sys_language_mode'     : 'reserved',
-       'sys_language_overlay'  : 'reserved',
-       'sys_language_softMergeIfNotBlank'      : 'reserved',
-       'sys_language_uid'      : 'reserved',
-       'table' : 'reserved',
-       'tableCellColor'        : 'reserved',
-       'tableParams'   : 'reserved',
-       'tables'        : 'reserved',
-       'tableStdWrap'  : 'reserved',
-       'tableStyle'    : 'reserved',
-       'tableWidth'    : 'reserved',
-       'tags'  : 'reserved',
-       'target'        : 'reserved',
-       'TDparams'      : 'reserved',
-       'templateContent'       : 'reserved',
-       'templateFile'  : 'reserved',
-       'text'  : 'reserved',
-       'textarea'      : 'reserved',
-       'textMargin'    : 'reserved',
-       'textMargin_outOfText'  : 'reserved',
-       'textMaxLength' : 'reserved',
-       'textObjNum'    : 'reserved',
-       'textPos'       : 'reserved',
-       'textStyle'     : 'reserved',
-       'thickness'     : 'reserved',
-       'thumbnailsByDefault'   : 'reserved',
-       'tile'  : 'reserved',
-       'time_stdWrap'  : 'reserved',
-       'tipafriendLib' : 'reserved',
-       'title' : 'reserved',
-       'titleLen'      : 'reserved',
-       'titleTagFunction'      : 'reserved',
-       'titleText'     : 'reserved',
-       'tm'    : 'reserved',
-       'token' : 'reserved',
-       'topOffset'     : 'reserved',
-       'totalWidth'    : 'reserved',
-       'transparentBackground' : 'reserved',
-       'transparentColor'      : 'reserved',
-       'trim'  : 'reserved',
-       'tsdebug_tree'  : 'reserved',
-       'type'  : 'reserved',
-       'typeNum'       : 'reserved',
-       'types' : 'reserved',
-       'typolinkCheckRootline' : 'reserved',
-       'uidInList'     : 'reserved',
-       'unset' : 'reserved',
-       'uploadFieldsInTopOfEB' : 'reserved',
-       'uploads'       : 'reserved',
-       'upper' : 'reserved',
-       'useCacheHash'  : 'reserved',
-       'useLargestItemX'       : 'reserved',
-       'useLargestItemY'       : 'reserved',
-       'user'  : 'reserved',
-       'userdefined'   : 'reserved',
-       'userfunction'  : 'reserved',
-       'userid'        : 'reserved',
-       'userIdColumn'  : 'reserved',
-       'USERNAME_substToken'   : 'reserved',
-       'userProc'      : 'reserved',
-       'value' : 'reserved',
-       'valueArray'    : 'reserved',
-       'wave'  : 'reserved',
-       'where' : 'reserved',
-       'width' : 'reserved',
-       'wiz'   : 'reserved',
-       'wordSpacing'   : 'reserved',
-       'workArea'      : 'reserved',
-       'wrap'  : 'reserved',
-       'wrap1' : 'reserved',
-       'wrap2' : 'reserved',
-       'wrap3' : 'reserved',
-       'wrapAfterTags' : 'reserved',
-       'wrapAlign'     : 'reserved',
-       'wrapFieldName' : 'reserved',
-       'wrapItemAndSub'        : 'reserved',
-       'wrapNonWrappedLines'   : 'reserved',
-       'wraps' : 'reserved',
-       'xhtml_cleaning'        : 'reserved',
-       'xmlprologue'   : 'reserved',
-       'xPosOffset'    : 'reserved',
-       'yPosOffset'    : 'reserved',
-       
-       'admPanel'      : 'keyword2',
-       'alt_print'     : 'keyword2',
-       'auth'  : 'keyword2',
-       'browser'       : 'keyword2',
-       'cache' : 'keyword2',
-       'CHECK' : 'keyword2',
-       'cObj'  : 'keyword2',
-       'cObject'       : 'keyword2',
-       'COMMENT'       : 'keyword2',
-       'config'        : 'keyword2',
-       'content'       : 'keyword2',
-       'copy'  : 'keyword2',
-       'CSS_inlineStyle'       : 'keyword2',
-       'cut'   : 'keyword2',
-       'dataArray'     : 'keyword2',
-       'dayofmonth'    : 'keyword2',
-       'dayofweek'     : 'keyword2',
-       'db_list'       : 'keyword2',
-       'device'        : 'keyword2',
-       'dynCSS'        : 'keyword2',
-       'edit'  : 'keyword2',
-       'edit_access'   : 'keyword2',
-       'edit_pageheader'       : 'keyword2',
-       'folder'        : 'keyword2',
-       'folderTree'    : 'keyword2',
-       'foldoutMenu'   : 'keyword2',
-       'Functions'     : 'keyword2',
-       'gmenu_foldout' : 'keyword2',
-       'gmenu_layers'  : 'keyword2',
-       'hostname'      : 'keyword2',
-       'hour'  : 'keyword2',
-       'imgList'       : 'keyword2',
-       'imgResource'   : 'keyword2',
-       'imgText'       : 'keyword2',
-       'info'  : 'keyword2',
-       'IP'    : 'keyword2',
-       'jsmenu'        : 'keyword2',
-       'JSwindow'      : 'keyword2',
-       'LABEL' : 'keyword2',
-       'layout'        : 'keyword2',
-       'lib'   : 'keyword2',
-       'loginUser'     : 'keyword2',
-       'marks' : 'keyword2',
-       'minute'        : 'keyword2',
-       'mod'   : 'keyword2',
-       'module'        : 'keyword2',
-       'month' : 'keyword2',
-       'move_wizard'   : 'keyword2',
-       'new'   : 'keyword2',
-       'new_wizard'    : 'keyword2',
-       'noResultObj'   : 'keyword2',
-       'numRows'       : 'keyword2',
-       'options'       : 'keyword2',
-       'page'  : 'keyword2',
-       'pageTree'      : 'keyword2',
-       'paste' : 'keyword2',
-       'perms' : 'keyword2',
-       'PIDinRootline' : 'keyword2',
-       'PIDupinRootline'       : 'keyword2',
-       'plugin'        : 'keyword2',
-       'postform'      : 'keyword2',
-       'postform_newThread'    : 'keyword2',
-       'preview'       : 'keyword2',
-       'publish'       : 'keyword2',
-       'RADIO' : 'keyword2',
-       'renderObj'     : 'keyword2',
-       'REQ'   : 'keyword2',
-       'RTE'   : 'keyword2',
-       'RTE_compliant' : 'keyword2',
-       'select'        : 'keyword2',
-       'setup' : 'keyword2',
-       'split' : 'keyword2',
-       'stat'  : 'keyword2',
-       'stat_apache'   : 'keyword2',
-       'stat_apache_logfile'   : 'keyword2',
-       'stat_apache_noHost'    : 'keyword2',
-       'stat_apache_notExtended'       : 'keyword2',
-       'stat_apache_pagenames' : 'keyword2',
-       'stat_excludeBEuserHits'        : 'keyword2',
-       'stat_excludeIPList'    : 'keyword2',
-       'stat_mysql'    : 'keyword2',
-       'stat_titleLen' : 'keyword2',
-       'stat_typeNumList'      : 'keyword2',
-       'stdWrap'       : 'keyword2',
-       'subparts'      : 'keyword2',
-       'system'        : 'keyword2',
-       'temp'  : 'keyword2',
-       'template'      : 'keyword2',
-       'treeLevel'     : 'keyword2',
-       'tsdebug'       : 'keyword2',
-       'typolink'      : 'keyword2',
-       'url'   : 'keyword2',
-       'useragent'     : 'keyword2',
-       'userFunc'      : 'keyword2',
-       'version'       : 'keyword2',
-       'view'  : 'keyword2',
-       'workOnSubpart' : 'keyword2',
-       
-       'ACT'   : 'keyword3',
-       'ACTIFSUB'      : 'keyword3',
-       'ACTIFSUBRO'    : 'keyword',
-       'ACTRO' : 'keyword3',
-       'all'   : 'keyword3',
-       'arrowACT'      : 'keyword3',
-       'arrowNO'       : 'keyword3',
-       'ascii' : 'keyword3',
-       'atLeast'       : 'keyword3',
-       'atMost'        : 'keyword3',
-       'BE'    : 'keyword3',
-       'be_groups'     : 'keyword3',
-       'be_users'      : 'keyword3',
-       'BOX'   : 'keyword3',
-       'browse'        : 'keyword3',
-       'bullets'       : 'keyword3',
-       'CUR'   : 'keyword3',
-       'CURIFSUB'      : 'keyword3',
-       'CURIFSUBRO'    : 'keyword3',
-       'CURRO' : 'keyword3',
-       'default'       : 'keyword3',
-       'description'   : 'keyword3',
-       'directory'     : 'keyword3',
-       'directReturn'  : 'keyword3',
-       'div'   : 'keyword3',
-       'else'  : 'keyword3',
-       'email' : 'keyword3',
-       'end'   : 'keyword3',
-       'equals'        : 'keyword3',
-       'external'      : 'keyword3',
-       'false' : 'keyword3',
-       'FE'    : 'keyword3',
-       'fe_groups'     : 'keyword3',
-       'fe_users'      : 'keyword3',
-       'feadmin'       : 'keyword3',
-       'header'        : 'keyword3',
-       'html'  : 'keyword3',
-       'id'    : 'keyword3',
-       'if'    : 'keyword3',
-       'ifEmpty'       : 'keyword3',
-       'IFSUB' : 'keyword3',
-       'IFSUBRO'       : 'keyword3',
-       'image' : 'keyword3',
-       'inBranch'      : 'keyword3',
-       'isFalse'       : 'keyword3',
-       'isGreaterThan' : 'keyword3',
-       'isInList'      : 'keyword3',
-       'isLessThan'    : 'keyword3',
-       'isPositive'    : 'keyword3',
-       'isTrue'        : 'keyword3',
-       'keyword3'      : 'keyword3',
-       'language'      : 'keyword3',
-       'leveltitle'    : 'keyword3',
-       'list'  : 'keyword3',
-       'login' : 'keyword3',
-       'mailform'      : 'keyword3',
-       'media' : 'keyword3',
-       'menu'  : 'keyword3',
-       'mod'   : 'keyword3',
-       'multimedia'    : 'keyword3',
-       'negate'        : 'keyword3',
-       'NEW'   : 'keyword3',
-       'NO'    : 'keyword3',
-       'none'  : 'keyword3',
-       'pages' : 'keyword3',
-       'pages_language_overlay'        : 'keyword3',
-       'parseFunc_RTE' : 'keyword3',
-       'pid'   : 'keyword3',
-       'required'      : 'keyword3',
-       'RO'    : 'keyword3',
-       'rootline'      : 'keyword3',
-       'script'        : 'keyword3',
-       'search'        : 'keyword3',
-       'shortcut'      : 'keyword3',
-       'sitemap'       : 'keyword3',
-       'SPC'   : 'keyword3',
-       'splash'        : 'keyword3',
-       'sys_dmail'     : 'keyword3',
-       'sys_domain'    : 'keyword3',
-       'sys_filemounts'        : 'keyword3',
-       'sys_note'      : 'keyword3',
-       'sys_template'  : 'keyword3',
-       'tabel' : 'keyword3',
-       'text'  : 'keyword3',
-       'textpic'       : 'keyword3',
-       'this'  : 'keyword3',
-       'top'   : 'keyword3',
-       'true'  : 'keyword3',
-       'tt_address'    : 'keyword3',
-       'tt_board'      : 'keyword3',
-       'tt_board_list' : 'keyword3',
-       'tt_board_tree' : 'keyword3',
-       'tt_calender'   : 'keyword3',
-       'tt_content'    : 'keyword3',
-       'tt_guest'      : 'keyword3',
-       'tt_news'       : 'keyword3',
-       'tt_poll'       : 'keyword3',
-       'tt_products'   : 'keyword3',
-       'tt_rating'     : 'keyword3',
-       'twice' : 'keyword3',
-       'tx_automaketemplate_pi1'       : 'keyword3',
-       'tx_belog_webinfo'      : 'keyword3',
-       'tx_browserpagetitle'   : 'keyword3',
-       'tx_browserpagetitle_browser_title'     : 'keyword3',
-       'tx_chcforum_pi1'       : 'keyword3',
-       'tx_cms_layout' : 'keyword3',
-       'tx_cms_webinfo_hits'   : 'keyword3',
-       'tx_cms_webinfo_lang'   : 'keyword3',
-       'tx_cms_webinfo_page'   : 'keyword3',
-       'tx_cssstyledcontent_pi1'       : 'keyword3',
-       'tx_dephpot_pi1'        : 'keyword3',
-       'tx_extkey'     : 'keyword3',
-       'tx_extkey_controllers' : 'keyword3',
-       'tx_extkey_login'       : 'keyword3',
-       'tx_extrapagecmoptions' : 'keyword3',
-       'tx_funcwizards_webfunc'        : 'keyword3',
-       'tx_gooffotoboek_pi1'   : 'keyword3',
-       'tx_impexp'     : 'keyword3',
-       'tx_impexp_clickmenu'   : 'keyword3',
-       'tx_impexp_modfunc1'    : 'keyword3',
-       'tx_indexed_search_extparse'    : 'keyword3',
-       'tx_indexedsearch'      : 'keyword3',
-       'tx_indexedsearch_indexer'      : 'keyword3',
-       'tx_indexedsearch_lexer'        : 'keyword3',
-       'tx_indexedsearch_modfunc1'     : 'keyword3',
-       'tx_indexedsearch_modfunc2'     : 'keyword3',
-       'tx_indexedsearch_pihook'       : 'keyword3',
-       'tx_infopagetsconfig_webinfo'   : 'keyword3',
-       'tx_install'    : 'keyword3',
-       'tx_lzgallery_pi1'      : 'keyword3',
-       'tx_mhajaxsearch_pi1'   : 'keyword3',
-       'tx_mhajaxsearch_q'     : 'keyword3',
-       'tx_mhajaxsearch_result'        : 'keyword3',
-       'tx_mhajaxsearch_search'        : 'keyword3',
-       'tx_newloginbox_pi1'    : 'keyword3',
-       'tx_newloginbox_pi3'    : 'keyword3',
-       'tx_open_printlink'     : 'keyword3',
-       'tx_pdfgenerator'       : 'keyword3',
-       'tx_realurl_advanced'   : 'keyword3',
-       'tx_realurl_enable'     : 'keyword3',
-       'tx_realurl_pathsegment'        : 'keyword3',
-       'tx_realurl_pi1'        : 'keyword3',
-       'tx_rlmptmplselector'   : 'keyword3',
-       'tx_rlmptmplselector_pi1'       : 'keyword3',
-       'tx_sochat_pi1' : 'keyword3',
-       'tx_srfeuserregister_pi1'       : 'keyword3',
-       'tx_sv_auth'    : 'keyword3',
-       'tx_sv_authbase'        : 'keyword3',
-       'tx_sysaction'  : 'keyword3',
-       'tx_templavoila_pi1'    : 'keyword3',
-       'tx_terdoc_pi1' : 'keyword3',
-       'tx_ttnews'     : 'keyword3',
-       'tx_ttnews_catmenu'     : 'keyword3',
-       'tx_ttnews_itemsProcFunc'       : 'keyword3',
-       'tx_ttnews_tcemain'     : 'keyword3',
-       'tx_ttnews_treeview='   : 'keyword3',
-       'tx_ttproducts_pi1'     : 'keyword3',
-       'tx_veguestbook_pi1'    : 'keyword3',
-       'tx_version_cm1'        : 'keyword3',
-       'tx_vjchat_chat'        : 'keyword3',
-       'tx_vjchat_pi1' : 'keyword3',
-       'tx_wizardcrpages_webfunc_2'    : 'keyword3',
-       'tx_wizardsortpages_webfunc_2'  : 'keyword3',
-       'tx_wwwebstats4u_pi1'   : 'keyword3',
-       'uid'   : 'keyword3',
-       'uniqueGlobal'  : 'keyword3',
-       'uniqueLocal'   : 'keyword3',
-       'unsetEmpty'    : 'keyword3',
-       'updated'       : 'keyword3',
-       'uploads'       : 'keyword3',
-       'us'    : 'keyword3',
-       'user_task'     : 'keyword3',
-       'USERDEF1'      : 'keyword3',
-       'USERDEF1RO'    : 'keyword3',
-       'USERDEF2'      : 'keyword3',
-       'USERDEF2RO'    : 'keyword3',
-       'usergroup'     : 'keyword3',
-       'USR'   : 'keyword3',
-       'USRRO' : 'keyword3',
-       'web_func'      : 'keyword3',
-       'web_info'      : 'keyword3',
-       'web_layout'    : 'keyword3',
-       'web_list'      : 'keyword3',
-       'web_ts'        : 'keyword',
-       'xhtml_strict'  : 'keyword3',
-       'xhtml_trans'   : 'keyword3',
-       'XY'    : 'keyword3',
-       'ypMenu'        : 'keyword3'
+       '_CSS_DEFAULT_STYLE': 'keyword',
+       '_DEFAULT_PI_VARS': 'keyword',
+       '_GIFBUILDER': 'keyword',
+       '_LOCAL_LANG': 'keyword',
+       'CARRAY': 'keyword',
+       'CASE': 'keyword',
+       'CLEARGIF': 'keyword',
+       'COA': 'keyword',
+       'COA_INT': 'keyword',
+       'COBJ_ARRAY': 'keyword',
+       'COLUMNS': 'keyword',
+       'CONFIG': 'keyword',
+       'CONSTANTS': 'keyword',
+       'CONTENT': 'keyword',
+       'CTABLE': 'keyword',
+       'CType': 'keyword',
+       'DB': 'keyword',
+       'DOCUMENT_BODY': 'keyword',
+       'EDITPANEL': 'keyword',
+       'EFFECT': 'keyword',
+       'FE_DATA': 'keyword',
+       'FE_TABLE': 'keyword',
+       'FEData': 'keyword',
+       'FILE': 'keyword',
+       'FORM': 'keyword',
+       'FRAME': 'keyword',
+       'FRAMESET': 'keyword',
+       'GIFBUILDER': 'keyword',
+       'global': 'keyword',
+       'globalString': 'keyword',
+       'globalVar': 'keyword',
+       'GMENU': 'keyword',
+       'GMENU_FOLDOUT': 'keyword',
+       'GMENU_LAYERS': 'keyword',
+       'GP': 'keyword',
+       'HMENU': 'keyword',
+       'HRULER': 'keyword',
+       'HTML': 'keyword',
+       'IENV': 'keyword',
+       'IMAGE': 'keyword',
+       'IMG_RESOURCE': 'keyword',
+       'IMGMENU': 'keyword',
+       'IMGMENUITEM': 'keyword',
+       'IMGTEXT': 'keyword',
+       'INCLUDE_TYPOSCRIPT': 'keyword',
+       'includeLibs': 'keyword',
+       'JSMENU': 'keyword',
+       'JSMENUITEM': 'keyword',
+       'LIT': 'keyword',
+       'LOAD_REGISTER': 'keyword',
+       'META': 'keyword',
+       'MULTIMEDIA': 'keyword',
+       'OTABLE': 'keyword',
+       'PAGE': 'keyword',
+       'PAGE_TARGET': 'keyword',
+       'PAGE_TSCONFIG_ID': 'keyword',
+       'PAGE_TSCONFIG_IDLIST': 'keyword',
+       'PAGE_TSCONFIG_STR': 'keyword',
+       'PHP_SCRIPT': 'keyword',
+       'PHP_SCRIPT_EXT': 'keyword',
+       'PHP_SCRIPT_INT': 'keyword',
+       'RECORDS': 'keyword',
+       'REMOTE_ADDR': 'keyword',
+       'RESTORE_REGISTER': 'keyword',
+       'RTE': 'keyword',
+       'SEARCHRESULT': 'keyword',
+       'SHARED': 'keyword',
+       'TCAdefaults': 'keyword',
+       'TCEFORM': 'keyword',
+       'TCEMAIN': 'keyword',
+       'TEMPLATE': 'keyword',
+       'TEXT': 'keyword',
+       'TMENU': 'keyword',
+       'TMENU_LAYERS': 'keyword',
+       'TMENUITEM': 'keyword',
+       'TSFE': 'keyword',
+       'USER': 'keyword',
+       'USER_INT': 'keyword',
+       'userFunc': 'keyword',
+
+       '_offset': 'reserved',
+       'absRefPrefix': 'reserved',
+       'accessibility': 'reserved',
+       'accessKey': 'reserved',
+       'addAttributes': 'reserved',
+       'addExtUrlsAndShortCuts': 'reserved',
+       'addItems': 'reserved',
+       'additionalHeaders': 'reserved',
+       'additionalParams': 'reserved',
+       'addParams': 'reserved',
+       'addQueryString': 'reserved',
+       'adjustItemsH': 'reserved',
+       'adjustSubItemsH': 'reserved',
+       'adminPanelStyles': 'reserved',
+       'after': 'reserved',
+       'afterImg': 'reserved',
+       'afterImgLink': 'reserved',
+       'afterImgTagParams': 'reserved',
+       'afterROImg': 'reserved',
+       'afterWrap': 'reserved',
+       'age': 'reserved',
+       'alertPopups': 'reserved',
+       'align': 'reserved',
+       'allow': 'reserved',
+       'allowCaching': 'reserved',
+       'allowedAttribs': 'reserved',
+       'allowedClasses': 'reserved',
+       'allowedCols': 'reserved',
+       'allowEdit': 'reserved',
+       'allowedNewTables': 'reserved',
+       'allowNew': 'reserved',
+       'allowTags': 'reserved',
+       'allowTVlisting': 'reserved',
+       'allSaveFunctions': 'reserved',
+       'allStdWrap': 'reserved',
+       'allWrap': 'reserved',
+       'alternateBgColors': 'reserved',
+       'alternativeSortingField': 'reserved',
+       'alternativeTempPath': 'reserved',
+       'altImgResource': 'reserved',
+       'altLabels': 'reserved',
+       'altTarget': 'reserved',
+       'altText': 'reserved',
+       'altUrl': 'reserved',
+       'altUrl_noDefaultParams': 'reserved',
+       'altWrap': 'reserved',
+       'always': 'reserved',
+       'alwaysActivePIDlist': 'reserved',
+       'alwaysLink': 'reserved',
+       'alwaysShowClickMenuInTopFrame': 'reserved',
+       'andWhere': 'reserved',
+       'angle': 'reserved',
+       'antiAlias': 'reserved',
+       'append': 'reserved',
+       'applyTotalH': 'reserved',
+       'applyTotalW': 'reserved',
+       'archive': 'reserved',
+       'archiveTypoLink': 'reserved',
+       'arrayReturnMode': 'reserved',
+       'arrowACT': 'reserved',
+       'arrowImgParams': 'reserved',
+       'arrowNO': 'reserved',
+       'ATagAfterWrap': 'reserved',
+       'ATagBeforeWrap': 'reserved',
+       'ATagParams': 'reserved',
+       'ATagTitle': 'reserved',
+       'attribute': 'reserved',
+       'autoInsertPID': 'reserved',
+       'autoLevels': 'reserved',
+       'autonumber': 'reserved',
+       'backColor': 'reserved',
+       'background': 'reserved',
+       'badMess': 'reserved',
+       'baseURL': 'reserved',
+       'before': 'reserved',
+       'beforeImg': 'reserved',
+       'beforeImgLink': 'reserved',
+       'beforeImgTagParams': 'reserved',
+       'beforeROImg': 'reserved',
+       'beforeWrap': 'reserved',
+       'begin': 'reserved',
+       'beLoginLinkIPList': 'reserved',
+       'beLoginLinkIPList_login': 'reserved',
+       'beLoginLinkIPList_logout': 'reserved',
+       'bgCol': 'reserved',
+       'bgImg': 'reserved',
+       'blankStrEqFalse': 'reserved',
+       'blur': 'reserved',
+       'bm': 'reserved',
+       'bodyTag': 'reserved',
+       'bodyTagAdd': 'reserved',
+       'bodyTagCObject': 'reserved',
+       'bodyTagMargins': 'reserved',
+       'bodytext': 'reserved',
+       'border': 'reserved',
+       'borderCol': 'reserved',
+       'bordersWithin': 'reserved',
+       'borderThick': 'reserved',
+       'bottomBackColor': 'reserved',
+       'bottomContent': 'reserved',
+       'bottomHeight': 'reserved',
+       'bottomImg': 'reserved',
+       'bottomImg_mask': 'reserved',
+       'br': 'reserved',
+       'brTag': 'reserved',
+       'bullet': 'reserved',
+       'bulletlist': 'reserved',
+       'bytes': 'reserved',
+       'cache_clearAtMidnight': 'reserved',
+       'cache_period': 'reserved',
+       'caption': 'reserved',
+       'caption_stdWrap': 'reserved',
+       'captionAlign': 'reserved',
+       'captionHeader': 'reserved',
+       'captionSplit': 'reserved',
+       'case': 'reserved',
+       'casesensitiveComp': 'reserved',
+       'cellpadding': 'reserved',
+       'cellspacing': 'reserved',
+       'centerImgACT': 'reserved',
+       'centerImgCUR': 'reserved',
+       'centerImgNO': 'reserved',
+       'centerLeftImgACT': 'reserved',
+       'centerLeftImgCUR': 'reserved',
+       'centerLeftImgNO': 'reserved',
+       'centerRightImgACT': 'reserved',
+       'centerRightImgCUR': 'reserved',
+       'centerRightImgNO': 'reserved',
+       'char': 'reserved',
+       'charcoal': 'reserved',
+       'charMapConfig': 'reserved',
+       'check': 'reserved',
+       'class': 'reserved',
+       'classesAnchor': 'reserved',
+       'classesCharacter': 'reserved',
+       'classesImage': 'reserved',
+       'classesParagraph': 'reserved',
+       'classicPageEditMode': 'reserved',
+       'clear': 'reserved',
+       'clearCache': 'reserved',
+       'clearCache_disable': 'reserved',
+       'clearCache_pageGrandParent': 'reserved',
+       'clearCache_pageSiblingChildren': 'reserved',
+       'clearCacheCmd': 'reserved',
+       'clearCacheLevels': 'reserved',
+       'clearCacheOfPages': 'reserved',
+       'clickMenuTimeOut': 'reserved',
+       'clickTitleMode': 'reserved',
+       'clipboardNumberPads': 'reserved',
+       'cMargins': 'reserved',
+       'cObjNum': 'reserved',
+       'collapse': 'reserved',
+       'color': 'reserved',
+       'color1': 'reserved',
+       'color2': 'reserved',
+       'color3': 'reserved',
+       'color4': 'reserved',
+       'colors': 'reserved',
+       'colour': 'reserved',
+       'colPos_list': 'reserved',
+       'colRelations': 'reserved',
+       'cols': 'reserved',
+       'colSpace': 'reserved',
+       'comment_auto': 'reserved',
+       'commentWrap': 'reserved',
+       'compensateFieldWidth': 'reserved',
+       'compX': 'reserved',
+       'compY': 'reserved',
+       'condensedMode': 'reserved',
+       'conf': 'reserved',
+       'constants': 'reserved',
+       'content_from_pid_allowOutsideDomain': 'reserved',
+       'contextMenu': 'reserved',
+       'copyLevels': 'reserved',
+       'count_HMENU_MENUOBJ': 'reserved',
+       'count_menuItems': 'reserved',
+       'count_MENUOBJ': 'reserved',
+       'create': 'reserved',
+       'createFoldersInEB': 'reserved',
+       'crop': 'reserved',
+       'csConv': 'reserved',
+       'CSS_inlineStyle': 'reserved',
+       'current': 'reserved',
+       'curUid': 'reserved',
+       'cWidth': 'reserved',
+       'data': 'reserved',
+       'dataWrap': 'reserved',
+       'date': 'reserved',
+       'date_stdWrap': 'reserved',
+       'datePrefix': 'reserved',
+       'debug': 'reserved',
+       'debugData': 'reserved',
+       'debugFunc': 'reserved',
+       'debugItemConf': 'reserved',
+       'debugRenumberedObject': 'reserved',
+       'default': 'reserved',
+       'defaultAlign': 'reserved',
+       'defaultCmd': 'reserved',
+       'defaultFileUploads': 'reserved',
+       'defaultHeaderType': 'reserved',
+       'defaultOutput': 'reserved',
+       'defaults': 'reserved',
+       'defaultType': 'reserved',
+       'delete': 'reserved',
+       'denyTags': 'reserved',
+       'depth': 'reserved',
+       'DESC': 'reserved',
+       'dimensions': 'reserved',
+       'directionLeft': 'reserved',
+       'directionUp': 'reserved',
+       'disableAdvanced': 'reserved',
+       'disableAllHeaderCode': 'reserved',
+       'disableAltText': 'reserved',
+       'disableBigButtons': 'reserved',
+       'disableCacheSelector': 'reserved',
+       'disableCharsetHeader': 'reserved',
+       'disableCMlayers': 'reserved',
+       'disabled': 'reserved',
+       'disableDelete': 'reserved',
+       'disableDocModuleInAB': 'reserved',
+       'disableDocSelector': 'reserved',
+       'disableHideAtCopy': 'reserved',
+       'disableIconLinkToContextmenu': 'reserved',
+       'disableItems': 'reserved',
+       'disableNewContentElementWizard': 'reserved',
+       'disableNoMatchingValueElement': 'reserved',
+       'disablePageExternalUrl': 'reserved',
+       'disablePrefixComment': 'reserved',
+       'disablePrependAtCopy': 'reserved',
+       'disableSearchBox': 'reserved',
+       'disableSingleTableView': 'reserved',
+       'disableTabInTextarea': 'reserved',
+       'displayActiveOnLoad': 'reserved',
+       'displayContent': 'reserved',
+       'displayFieldIcons': 'reserved',
+       'displayIcons': 'reserved',
+       'displayMessages': 'reserved',
+       'displayQueries': 'reserved',
+       'displayRecord': 'reserved',
+       'displayTimes': 'reserved',
+       'distributeX': 'reserved',
+       'distributeY': 'reserved',
+       'DIV': 'reserved',
+       'doctype': 'reserved',
+       'doctypeSwitch': 'reserved',
+       'doktype': 'reserved',
+       'doNotLinkIt': 'reserved',
+       'doNotShowLink': 'reserved',
+       'doNotStripHTML': 'reserved',
+       'dontCheckPid': 'reserved',
+       'dontFollowMouse': 'reserved',
+       'dontHideOnMouseUp': 'reserved',
+       'dontLinkIfSubmenu': 'reserved',
+       'dontShowPalettesOnFocusInAB': 'reserved',
+       'dontWrapInTable': 'reserved',
+       'doubleBrTag': 'reserved',
+       'doublePostCheck': 'reserved',
+       'dWorkArea': 'reserved',
+       'edge': 'reserved',
+       'edit_docModuleUplaod': 'reserved',
+       'edit_docModuleUpload': 'reserved',
+       'edit_RTE': 'reserved',
+       'edit_showFieldHelp': 'reserved',
+       'edit_wideDocument': 'reserved',
+       'editFieldsAtATime': 'reserved',
+       'editFormsOnPage': 'reserved',
+       'editIcons': 'reserved',
+       'editNoPopup': 'reserved',
+       'editPanel': 'reserved',
+       'elements': 'reserved',
+       'emailMeAtLogin': 'reserved',
+       'emailMess': 'reserved',
+       'emboss': 'reserved',
+       'enable': 'reserved',
+       'encapsLines': 'reserved',
+       'encapsLinesStdWrap': 'reserved',
+       'encapsTagList': 'reserved',
+       'entryLevel': 'reserved',
+       'equalH': 'reserved',
+       'everybody': 'reserved',
+       'excludeDoktypes': 'reserved',
+       'excludeUidList': 'reserved',
+       'expAll': 'reserved',
+       'expand': 'reserved',
+       'explode': 'reserved',
+       'ext': 'reserved',
+       'externalBlocks': 'reserved',
+       'extTarget': 'reserved',
+       'face': 'reserved',
+       'fe_adminLib': 'reserved',
+       'field': 'reserved',
+       'fieldOrder': 'reserved',
+       'fieldRequired': 'reserved',
+       'fields': 'reserved',
+       'fieldWrap': 'reserved',
+       'file': 'reserved',
+       'file1': 'reserved',
+       'file2': 'reserved',
+       'file3': 'reserved',
+       'file4': 'reserved',
+       'file5': 'reserved',
+       'filelink': 'reserved',
+       'filelist': 'reserved',
+       'firstLabel': 'reserved',
+       'firstLabelGeneral': 'reserved',
+       'fixAttrib': 'reserved',
+       'flip': 'reserved',
+       'flop': 'reserved',
+       'foldSpeed': 'reserved',
+       'foldTimer': 'reserved',
+       'fontColor': 'reserved',
+       'fontFile': 'reserved',
+       'fontOffset': 'reserved',
+       'fontSize': 'reserved',
+       'fontSizeMultiplicator': 'reserved',
+       'fontTag': 'reserved',
+       'forceDisplayFieldIcons': 'reserved',
+       'forceDisplayIcons': 'reserved',
+       'forceNoPopup': 'reserved',
+       'forceTemplateParsing': 'reserved',
+       'forceTypeValue': 'reserved',
+       'format': 'reserved',
+       'frame': 'reserved',
+       'frameReloadIfNotInFrameset': 'reserved',
+       'frameSet': 'reserved',
+       'freezeMouseover': 'reserved',
+       'ftu': 'reserved',
+       'function': 'reserved',
+       'gamma': 'reserved',
+       'gapBgCol': 'reserved',
+       'gapLineCol': 'reserved',
+       'gapLineThickness': 'reserved',
+       'gapWidth': 'reserved',
+       'get': 'reserved',
+       'getBorder': 'reserved',
+       'getLeft': 'reserved',
+       'getRight': 'reserved',
+       'globalNesting': 'reserved',
+       'goodMess': 'reserved',
+       'gray': 'reserved',
+       'group': 'reserved',
+       'groupBy': 'reserved',
+       'groupid': 'reserved',
+       'header': 'reserved',
+       'header_layout': 'reserved',
+       'headerComment': 'reserved',
+       'headerData': 'reserved',
+       'headerSpace': 'reserved',
+       'headTag': 'reserved',
+       'height': 'reserved',
+       'helpText': 'reserved',
+       'hidden': 'reserved',
+       'hiddenFields': 'reserved',
+       'hide': 'reserved',
+       'hideButCreateMap': 'reserved',
+       'hideMenuTimer': 'reserved',
+       'hideMenuWhenNotOver': 'reserved',
+       'hidePStyleItems': 'reserved',
+       'hideRecords': 'reserved',
+       'hideSubmoduleIcons': 'reserved',
+       'highColor': 'reserved',
+       'history': 'reserved',
+       'hover': 'reserved',
+       'hoverStyle': 'reserved',
+       'HTMLparser': 'reserved',
+       'HTMLparser_tags': 'reserved',
+       'htmlSpecialChars': 'reserved',
+       'htmlTag_dir': 'reserved',
+       'htmlTag_langKey': 'reserved',
+       'htmlTag_setParams': 'reserved',
+       'http': 'reserved',
+       'icon': 'reserved',
+       'icon_image_ext_list': 'reserved',
+       'icon_link': 'reserved',
+       'iconCObject': 'reserved',
+       'ifEmpty': 'reserved',
+       'image': 'reserved',
+       'image_compression': 'reserved',
+       'image_effects': 'reserved',
+       'image_frames': 'reserved',
+       'imageLinkWrap': 'reserved',
+       'imagePath': 'reserved',
+       'images': 'reserved',
+       'imageWrapIfAny': 'reserved',
+       'imgList': 'reserved',
+       'imgMap': 'reserved',
+       'imgMapExtras': 'reserved',
+       'imgMax': 'reserved',
+       'imgNameNotRandom': 'reserved',
+       'imgNamePrefix': 'reserved',
+       'imgObjNum': 'reserved',
+       'imgParams': 'reserved',
+       'imgPath': 'reserved',
+       'imgStart': 'reserved',
+       'import': 'reserved',
+       'inc': 'reserved',
+       'includeCSS': 'reserved',
+       'includeLibrary': 'reserved',
+       'includeNotInMenu': 'reserved',
+       'incT3Lib_htmlmail': 'reserved',
+       'index': 'reserved',
+       'index_descrLgd': 'reserved',
+       'index_enable': 'reserved',
+       'index_externals': 'reserved',
+       'inlineStyle2TempFile': 'reserved',
+       'innerStdWrap': 'reserved',
+       'innerStdWrap_all': 'reserved',
+       'innerWrap': 'reserved',
+       'innerWrap2': 'reserved',
+       'input': 'reserved',
+       'inputLevels': 'reserved',
+       'insertClassesFromRTE': 'reserved',
+       'insertData': 'reserved',
+       'insertDmailerBoundaries': 'reserved',
+       'intensity': 'reserved',
+       'intTarget': 'reserved',
+       'intval': 'reserved',
+       'invert': 'reserved',
+       'IProcFunc': 'reserved',
+       'itemArrayProcFunc':