Added feature #9670: Integrate code-completion for TypoScript in the t3editor
authorOliver Hader <oliver.hader@typo3.org>
Wed, 12 Nov 2008 19:08:25 +0000 (19:08 +0000)
committerOliver Hader <oliver.hader@typo3.org>
Wed, 12 Nov 2008 19:08:25 +0000 (19:08 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@4460 709f56b5-9817-0410-a4d7-c38de5d9e867

16 files changed:
ChangeLog
NEWS.txt
typo3/sysext/t3editor/class.tx_t3editor.php
typo3/sysext/t3editor/css/t3editor.css
typo3/sysext/t3editor/ext_emconf.php
typo3/sysext/t3editor/ext_localconf.php
typo3/sysext/t3editor/ext_tables.php
typo3/sysext/t3editor/jslib/t3editor.js
typo3/sysext/t3editor/jslib/ts_codecompletion/completionresult.js [new file with mode: 0644]
typo3/sysext/t3editor/jslib/ts_codecompletion/descriptionPlugin.js [new file with mode: 0644]
typo3/sysext/t3editor/jslib/ts_codecompletion/tscodecompletion.js [new file with mode: 0644]
typo3/sysext/t3editor/jslib/ts_codecompletion/tsparser.js [new file with mode: 0644]
typo3/sysext/t3editor/jslib/ts_codecompletion/tsref.js [new file with mode: 0644]
typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_codecompletion.php [new file with mode: 0644]
typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php [new file with mode: 0644]
typo3/sysext/t3editor/tsref/tsref.xml [new file with mode: 0644]

index b8f4147..6cbe62c 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@
        * Added feature #9778: Improvement of removeXSS (thanks to Steffen Kamper, David Slayback)
        * Fixed bug #9748: Some extensions do not work anymore in the frontend
        * Fixed bug #9639: DB Analyzer / Compare Tool can't handle the upgrade of the cache tables (thanks to Michael Stucki)
+       * Added feature #9670: Integrate code-completion for TypoScript in the t3editor (thanks to Stephan Petzl, Christian Kartnig and Tobias Liebig)
 
 2008-11-11  Steffen Kamper  <info@sk-typo3.de>
 
index a8787bb..b9cb934 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -21,6 +21,9 @@ Backend
          prevent updates for this extension. This is very useful if you made local changes
          to an extension and don't want any admin to overwrite them.
 
+       * The TypoScript editor "t3editor" was enhanced with code-completion. Now you get
+         context-sensitive suggestions about possible properties while entering TypoScript.
+
 Frontend
 ========
 
index c392259..60e1e9c 100755 (executable)
@@ -138,13 +138,18 @@ class tx_t3editor {
                                // include editor-js-lib
                        $doc->loadJavascriptLib($path_t3e . 'jslib/codemirror/codemirror.js');
                        $doc->loadJavascriptLib($path_t3e . 'jslib/t3editor.js');
-
+                       
+                       $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tsref.js');
+                       $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/completionresult.js');
+                       $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tsparser.js');
+                       $doc->loadJavascriptLib($path_t3e . 'jslib/ts_codecompletion/tscodecompletion.js');
+                       
                        // set correct path to the editor
-                       $code.= '<script type="text/javascript">' .
-                               'PATH_t3e = "' .
-                               $GLOBALS['BACK_PATH'] . t3lib_extmgm::extRelPath('t3editor') . '"; ' .
-                               '</script>';
-
+                       
+                       $code.= t3lib_div::wrapJS(
+                               'var PATH_t3e = "' . $GLOBALS['BACK_PATH'] . t3lib_extmgm::extRelPath('t3editor') . '"; ' .
+                               'var URL_typo3 = "' . htmlspecialchars(t3lib_div::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir) . '"; '
+                       );
                }
 
                return $code;
@@ -416,6 +421,27 @@ class tx_t3editor {
                }
                return $savingsuccess;
        }
+       
+       /**
+        * Gets plugins that are defined at $TYPO3_CONF_VARS']['EXTCONF']['t3editor']['plugins']
+        * (called by typo3/ajax.php)
+        *
+        * @param       array           $params: additional parameters (not used here)
+        * @param       TYPO3AJAX       &$ajaxObj: the TYPO3AJAX object of this request
+        * @return      void
+        * @author      Oliver Hader <oliver@typo3.org>
+        */
+       public function getPlugins($params, TYPO3AJAX &$ajaxObj) {
+               $result = array();
+               $plugins =& $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['t3editor']['plugins'];
+
+               if (is_array($plugins)) {
+                       $result = array_values($plugins);
+               }
+
+               $ajaxObj->setContent($result);
+               $ajaxObj->setContentFormat('jsonbody');
+       }
 }
 
 
index d0b271d..a87eafe 100755 (executable)
@@ -1,4 +1,60 @@
-
+.TSREF_type_label, .TSREF_description_label{
+  font-weight: bold;
+}
+.t3e_codeCompleteBox ul li span.word_definedTSREFProperty {
+  color:#DF4E00;
+  font-size:0.95em;
+  font-weight:bold;
+}
+.t3e_codeCompleteBox ul li span.word_undefinedTSREFProperty {
+  color:#FF8400;
+  font-size:0.95em;
+  font-weight:bold;
+}
+.t3e_codeCompleteBox ul li span.word_userProperty {
+  color:#7c7c7c;
+  font-size:0.95em;
+  font-weight:bold;
+}
+.t3e_toolbar{
+  position:absolute;
+  right:50px;
+  top:0pt;
+  width:200px;
+  /*border: 1px solid #CCCCCC;*/
+}
+.t3e_toolbar_icon{
+  border: 1px solid #CCCCCC; 
+  width: 20px; 
+  height: 20px; 
+  float: left;
+}
+.t3e_codeCompleteBox {
+       position: absolute;
+       top: 0; left: 0;
+    background-color: #EFEFF4;
+       z-index:190;    
+       border:2px solid silver;
+       padding:0px;
+}
+.t3e_codeCompleteBox ul{
+       list-style-type: none;
+       padding:0px;
+       margin:0px;
+       
+}
+.t3e_codeCompleteBox ul li{
+       padding-left:2px;
+       padding-right:2px;
+       font-weight:bold;
+       cursor: pointer; cursor: hand;
+}
+.t3e_codeCompleteBox ul li.active{
+       padding-left:2px;
+       padding-right:2px;
+       font-weight:bold;
+       background-color: #cfcfcf;
+}
 /* around the editor */
 .t3e_wrap {
        border: 1px solid gray;
 
 .t3e_footeritem_active {
        background-color: #cfcfcf;
-}
\ No newline at end of file
+}
index 67bbe7a..8db46bd 100755 (executable)
@@ -3,7 +3,7 @@
 ########################################################################
 # Extension Manager/Repository config file for ext: "t3editor"
 #
-# Auto generated 23-04-2008 11:04
+# Auto generated 12-11-2008 01:51
 #
 # Manual updates:
 # Only the data in the array - anything else is removed by next write.
@@ -12,7 +12,7 @@
 
 $EM_CONF[$_EXTKEY] = array(
        'title' => 'Editor with syntax highlighting',
-       'description' => 'JavaScript-driven editor with syntax highlighting for TS and more. Based on CodeMirror.',
+       'description' => 'JavaScript-driven editor with syntax highlighting and codecompletion for TS. Based on CodeMirror.',
        'category' => 'be',
        'shy' => 0,
        'dependencies' => '',
@@ -27,13 +27,13 @@ $EM_CONF[$_EXTKEY] = array(
        'modify_tables' => '',
        'clearCacheOnLoad' => 0,
        'lockType' => '',
-       'author' => 'Tobias Liebig',
-       'author_email' => 'mail_typo3@etobi.de',
+       'author' => 'Tobias Liebig, Stephan Petzl, Christian Kartnig',
+       'author_email' => 'mail_typo3@etobi.de, spetzl@gmx.at, office@hahnepeter.de',
        'author_company' => '',
        'CGLcompliance' => '',
        'CGLcompliance_note' => '',
-       'version' => '0.0.10',
-       '_md5_values_when_last_written' => 'a:29:{s:7:"LICENSE";s:4:"d8dd";s:21:"class.tx_t3editor.php";s:4:"c33a";s:17:"ext_localconf.php";s:4:"dc97";s:23:"icons/loader_eeeeee.gif";s:4:"83a4";s:13:"jslib/LICENSE";s:4:"d835";s:24:"jslib/parsejavascript.js";s:4:"c0dd";s:24:"jslib/parsetyposcript.js";s:4:"5f84";s:15:"jslib/select.js";s:4:"7224";s:21:"jslib/stringstream.js";s:4:"3c02";s:17:"jslib/t3editor.js";s:4:"3c88";s:27:"jslib/tokenizejavascript.js";s:4:"7c98";s:27:"jslib/tokenizetyposcript.js";s:4:"d335";s:13:"jslib/util.js";s:4:"d2a9";s:24:"jslib/codemirror/LICENSE";s:4:"2c10";s:23:"jslib/codemirror/README";s:4:"e540";s:30:"jslib/codemirror/codemirror.js";s:4:"8729";s:26:"jslib/codemirror/editor.js";s:4:"1e72";s:35:"jslib/codemirror/parsejavascript.js";s:4:"23f6";s:35:"jslib/codemirror/parsetyposcript.js";s:4:"4808";s:28:"jslib/codemirror/parsexml.js";s:4:"276a";s:41:"jslib/codemirror/patch.codemirror055.diff";s:4:"50ce";s:26:"jslib/codemirror/select.js";s:4:"6b76";s:32:"jslib/codemirror/stringstream.js";s:4:"665b";s:38:"jslib/codemirror/tokenizejavascript.js";s:4:"7ea7";s:38:"jslib/codemirror/tokenizetyposcript.js";s:4:"b51d";s:24:"jslib/codemirror/undo.js";s:4:"e078";s:24:"jslib/codemirror/util.js";s:4:"8d3e";s:16:"css/t3editor.css";s:4:"f82e";s:22:"css/t3editor_inner.css";s:4:"450b";}',
+       'version' => '0.0.11',
+       '_md5_values_when_last_written' => 'a:30:{s:7:"LICENSE";s:4:"d8dd";s:21:"class.tx_t3editor.php";s:4:"62e4";s:17:"ext_localconf.php";s:4:"5241";s:14:"ext_tables.php";s:4:"7918";s:17:"jslib/t3editor.js";s:4:"88e1";s:24:"jslib/codemirror/LICENSE";s:4:"2c10";s:23:"jslib/codemirror/README";s:4:"e540";s:30:"jslib/codemirror/codemirror.js";s:4:"8729";s:26:"jslib/codemirror/editor.js";s:4:"1e72";s:35:"jslib/codemirror/parsejavascript.js";s:4:"23f6";s:35:"jslib/codemirror/parsetyposcript.js";s:4:"4808";s:28:"jslib/codemirror/parsexml.js";s:4:"276a";s:41:"jslib/codemirror/patch.codemirror055.diff";s:4:"50ce";s:26:"jslib/codemirror/select.js";s:4:"6b76";s:32:"jslib/codemirror/stringstream.js";s:4:"665b";s:38:"jslib/codemirror/tokenizejavascript.js";s:4:"7ea7";s:38:"jslib/codemirror/tokenizetyposcript.js";s:4:"43b8";s:24:"jslib/codemirror/undo.js";s:4:"e078";s:24:"jslib/codemirror/util.js";s:4:"b96d";s:43:"jslib/ts_codecompletion/completionresult.js";s:4:"114a";s:44:"jslib/ts_codecompletion/descriptionPlugin.js";s:4:"5c6e";s:43:"jslib/ts_codecompletion/tscodecompletion.js";s:4:"82d6";s:35:"jslib/ts_codecompletion/tsparser.js";s:4:"aa5a";s:32:"jslib/ts_codecompletion/tsref.js";s:4:"ef55";s:16:"css/t3editor.css";s:4:"22bd";s:22:"css/t3editor_inner.css";s:4:"a33f";s:23:"icons/loader_eeeeee.gif";s:4:"83a4";s:15:"tsref/tsref.xml";s:4:"303c";s:58:"lib/ts_codecompletion/class.tx_t3editor_codecompletion.php";s:4:"8051";s:55:"lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php";s:4:"f905";}',
        'constraints' => array(
                'depends' => array(
                        'php' => '5.1.0-0.0.0',
index 92a99d7..a4ee6e9 100644 (file)
@@ -1,8 +1,7 @@
 <?php
 if (!defined ('TYPO3_MODE'))   die ('Access denied.');
 
-
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'][] = 'EXT:t3editor/class.tx_t3editor.php:&tx_t3editor->preStartPageHook';
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postOutputProcessingHook'][] = 'EXT:t3editor/class.tx_t3editor.php:&tx_t3editor->postOutputProcessingHook';
-
- ?>
+// Define hooks:
+$TYPO3_CONF_VARS['SC_OPTIONS']['typo3/template.php']['preStartPageHook'][] = 'EXT:t3editor/class.tx_t3editor.php:&tx_t3editor->preStartPageHook';
+$TYPO3_CONF_VARS['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postOutputProcessingHook'][] = 'EXT:t3editor/class.tx_t3editor.php:&tx_t3editor->postOutputProcessingHook';
+?>
\ No newline at end of file
index 23011d3..1e3c3f2 100644 (file)
@@ -1,14 +1,14 @@
 <?php
-
 if (!defined('TYPO3_MODE')) {
        die('Access denied.');
 }
 
 if (TYPO3_MODE == 'BE') {
-       $t3editorPath = t3lib_extMgm::extPath('t3editor');
-
-       // register AJAX calls
-       $GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']['tx_t3editor::saveCode'] = $t3editorPath . 'class.tx_t3editor.php:tx_t3editor->saveCode';
+       // Register AJAX handlers:
+       $TYPO3_CONF_VARS['BE']['AJAX']['tx_t3editor::saveCode'] = 'EXT:t3editor/class.tx_t3editor.php:tx_t3editor->saveCode';
+       $TYPO3_CONF_VARS['BE']['AJAX']['tx_t3editor::getPlugins'] = 'EXT:t3editor/class.tx_t3editor.php:tx_t3editor->getPlugins';
+       $TYPO3_CONF_VARS['BE']['AJAX']['tx_t3editor_TSrefLoader::getTypes'] = 'EXT:t3editor/lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php:tx_t3editor_TSrefLoader->processAjaxRequest';
+       $TYPO3_CONF_VARS['BE']['AJAX']['tx_t3editor_TSrefLoader::getDescription'] = 'EXT:t3editor/lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php:tx_t3editor_TSrefLoader->processAjaxRequest';
+       $TYPO3_CONF_VARS['BE']['AJAX']['tx_t3editor_codecompletion::loadTemplates'] = 'EXT:t3editor/lib/ts_codecompletion/class.tx_t3editor_codecompletion.php:tx_t3editor_codecompletion->processAjaxRequest';
 }
-
 ?>
\ No newline at end of file
index 8a63e65..c4ca487 100755 (executable)
@@ -139,7 +139,7 @@ function T3editor(textarea) {
 
                // get the editor
        this.mirror = new CodeMirror(this.mirror_wrap, options);
-
+        this.tsCodeCompletion = new TsCodeCompletion(this.mirror,this.outerdiv);
 }
 
 T3editor.prototype = {
@@ -160,7 +160,9 @@ T3editor.prototype = {
                        this.saveButtons.each(function(button) {
                                Event.observe(button,'click',this.saveFunctionEvent);
                        }.bind(this));
-
+                        Event.observe(this.mirror.win.document, 'keyup', this.tsCodeCompletion.keyUp);
+                        Event.observe(this.mirror.win.document, 'keydown', this.tsCodeCompletion.keyDown);
+                        Event.observe(this.mirror.win.document, 'click', this.tsCodeCompletion.click);
                        this.resize(textareaDim.width, textareaDim.height );
                },
        
@@ -245,7 +247,7 @@ T3editor.prototype = {
                        params = Object.extend( { ajaxID: 'tx_t3editor::saveCode' }, params);
                        
                        new Ajax.Request(
-                               (top && top.TS ? top.TS.PATH_typo3 : PATH_t3e + '../../' ) + 'ajax.php', { 
+                               URL_typo3 + 'ajax.php', {
                                        parameters: params,
                                        onComplete: this.saveFunctionComplete.bind(this)
                                }
diff --git a/typo3/sysext/t3editor/jslib/ts_codecompletion/completionresult.js b/typo3/sysext/t3editor/jslib/ts_codecompletion/completionresult.js
new file mode 100644 (file)
index 0000000..fcff806
--- /dev/null
@@ -0,0 +1,112 @@
+/***************************************************************\r
+* Copyright notice\r
+*\r
+* (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de> \r
+* All rights reserved\r
+*\r
+* This script is part of the TYPO3 project. The TYPO3 project is\r
+* free software; you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation; either version 2 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* The GNU General Public License can be found at\r
+* http://www.gnu.org/copyleft/gpl.html.\r
+* A copy is found in the textfile GPL.txt and important notices to the license\r
+* from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+* This script is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * @fileoverview contains the CompletionResult class \r
+ */ \r
+\r
+/** \r
+ * @class this class post-processes the result from the codecompletion, so that it can be\r
+ * displayed in the next step.\r
+ * @constructor\r
+ * @param tsRef the TsRef Tree\r
+ * @param tsTreeNode the current Node in the codetree built by the parser\r
+ * @return a new CompletionResult instance                     \r
+ */\r
+var CompletionResult = function(tsRef,tsTreeNode) {\r
+       var currentTsTreeNode = tsTreeNode;\r
+       var tsRef = tsRef;\r
+\r
+       /**\r
+        * returns the type of the currentTsTreeNode\r
+        */\r
+       this.getType = function() {\r
+               var val = currentTsTreeNode.getValue();\r
+               if (tsRef.isType(val)) {\r
+                       return tsRef.getType(val);\r
+               } else {\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * returns a list of possible path completions (proposals), which is:\r
+        * a list of the children of the current TsTreeNode (= userdefined properties)\r
+        * and a list of properties allowed for the current object in the TsRef\r
+        * remove all words from list that don't start with the string in filter\r
+        * @param {String} filter beginning of the words contained in the proposal list\r
+        * @returns an Array of Proposals\r
+        */\r
+       this.getFilteredProposals = function(filter) {\r
+\r
+                       var defined = new Array();\r
+                       var propArr = new Array();\r
+                       var childNodes = currentTsTreeNode.getChildNodes();\r
+\r
+                       // first get the childNodes of the Node (=properties defined by the user)\r
+                       for (key in childNodes) {\r
+                               if (typeof(childNodes[key].value) == "string") {\r
+                                       propObj = new Object();\r
+                                       propObj.word = key;\r
+                                       if (childNodes[key].tsrefProperty) {\r
+                                               propObj.cssClass = 'definedTSREFProperty';\r
+                                               propObj.type = childNodes[key].value;\r
+                                       } else {\r
+                                               propObj.cssClass = 'userProperty';\r
+                                               if (tsRef.isType(childNodes[key].value)) {\r
+                                                       propObj.type = childNodes[key].value;\r
+                                               } else {\r
+                                                       propObj.type = '';\r
+                                               }\r
+                                       }\r
+                                       propArr.push(propObj);\r
+                                       defined[key] = true;\r
+                               }\r
+                       }\r
+\r
+                       // then get the tsref properties\r
+                       var props = tsRef.getPropertiesFromTypeId(currentTsTreeNode.getValue());\r
+                       for (key in props) {\r
+                       // show just the TSREF properties - no properties of the array-prototype and no properties which have been defined by the user\r
+                               if (props[key].value != null && !defined[key]) {\r
+                                       propObj = new Object();\r
+                                       propObj.word = key;\r
+                                       propObj.cssClass = 'undefinedTSREFProperty';\r
+                                       propObj.type = props[key].value;\r
+                                       propArr.push(propObj);\r
+                               }\r
+                       }\r
+\r
+                       var result = [];\r
+                       var wordBeginning = "";\r
+                       for (var i=0; i < propArr.length;i++) {\r
+                               wordBeginning = propArr[i].word.substring(0, filter.length);\r
+                               if (filter == "" || filter == null || wordBeginning == filter) {\r
+                                       result.push(propArr[i]);\r
+                               }\r
+                       }\r
+                       return result;\r
+       }\r
+}\r
diff --git a/typo3/sysext/t3editor/jslib/ts_codecompletion/descriptionPlugin.js b/typo3/sysext/t3editor/jslib/ts_codecompletion/descriptionPlugin.js
new file mode 100644 (file)
index 0000000..ba09f2e
--- /dev/null
@@ -0,0 +1,98 @@
+/***************************************************************\r
+* Copyright notice\r
+*\r
+* (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de> \r
+* All rights reserved\r
+*\r
+* This script is part of the TYPO3 project. The TYPO3 project is\r
+* free software; you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation; either version 2 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* The GNU General Public License can be found at\r
+* http://www.gnu.org/copyleft/gpl.html.\r
+* A copy is found in the textfile GPL.txt and important notices to the license\r
+* from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+* This script is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+\r
+/**\r
+ * @class Descriptionbox plugin for the t3editor-codecompletion which displays the datatype \r
+ * and the desciption for each property displayed in the completionbox\r
+ * @constructor\r
+ * @return A new DescriptionPlugin instance    \r
+ **/\r
+\r
+var DescriptionPlugin = function(){\r
+       var outerdiv;\r
+       var descriptionBox;\r
+       var completionBox;\r
+       var tsRef;\r
+       var pluginMeta;\r
+\r
+       this.init = function(pluginContext,plugin) {\r
+               pluginMeta = plugin;\r
+               outerdiv = pluginContext.outerdiv;\r
+               completionBox = pluginContext.codeCompleteBox;\r
+               tsRef = pluginContext.tsRef;\r
+               descriptionBox = new Element("DIV", {"class": "t3e_codeCompleteBox"});\r
+               descriptionBox.hide();\r
+               outerdiv.appendChild(descriptionBox);\r
+       }\r
+       this.afterKeyDown = function(currWordObj,compResult) {\r
+               refreshBox(currWordObj,compResult);\r
+       }\r
+       this.afterKeyUp = function(currWordObj,compResult) {\r
+               refreshBox(currWordObj,compResult);\r
+       }\r
+       this.afterCCRefresh = function(currWordObj,compResult) {\r
+               refreshBox(currWordObj,compResult);\r
+       }\r
+       function descriptionLoaded(desc) {\r
+               $('TSREF_description').innerHTML        = desc;\r
+       }\r
+\r
+       function refreshBox(proposalObj,compResult) {\r
+               var type = compResult.getType();\r
+\r
+               if (type && type.properties[proposalObj.word]) {\r
+                       // first a container has to be built\r
+                       descriptionBox.innerHTML = '<div class="TSREF_type_label">TSREF-type: </div><div class="TSREF_type">'+type.typeId+'->'+proposalObj.type+'</div><br/>';\r
+                       descriptionBox.innerHTML += '<div class="TSREF_description_label">TSREF-description:</div><div id="TSREF_description"><img src="../../../gfx/spinner.gif" border="0" alt="one moment please..."/></div>';\r
+                       //window.clearTimeout(this.lastTimeoutId);\r
+                       // then the desciption can be loaded and inserted into the container\r
+                       this.lastTimeoutId = type.properties[proposalObj.word].getDescription(descriptionLoaded);\r
+                       descriptionBox.show();\r
+               } else if (proposalObj.type) {\r
+                       descriptionBox.innerHTML = '<div class="TSREF_type_label">TSREF-type: </div><div class="TSREF_type">'+proposalObj.type+'</div><br/>';\r
+                       descriptionBox.show();\r
+               } else {\r
+                       descriptionBox.innerHTML = '';\r
+                       descriptionBox.hide();\r
+               }\r
+\r
+\r
+               descriptionBox.scrollTop = 0;\r
+               descriptionBox.style.overflowY = 'scroll';\r
+               descriptionBox.style.height = completionBox.getStyle('height');\r
+               descriptionBox.style.width = '200px';\r
+               var leftOffset = parseInt(completionBox.getStyle('left').gsub('px','')) + parseInt(completionBox.getStyle('width').gsub('px','')) + 5;\r
+               leftOffset += 'px';\r
+               descriptionBox.setStyle({\r
+                       top: completionBox.getStyle('top'),\r
+                       left: leftOffset\r
+               });\r
+       }\r
+\r
+       this.endCodeCompletion = function() {\r
+               descriptionBox.hide();\r
+       }\r
+}\r
diff --git a/typo3/sysext/t3editor/jslib/ts_codecompletion/tscodecompletion.js b/typo3/sysext/t3editor/jslib/ts_codecompletion/tscodecompletion.js
new file mode 100644 (file)
index 0000000..759f9f6
--- /dev/null
@@ -0,0 +1,606 @@
+/***************************************************************\r
+* Copyright notice\r
+*\r
+* (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de> \r
+* All rights reserved\r
+*\r
+* This script is part of the TYPO3 project. The TYPO3 project is\r
+* free software; you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation; either version 2 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* The GNU General Public License can be found at\r
+* http://www.gnu.org/copyleft/gpl.html.\r
+* A copy is found in the textfile GPL.txt and important notices to the license\r
+* from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+* This script is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+\r
+/**\r
+ * @fileoverview contains the TsCodeCompletion class\r
+ */\r
+\r
+/**\r
+ * Construct a new TsCodeCompletion object.\r
+ * @class This is the main class of the codeCompletion.\r
+ * it is directly invoked by the editor. It instantiates all other classes\r
+ * manages the control flow and takes care of the completionbox\r
+ *\r
+ * @constructor\r
+ * @param codeMirror codeMirror instance, for retrieving the cursor position\r
+ * @param outerdiv div that contains the editor, for DOM manipulation\r
+ * @return A new TsCodeCompletion instance\r
+ */\r
+var TsCodeCompletion = function(codeMirror,outerdiv) {\r
+       // private Vars\r
+       var tsRef       = new TsRef();\r
+       var mirror = codeMirror;\r
+       var options = {ccWords : 10};\r
+       // t3editor index (=0 if there is just one editor on the page, should be set from outside)\r
+       var index = 0;\r
+\r
+       var currWord = 0;\r
+       var cc_up;\r
+       var cc_down;\r
+       var proposals;\r
+       var compResult;\r
+       var cc = 0;\r
+       var filter = "";\r
+       var linefeedsPrepared = false;\r
+       var currentCursorPosition = null;\r
+\r
+       // load the external templates ts-setup into extTsObjTree\r
+       var extTsObjTree = new Object();\r
+       var parser = new TsParser(tsRef,extTsObjTree);\r
+       loadExtTemplatesAsync();\r
+\r
+       // plugin-array will be retrieved through AJAX from the conf array\r
+       // plugins can be attached by regular TYPO3-extensions\r
+       var plugins = [];\r
+\r
+       // we add the description plugin here because its packed with the codecompletion currently\r
+       // maybe we will swap it to an external plugin in future\r
+       var plugin = new Object();\r
+       plugin.extpath = PATH_t3e;\r
+       plugin.classpath =      'jslib/ts_codecompletion/descriptionPlugin.js';\r
+       plugin.classname = 'DescriptionPlugin';\r
+\r
+       plugins.push(plugin);\r
+\r
+\r
+\r
+       // to roll back linebreaks inserted by hitting enter, the current node has to be stored before the codecompletion outside of the eventlistener\r
+       //var nodeBeforeInsert;\r
+\r
+\r
+       var codeCompleteBox = new Element("DIV", {\r
+               "class": "t3e_codeCompleteBox"\r
+       });\r
+       codeCompleteBox.hide();\r
+       outerdiv.appendChild(codeCompleteBox);\r
+\r
+       var toolbardiv = new Element("DIV", {\r
+               "class": "t3e_toolbar"\r
+       });\r
+       toolbardiv.show();\r
+       outerdiv.appendChild(toolbardiv);\r
+\r
+       // load the external xml-reference\r
+       tsRef.loadTsrefAsync();\r
+\r
+       // plugins will be provided with the pluginContext\r
+       var pluginContext = new Object();\r
+       pluginContext.outerdiv = outerdiv;\r
+       pluginContext.codeCompleteBox = codeCompleteBox;\r
+       pluginContext.toolbardiv = toolbardiv;\r
+       pluginContext.tsRef = tsRef;\r
+       pluginContext.parser = parser;\r
+       pluginContext.plugins = plugins;\r
+\r
+       // should we use a pluginmanager so no for loops are required on each hook?\r
+       // e.g. pluginmanager.call('afterKeyUp',....);\r
+       loadPluginArray();\r
+\r
+\r
+       /* loads the array of registered codecompletion plugins\r
+        * to register a plugin you have to add an array to the localconf\r
+        * $TYPO3_CONF_VARS['EXTCONF']['t3editor']['plugins'][] = array( 'extpath' => t3lib_div::getIndpEnv('TYPO3_SITE_URL').t3lib_extMgm::siteRelPath($_EXTKEY),\r
+                                                                                                                               'classpath' => 'js/my_plugin.js',\r
+                                                                                                                               'classname'=> 'MyPlugin');\r
+        */\r
+       function loadPluginArray(){\r
+               var urlParameters = '&ajaxID=tx_t3editor::getPlugins';\r
+               new Ajax.Request(\r
+                       URL_typo3 + 'ajax.php',\r
+                       {\r
+                               parameters: urlParameters,\r
+                               method: 'get',\r
+                               onSuccess: function(transport) {\r
+                                       var loadedPlugins = eval('('+ transport.responseText +')');\r
+                                       plugins = plugins.concat(loadedPlugins);\r
+                                       // register an internal plugin\r
+                                       loadPlugins();\r
+                               }\r
+                       }\r
+               );\r
+       }\r
+       /* instantiates all plugins and adds the instances to the plugin array\r
+       */\r
+       function loadPlugins(){\r
+               for(var i=0;i<plugins.length;i++){\r
+                       var script = document.createElement('script');\r
+                       script.setAttribute('type','text/javascript');\r
+                       script.setAttribute('src',plugins[i].extpath+plugins[i].classpath);\r
+                       document.getElementsByTagName('head')[0].appendChild(script);\r
+                       window.setTimeout(makeInstance.bind(this,plugins[i],i),1000);\r
+               }\r
+       }\r
+       /* makes a single plugin instance\r
+       */\r
+       function makeInstance(plugin,i){\r
+               try{\r
+                       var localname = "plugins[" + i + "].obj";\r
+                       eval(localname+' = new '+plugin.classname+'();');\r
+                       var obj = eval(localname);\r
+                       //console.log("initialized a new "+plugin.classname+" in "+localname);\r
+               }catch(e){\r
+                       throw("error occured while trying to make new instance of \""+plugin.classname+"\"! maybe syntax error or wrong filepath?");\r
+                       return;\r
+               }\r
+               obj.init(pluginContext,plugin);\r
+       }\r
+       /**\r
+        * all external templates along the rootline have to be loaded,\r
+        * this function retrieves the JSON code by comitting a AJAX request\r
+        */\r
+       function loadExtTemplatesAsync(){\r
+               var urlParameters = '&ajaxID=tx_t3editor_codecompletion::loadTemplates&pageId=' + getGetVar('id');\r
+               new Ajax.Request(\r
+                       URL_typo3 + 'ajax.php',\r
+                       {\r
+                               method: 'get',\r
+                               parameters: urlParameters,\r
+                               onSuccess: function(transport) {\r
+                                       extTsObjTree.c = eval('('+ transport.responseText +')');\r
+                                       resolveExtReferencesRec(extTsObjTree.c);\r
+                               }\r
+                       }\r
+               );\r
+       }\r
+\r
+       /**\r
+        * since the references are not resolved server side we have to do it client-side\r
+        * benefit: less loading time due to less data which has to be transmitted\r
+        */\r
+       function resolveExtReferencesRec(childNodes){\r
+               for(var key in childNodes){\r
+                       var childNode;\r
+                       // if the childnode has a value and there is a parto of a reference operator ('<')\r
+                       // and it does not look like a html tag ('>')\r
+                       if(childNodes[key].v && childNodes[key].v[0] == '<' && childNodes[key].v.indexOf('>') == -1 ){\r
+                       var path = childNodes[key].v.replace(/</,"").strip();\r
+                       // if there are still whitespaces its no path\r
+                       if(path.indexOf(' ') == -1){\r
+                               childNode = getExtChildNode(path);\r
+                               // if the node was found - reference it\r
+                               if(childNode != null){\r
+                               childNodes[key] = childNode;\r
+                               }\r
+                       }\r
+                       }\r
+                       // if there was no reference-resolving then we go deeper into the tree\r
+                       if(!childNode && childNodes[key].c){\r
+                       resolveExtReferencesRec(childNodes[key].c);\r
+                       }\r
+               }\r
+       }\r
+\r
+       function getExtChildNode(path){\r
+               var extTree = extTsObjTree;\r
+               var path = path.split('.');\r
+               var pathSeg;\r
+               var i;\r
+               for(i=0;i<path.length;i++){\r
+                       pathSeg = path[i];\r
+                       if(extTree.c == null || extTree.c[pathSeg] == null)\r
+                       return null;\r
+                       extTree = extTree.c[pathSeg];\r
+               }\r
+               return extTree;\r
+       }\r
+\r
+       /**\r
+        * replaces editor functions insertNewlineAtCursor and indentAtCursor\r
+        * with modified ones that only execute when codecompletion box is not shown\r
+        */\r
+       function prepareLinefeeds() {\r
+               mirror.editor.win.select.insertNewlineAtCursor_original = mirror.editor.win.select.insertNewlineAtCursor;\r
+               mirror.editor.win.select.insertNewlineAtCursor = function(window) {\r
+                       if (cc==0) {\r
+                       mirror.editor.win.select.insertNewlineAtCursor_original(window);\r
+                       }\r
+               };\r
+               mirror.editor.indentAtCursor_original = mirror.editor.indentAtCursor;\r
+               mirror.editor.indentAtCursor = function() {\r
+                       if (cc==0) {\r
+                       mirror.editor.indentAtCursor_original();\r
+                       }\r
+               };\r
+               linefeedsPrepared = true;\r
+       }\r
+\r
+       /**\r
+        * Eventhandler function for mouseclicks\r
+        * ends the codecompletion\r
+        * @param event fired prototype event object\r
+        * @type void\r
+        */\r
+       this.click=function(event) {\r
+               endAutoCompletion();\r
+       }\r
+       function getFilter(cursorPosNode){\r
+               //var cursorPosNode = cursor.start.node.parentNode;\r
+                // var filter = cursorPosNode.innerHTML.replace('.','');\r
+               if(cursorPosNode.currentText) {\r
+                       var filter = cursorPosNode.currentText.replace('.','');\r
+                       return filter.replace(/\s/g,"");\r
+               } else {\r
+                       return "";\r
+               }\r
+       }\r
+\r
+       function getCurrentLine(cursor) {\r
+               var line = "";\r
+               var currentNode = cursor.start.node.parentNode;\r
+               while (currentNode.tagName !='BR') {\r
+                       if(currentNode.hasChildNodes() && currentNode.firstChild.nodeType==3 && currentNode.currentText.length>0) {\r
+                       line = currentNode.currentText + line;\r
+                       }\r
+                       if (currentNode.previousSibling == null) {\r
+                       break;\r
+                       } else {\r
+                       currentNode = currentNode.previousSibling;\r
+                       }\r
+               }\r
+               return line;\r
+       }\r
+\r
+       /**\r
+        * Eventhandler function executed after keystroke release\r
+        * triggers CC on pressed dot and typing on\r
+        * @param event fired prototype event object\r
+        * @type void\r
+        */\r
+       this.keyUp = function(event) {\r
+               var keycode = event.keyCode;\r
+               if      (keycode == 190){\r
+                       refreshCodeCompletion();\r
+               }else if(cc == 1){\r
+                       if(keycode != Event.KEY_DOWN && keycode != Event.KEY_UP){\r
+                       refreshCodeCompletion();\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Eventhandler function executed after keystroke release\r
+        * triggers CC on pressed dot and typing on\r
+        * @param event fired prototype event object\r
+        * @type void\r
+        */\r
+       this.keyDown = function(event){\r
+               // prepareLinefeeds() gets called the first time keyDown is executed.\r
+               // we have to put this here, cause in the constructor mirror.editor is not yet loaded\r
+               if (!linefeedsPrepared) {\r
+                       prepareLinefeeds();\r
+               }\r
+               var keycode = event.keyCode;\r
+               if (cc == 1){\r
+                       if (keycode == Event.KEY_UP) {\r
+                                       // arrow up:    move up cursor in codecomplete box\r
+                                       event.stop();\r
+                       codeCompleteBoxMoveUpCursor();\r
+                                       for(var i=0;i<plugins.length;i++){\r
+                               if(plugins[i].obj && plugins[i].obj.afterKeyUp) plugins[i].obj.afterKeyUp(proposals[currWord],compResult);\r
+                       }\r
+                               } else if (keycode == Event.KEY_DOWN) {\r
+                                       // Arrow down: move down cursor in codecomplete box\r
+                                       event.stop();\r
+                       codeCompleteBoxMoveDownCursor();\r
+                       for(var i=0;i<plugins.length;i++){\r
+                               if(plugins[i].obj && plugins[i].obj.afterKeyDown)plugins[i].obj.afterKeyDown(proposals[currWord],compResult);\r
+                       }\r
+                               } else if (keycode == Event.KEY_ESC || keycode == Event.KEY_LEFT || keycode== Event.KEY_RIGHT) {\r
+                                       // Esc, Arrow Left, Arrow Right: if codecomplete box is showing, hide it\r
+                                       endAutoCompletion();\r
+\r
+                               } else if (keycode == Event.KEY_RETURN) {\r
+                                       event.stop();\r
+                                       if (currWord == -1) {\r
+                               endAutoCompletion();\r
+                       } else {\r
+                               insertCurrWordAtCursor();\r
+                               event.stop();\r
+                               endAutoCompletion();\r
+                       }\r
+                               } else if(keycode == 32 && !event.ctrlKey) {\r
+                                       endAutoCompletion();\r
+                       } else if(keycode == 32 && event.ctrlKey) {\r
+                                       refreshCodeCompletion();\r
+                       } else if(keycode == Event.KEY_BACKSPACE) {\r
+                       var cursorNode = mirror.editor.win.select.selectionTopNode(mirror.editor.win.document.body, false);\r
+                       if(cursorNode.innerHTML == '.'){\r
+                               // force full refresh at keyUp\r
+                               compResult = null;\r
+                       }\r
+                       }\r
+                       } else { // if autocompletion is deactivated and ctrl+space is pressed\r
+                       if(keycode == 32 && event.ctrlKey){\r
+                       event.stop();\r
+                                       refreshCodeCompletion();\r
+                       }\r
+\r
+               }\r
+       }\r
+\r
+       function refreshCodeCompletion() {\r
+               // init vars for up/down moving in word list\r
+               cc_up = 0;\r
+               cc_down = options.ccWords-1;\r
+               // clear the last completion wordposition\r
+               currWord = -1;\r
+               mirror.editor.highlightAtCursor();\r
+               // retrieves the node right to the cursor\r
+               var cursorNode = mirror.editor.win.select.selectionTopNode(mirror.editor.win.document.body, false);\r
+\r
+               // cursorNode is null if the cursor is positioned at the beginning of the first line\r
+               if(cursorNode == null)\r
+                       cursorNode = mirror.editor.container.firstChild;\r
+               else if(cursorNode.tagName=='BR') // at the beginning of the line\r
+                       cursorNode = cursorNode.nextSibling;\r
+\r
+                       currentCursorPosition = mirror.editor.win.select.markSelection(mirror.editor.win);\r
+\r
+               // the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active\r
+               //nodeBeforeInsert = cursorNode;\r
+               filter = getFilter(cursorNode);\r
+\r
+               if(compResult == null || cursorNode.innerHTML == '.'){\r
+\r
+                       // TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults())\r
+                       var currentTsTreeNode = parser.buildTsObjTree(mirror.editor.container.firstChild, cursorNode);\r
+                       compResult = new CompletionResult(tsRef,currentTsTreeNode);\r
+               }\r
+\r
+               proposals = compResult.getFilteredProposals(filter);\r
+\r
+               // if proposals are found - show box\r
+               if (proposals.length > 0){\r
+\r
+                       // make UL list of completation proposals\r
+                                               var html = '<ul>';\r
+                                               for (i = 0; i < proposals.length; i++) {\r
+                                                       html += '<li style="height:16px;vertical-align:middle;" ' +\r
+                                                                       'id="cc_word_' + i + '" ' +\r
+                                                                       'onclick="t3e_instances[' + index + '].tsCodeCompletion.insertCurrWordAtCursor(' + i + ');t3e_instances[' + index + '].tsCodeCompletion.endAutoCompletion();" ' +\r
+                                                                       'onmouseover="t3e_instances[' + index + '].tsCodeCompletion.highlightCurrWord(' + i + ');">' +\r
+                                                                       '<span class="word_' + proposals[i].cssClass + '">' +\r
+                                                                       proposals[i].word +\r
+                                                                       '</span></li>';\r
+                                               }\r
+                                               html += '</ul>';\r
+\r
+                                               //put HTML and show box\r
+                                               codeCompleteBox.innerHTML = html;\r
+                                               codeCompleteBox.show();\r
+                                               codeCompleteBox.scrollTop = 0;\r
+\r
+                                               //      init styles\r
+\r
+                                               codeCompleteBox.style.overflowY = 'scroll';\r
+                                               if (Prototype.Browser.Gecko) {\r
+                                                       codeCompleteBox.style.height = (options.ccWords * ($("cc_word_0").offsetHeight)) + 'px';\r
+                                               } else {\r
+                                                       codeCompleteBox.style.height = (options.ccWords * ($("cc_word_0").offsetHeight)) + 4 + 'px';\r
+                                                       codeCompleteBox.style.width = codeCompleteBox.offsetWidth + 20 + 'px';\r
+                                               }\r
+\r
+\r
+                                               var leftpos = (Position.cumulativeOffset($$('.t3e_iframe_wrap')[index])[0] + Position.cumulativeOffset(cursorNode)[0] + cursorNode.offsetWidth) + 'px';\r
+                                                                               var toppos = (Position.cumulativeOffset(cursorNode)[1] + cursorNode.offsetHeight - Element.cumulativeScrollOffset(cursorNode)[1]) + 'px';\r
+                                                                               codeCompleteBox.setStyle({left: leftpos,top:    toppos});\r
+                       // set flag to 1 - needed for continue typing word.\r
+                       cc = 1;\r
+                       // highlight first word in list\r
+                       highlightCurrWord(0);\r
+                       for(var i=0;i<plugins.length;i++){\r
+                               if(plugins[i].obj && plugins[i].obj.afterCCRefresh)plugins[i].obj.afterCCRefresh(proposals[currWord],compResult);\r
+                       }\r
+               } else {\r
+                       endAutoCompletion();\r
+               }\r
+       }\r
+\r
+\r
+\r
+\r
+       /**\r
+        * hides codecomplete box and resets completionResult\r
+        * afterwards the interceptor method endCodeCompletion gets called\r
+        * @type void\r
+        */\r
+       this.endAutoCompletion = function() {\r
+               endAutoCompletion();\r
+       }\r
+       function endAutoCompletion(){\r
+               cc = 0;\r
+               codeCompleteBox.hide();\r
+               // force full refresh\r
+               compResult = null;\r
+               for(var i=0;i<plugins.length;i++){\r
+                       if(plugins[i].obj && plugins[i].obj.endCodeCompletion)plugins[i].obj.endCodeCompletion();\r
+               }\r
+       }\r
+\r
+\r
+       // move cursor in autcomplete box up\r
+       function codeCompleteBoxMoveUpCursor() {\r
+               // if previous position was first or position not initialized - then move cursor to last word, else decrease position\r
+               if (currWord == 0 || currWord == -1) {\r
+                       var id = proposals.length - 1;\r
+               } else {\r
+                       var id = currWord - 1;\r
+               }\r
+               // hightlight new cursor position\r
+               highlightCurrWord(id);\r
+               // update id of first and last showing proposals and scroll box\r
+               if (currWord < cc_up || currWord == (proposals.length - 1)) {\r
+                       cc_up = currWord;\r
+                       cc_down = currWord + (options.ccWords - 1);\r
+                       if (cc_up === proposals.length - 1) {\r
+                               cc_down = proposals.length - 1;\r
+                               cc_up = cc_down - (options.ccWords - 1);\r
+                       }\r
+                       codeCompleteBox.scrollTop = cc_up * 16;\r
+               }\r
+       }\r
+\r
+       //move cursor in codecomplete box down\r
+       function codeCompleteBoxMoveDownCursor() {\r
+               // if previous position was last word in list - then move cursor to first word if not than      position ++\r
+               if (currWord == proposals.length - 1) {\r
+                       var id = 0;\r
+               } else {\r
+                       var id = currWord + 1;\r
+               }\r
+               // highlight new cursor position\r
+               highlightCurrWord(id);\r
+\r
+               // update id of first and last showing proposals and scroll box\r
+               if (currWord > cc_down || currWord == 0) {\r
+                       cc_down = currWord;\r
+                       cc_up = currWord - (options.ccWords - 1);\r
+                       if (cc_down == 0) {\r
+                               cc_up = 0;\r
+                               cc_down = options.ccWords - 1;\r
+                       }\r
+                       codeCompleteBox.scrollTop = cc_up * 16;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * highlights entry in codecomplete box by id\r
+        * @param {int} id\r
+        * @type void\r
+        */\r
+       this.highlightCurrWord = function(id){\r
+       highlightCurrWord(id);\r
+       }\r
+       function highlightCurrWord(id) {\r
+               if (currWord != -1) {\r
+                       $('cc_word_' + currWord).className = '';\r
+               }\r
+               $('cc_word_' + id).className = 'active';\r
+               currWord = id;\r
+       }\r
+\r
+       /**\r
+        * Insert the currently selected item in the proposal list\r
+        * of the codecompletion box into the editor div at cursor position\r
+        * @type void\r
+        * @see #highlightCurrWord\r
+        */\r
+       this.insertCurrWordAtCursor = function(){\r
+               insertCurrWordAtCursor();\r
+       }\r
+       // insert selected word into text from codecompletebox\r
+       function insertCurrWordAtCursor() {\r
+               var word = proposals[currWord].word;\r
+               word = word.substring(filter.length);\r
+                       mirror.win.focus();\r
+                       mirror.editor.win.select.selectMarked(currentCursorPosition);\r
+                       mirror.editor.win.select.insertTextAtCursor(mirror.editor.win, word);\r
+       }\r
+\r
+       /**\r
+        * determines what kind of completion is possible and return a array of proposals\r
+        * if we have no suggestions, the list will be empty\r
+        */\r
+        /*\r
+       function getCompletionResult(startNode, cursor) {\r
+       var compResult;\r
+       buildTsObjTree(startNode, cursor);\r
+\r
+       // is there an operator left of the current curser Position (= in the currentLine)\r
+       var op = getOperator(currentLine);\r
+       if (op != -1) {\r
+               // is it a reference/copy operator?\r
+               if (op.indexOf("<") != -1) {\r
+               // show path completion\r
+               compResult = getPathCompletion(currentTsTreeNode);\r
+               } else {\r
+               // show what ?????\r
+               // biggest mystery!!\r
+               // think about!\r
+               }\r
+       // no operator in the line\r
+       } else {\r
+\r
+               // whitespace after last characters? -> show operators\r
+               if(currentLine.substr(-1,1) == " ") {\r
+               compResult = getOperatorCompletion();\r
+               // no whitespace? we're in a path!\r
+               } else {\r
+               compResult = getPathCompletion(currentTsTreeNode);\r
+               }\r
+       }\r
+\r
+       return compResult;\r
+       }*/\r
+\r
+       /**\r
+        * retrieves the get-variable with the specified name\r
+        */\r
+\r
+       function getGetVar(name){\r
+               var get_string = document.location.search;\r
+               var return_value = '';\r
+               var value;\r
+               do { //This loop is made to catch all instances of any get variable.\r
+                       var name_index = get_string.indexOf(name + '=');\r
+                       if(name_index != -1) {\r
+                               get_string = get_string.substr(name_index + name.length + 1, get_string.length - name_index);\r
+                               end_of_value = get_string.indexOf('&');\r
+                               if(end_of_value != -1) {\r
+                                       value = get_string.substr(0, end_of_value);\r
+                               } else {\r
+                                       value = get_string;\r
+                               }\r
+\r
+                               if(return_value == '' || value == '') {\r
+                                       return_value += value;\r
+                               } else {\r
+                                       return_value += ', ' + value;\r
+                               }\r
+                       }\r
+               } while(name_index != -1);\r
+\r
+                //Restores all the blank spaces.\r
+               var space = return_value.indexOf('+');\r
+               while(space != -1) {\r
+                       return_value = return_value.substr(0, space) + ' ' +\r
+                       return_value.substr(space + 1, return_value.length);\r
+                       space = return_value.indexOf('+');\r
+               }\r
+\r
+               return(return_value);\r
+       }\r
+}
\ No newline at end of file
diff --git a/typo3/sysext/t3editor/jslib/ts_codecompletion/tsparser.js b/typo3/sysext/t3editor/jslib/ts_codecompletion/tsparser.js
new file mode 100644 (file)
index 0000000..6de6249
--- /dev/null
@@ -0,0 +1,452 @@
+/***************************************************************\r
+* Copyright notice\r
+*\r
+* (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de>\r
+* All rights reserved\r
+*\r
+* This script is part of the TYPO3 project. The TYPO3 project is\r
+* free software; you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation; either version 2 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* The GNU General Public License can be found at\r
+* http://www.gnu.org/copyleft/gpl.html.\r
+* A copy is found in the textfile GPL.txt and important notices to the license\r
+* from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+* This script is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+* GNU General Public License for more details.\r
+*\r
+* This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * @fileoverview contains the TsParser class and the TreeNode helper class\r
+ */\r
+\r
+/**\r
+ * Construct a new TsParser object.\r
+ * @class This class takes care of the parsing and builds the codeTree\r
+ *\r
+ * @constructor\r
+ * @param tsRef typoscript reference tree\r
+ * @param extTsObjTree codeTree for all typoscript templates\r
+ *                      excluding the current one.\r
+ * @return A new TsParser instance\r
+ */\r
+var TsParser = function(tsRef,extTsObjTree) {\r
+\r
+       /**\r
+        * @class data structure for the nodes of the code tree\r
+        * mainly used for retrieving the externals templates childnodes\r
+        * @constructor\r
+        * @param {String} name\r
+        */\r
+       function TreeNode(nodeName) {\r
+               this.name = nodeName;\r
+               //this.tsObjTree = tsObjTree;\r
+               this.childNodes = new Array();\r
+               //has to be set, so the node can retrieve the childnodes of the external templates\r
+               this.extPath = "";\r
+               // the TS-objecttype ID (TSREF)\r
+               this.value = "";\r
+               //this.extTsObjTree = null;\r
+               this.tsrefProperty = false;\r
+               // current template or external template\r
+               this.isExternal = false;\r
+\r
+               /**\r
+                * returns local properties and the properties of the external templates\r
+                * @returns {Array} ChildNodes\r
+                */\r
+               this.getChildNodes = function() {\r
+                       var node = this.getExtNode();\r
+                       if (node) {\r
+                               for (key in node.c) {\r
+                                       var tn = new TreeNode(key,this.tsObjTree);\r
+                                       tn.global = true;\r
+                                       tn.value = (node.c[key].v)? node.c[key].v : "";\r
+                                       tn.isExternal = true;\r
+                                       this.childNodes[key] = tn;\r
+                               }\r
+                       }\r
+                       return this.childNodes;\r
+               }\r
+\r
+               this.getValue = function() {\r
+                       if(this.value != "") {\r
+                               return this.value;\r
+                       } else {\r
+                               var node = this.getExtNode();\r
+                               if(node) {\r
+                                       return node.v;\r
+                               } else {\r
+                                       return "";\r
+                               }\r
+                       }\r
+               }\r
+\r
+               this.getExtNode = function() {\r
+                       var extTree = extTsObjTree;\r
+                       var path = this.extPath.split('.');\r
+                       var pathSeg;\r
+                       if (path == "") return extTree;\r
+                       var i;\r
+                       for (i=0;i<path.length;i++) {\r
+                               pathSeg = path[i];\r
+                               if(extTree.c == null || extTree.c[pathSeg] == null) {\r
+                                       return null;\r
+                               }\r
+                               extTree = extTree.c[pathSeg];\r
+                       }\r
+                       return extTree;\r
+               }\r
+\r
+       }\r
+\r
+       var tsTree = new TreeNode("");\r
+       var currentLine = "";\r
+\r
+\r
+       /**\r
+        * build Tree of TsObjects from beginning of editor to actual cursorPos\r
+        * and store it in tsTree.\r
+        * also store string from cursor position to the beginning of the line in currentLine\r
+        * and return the reference to the last path before the cursor position in currentTsTreeNode\r
+        * @param startNode DOM Node containing the first word in the editor\r
+        * @param cursorNode DOM Node containing the word at cursor position\r
+        * @return currentTsTreeNode\r
+        */\r
+       this.buildTsObjTree = function(startNode, cursorNode) {\r
+               return buildTsObjTree(startNode, cursorNode);\r
+       }\r
+       function buildTsObjTree(startNode, cursorNode) {\r
+               var currentNode = startNode;\r
+               var line = "";\r
+               tsTree = new TreeNode("");\r
+               function Stack() {\r
+               }\r
+\r
+               Stack.prototype = new Array();\r
+\r
+               Stack.prototype.lastElementEquals = function(str) {\r
+                       if (this.length > 0 && this[this.length-1]==str) {\r
+                               return true;\r
+                       }else {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               Stack.prototype.popIfLastElementEquals = function(str) {\r
+                       if(this.length > 0 && this[this.length-1]==str) {\r
+                               this.pop();\r
+                               return true;\r
+                       }else {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               var stack = new Stack();\r
+               var prefixes = new Array();\r
+               var ignoreLine = false;\r
+               //var cursorReached = false;\r
+               var insideCondition = false;\r
+\r
+               while(true) {\r
+                       if(currentNode.hasChildNodes() && currentNode.firstChild.nodeType==3 && currentNode.currentText.length>0) {\r
+                               node = currentNode.currentText;\r
+                               if (node[0] == '#')stack.push('#');\r
+                               if (node                == '(')stack.push('(');\r
+                               if (node[0] == '/' && node[1]=='*')stack.push('/*');\r
+                               if (node                == '{') {\r
+                                       stack.push('{');\r
+                                       prefixes.push(line);\r
+                                       ignoreLine = true;\r
+                               }\r
+                               // TODO: conditions\r
+                               // if condition starts -> ignore everything until end of condition\r
+                               if (node.search(/^\s*\[.*\]/) != -1\r
+                                               && line.search(/\S/) == -1\r
+                                               && node.search(/^\s*\[(global|end|GLOBAL|END)\]/) == -1\r
+                                               && !stack.lastElementEquals('#')\r
+                                               && !stack.lastElementEquals('/*')\r
+                                               && !stack.lastElementEquals('{')\r
+                                               && !stack.lastElementEquals('(')\r
+                                               ) {\r
+                                       insideCondition = true;\r
+                                       ignoreLine = true;\r
+                               }\r
+\r
+                               // if end of condition reached\r
+                               if (line.search(/\S/) == -1\r
+                                               && !stack.lastElementEquals('#')\r
+                                               && !stack.lastElementEquals('/*')\r
+                                               && !stack.lastElementEquals('(')\r
+                                               && (\r
+                                                                (node.search(/^\s*\[(global|end|GLOBAL|END)\]/) != -1\r
+                                                                       && !stack.lastElementEquals('{'))\r
+                                                       || (node.search(/^\s*\[(global|GLOBAL)\]/) != -1)\r
+                                                        )\r
+                                               ) {\r
+                                       insideCondition = false;\r
+                                       ignoreLine = true;\r
+                               }\r
+\r
+\r
+\r
+                               if (node == ')') {\r
+                                       stack.popIfLastElementEquals('(');\r
+                               }\r
+                               if (node[0] == '*' && node[1]=='/') {\r
+                                       stack.popIfLastElementEquals('/*');\r
+                                       ignoreLine = true;\r
+                               }\r
+                               if (node == '}') {\r
+                                       stack.popIfLastElementEquals('{');\r
+                                       if (prefixes.length>0) prefixes.pop();\r
+                                       ignoreLine = true;\r
+                               }\r
+                               if (!stack.lastElementEquals('#')) {\r
+                                       line += node;\r
+                               }\r
+\r
+                       } else {\r
+                               //end of line? divide line into path and text and try to build a node\r
+                               if (currentNode.tagName == "BR") {\r
+                                       // ignore comments, ...\r
+                                       if(!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) {\r
+                                               line = line.replace(/\s/g,"");\r
+                                               // check if there is any operator in this line\r
+                                               var op = getOperator(line);\r
+                                               if (op != -1) {\r
+                                                       // figure out the position of the operator\r
+                                                       var pos = line.indexOf(op);\r
+                                                       // the target objectpath should be left to the operator\r
+                                                       var path = line.substring(0,pos);\r
+                                                       // if we are in between curly brackets: add prefixes to object path\r
+                                                       if (prefixes.length>0) {\r
+                                                               path = prefixes.join('.') + '.' + path;\r
+                                                       }\r
+                                                       // the type or value should be right to the operator\r
+                                                       var str = line.substring(pos+op.length, line.length);\r
+                                                       path = path.replace(/\s/g,"");\r
+                                                       str = str.replace(/\s/g,"");\r
+                                                       switch(op) {    // set a value or create a new object\r
+                                                               case '=':\r
+                                                                       setTreeNodeValue(path, str);\r
+                                                                       break;\r
+                                                               case '=<': // reference to another object in the tree\r
+                                                                       setReference(path, str);\r
+                                                                       break;\r
+                                                               case '<': // copy from another object in the tree\r
+                                                                       setCopy(path, str);\r
+                                                                       break;\r
+                                                               case '>': // delete object value and properties\r
+                                                                       deleteTreeNodeValue(path);\r
+                                                                       break;\r
+                                                               case ':=': // function operator\r
+                                                                       // TODO: function-operator\r
+                                                                       break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       stack.popIfLastElementEquals('#');\r
+                                       ignoreLine = false;\r
+                                       line = "";\r
+                               }\r
+                       }\r
+                       // todo: fix problem: occurs if you type something, delete it with backspace and press ctrl+space\r
+                       // hack: cursor.start does not always return the node on the same level- so we have to check both\r
+                       // if (currentNode == cursor.start.node.parentNode || currentNode == cursor.start.node.previousSibling){\r
+                       // another problem: also the filter is calculated wrong, due to the buggy cursor, so this hack is useless\r
+                       if (currentNode == cursorNode) {\r
+                               break;\r
+                       } else {\r
+                               currentNode = currentNode.nextSibling;\r
+                       }\r
+               }\r
+               // when node at cursorPos is reached:\r
+               // save currentLine, currentTsTreeNode and filter if necessary\r
+               // if there is a reference or copy operator ('<' or '=<')\r
+               // return the treeNode of the path right to the operator,\r
+               // else try to build a path from the whole line\r
+\r
+               if(!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) {\r
+                       currentLine = line;\r
+                       var i = line.indexOf('<');\r
+                       if (i != -1) {\r
+                               var path = line.substring(i+1, line.length)\r
+                       } else {\r
+                               var path = line;\r
+                               if (prefixes.length>0) {\r
+                                       path = prefixes.join('.') + '.' + path;\r
+                               }\r
+                       }\r
+                       path = path.replace(/\s/g,"");\r
+                       var lastDot = path.lastIndexOf(".");\r
+                       path = path.substring(0, lastDot);\r
+               }\r
+               return getTreeNode(path);\r
+       }\r
+\r
+\r
+       /**\r
+        * check if there is an operator in the line and return it\r
+        * if there is none, return -1\r
+        */\r
+       function getOperator(line) {\r
+               var operators = new Array(":=", "=<", "<", ">", "=");\r
+               for (var i=0; i<operators.length; i++) {\r
+                       var op = operators[i];\r
+                       if (line.indexOf(op) != -1) {\r
+                               // check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML)\r
+                               // we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder"\r
+                               if((op == "=<" || op == "<") && line.indexOf(">") != -1){\r
+                                               // if there is a ">" in the line suppose there's some HTML\r
+                                               return "=";\r
+                               }\r
+                               return op;\r
+                       }\r
+               }\r
+               return -1;\r
+       }\r
+\r
+\r
+       /**\r
+        * iterates through the object tree, and creates treenodes\r
+        * along the path, if necessary\r
+        */\r
+       function getTreeNode(path){\r
+               var aPath = path.replace(/\s/g,"").split(".");\r
+               if (aPath == "") {\r
+                       return tsTree;\r
+               }\r
+               var subTree = tsTree.childNodes;\r
+               var pathSeg;\r
+               var parent;\r
+               // step through the path from left to right\r
+               for (i=0;i<aPath.length;i++) {\r
+                       pathSeg = aPath[i];\r
+                       // if there isn't already a treenode\r
+                       if (subTree[pathSeg]==null || subTree[pathSeg].childNodes == null) { // if this subpath is not defined in the code\r
+                               // create a new treenode\r
+                               subTree[pathSeg] = new TreeNode(pathSeg);\r
+                               subTree[pathSeg].parent = parent;\r
+                               //subTree[pathSeg].extTsObjTree = extTsObjTree;\r
+                               // the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates\r
+                               if(parent == null) {\r
+                                       subTree[pathSeg].extPath = pathSeg;\r
+                               } else {\r
+                                       subTree[pathSeg].extPath = parent.extPath+'.'+pathSeg;\r
+                               }\r
+                               // if its no root element && search in the TSREF found a matching property\r
+                               if (parent != null && tsRef.typeHasProperty(parent.getValue(),pathSeg)) { // if there is a matching property in the tsref\r
+                                       // get type of the current treeNode\r
+                                       var type = tsRef.getType(parent.getValue());\r
+                                       // get the type of the subNode\r
+                                       var propertyTypeId = type.properties[pathSeg].value;\r
+                                       // set type in the tree\r
+                                       subTree[pathSeg].value = propertyTypeId;\r
+                                       subTree[pathSeg].tsrefProperty = true;\r
+                                       // set subproperties of property-type as childNodes\r
+                                       //subTree[pathSeg].childNodes = tsRef.getPropertiesFromTypeId(propertyTypeId).clone();\r
+                                       subTree[pathSeg].parent = parent;\r
+                               }\r
+                       }\r
+                       if (i==aPath.length-1) {\r
+                               return subTree[pathSeg];\r
+                       }\r
+                       parent = subTree[pathSeg];\r
+                       subTree = subTree[pathSeg].childNodes;\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * navigates to the respecting treenode,\r
+        * create nodes in the path, if necessary, and sets the value\r
+        */\r
+       function setTreeNodeValue(path, value) {\r
+               var treeNode = getTreeNode(path);\r
+               // if we are inside a GIFBUILDER Object\r
+               if (treeNode.parent != null && treeNode.parent.value == "GIFBUILDER" && value == "TEXT") {\r
+                       value = "IMGTEXT";\r
+               }\r
+               // just override if it is a real objecttype\r
+               if (tsRef.isType(value)) {\r
+                       treeNode.value = value;\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+        * navigates to the respecting treenode,\r
+        * creates nodes if necessary, empties the value and childNodes-Array\r
+        */\r
+       function deleteTreeNodeValue(path) {\r
+               var treeNode = getTreeNode(path);\r
+               // currently the node is not deleted really, its just not displayed cause value == null\r
+               // deleting it would be a cleaner solution\r
+               treeNode.value = null;\r
+               treeNode.childNodes = null;\r
+               treeNode = null;\r
+       }\r
+\r
+\r
+       /**\r
+        * copies a reference of the treeNode specified by path2\r
+        * to the location specified by path1\r
+        */\r
+       function setReference(path1, path2) {\r
+               path1arr = path1.split('.');\r
+               lastNodeName = path1arr[path1arr.length-1];\r
+               var treeNode1 = getTreeNode(path1);\r
+               var treeNode2 = getTreeNode(path2);\r
+               if (treeNode1.parent != null) {\r
+                       treeNode1.parent.childNodes[lastNodeName] = treeNode2;\r
+               } else {\r
+                       tsTree.childNodes[lastNodeName] = treeNode2;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * copies a treeNode specified by path2\r
+        * to the location specified by path1\r
+        */\r
+       function setCopy(path1,path2){\r
+               this.clone = function(myObj) {\r
+                       if (myObj == null || typeof(myObj) != 'object') {\r
+                               return myObj;\r
+                       }\r
+\r
+                       var myNewObj = new Object();\r
+\r
+                       for (var i in myObj) {\r
+                               if(i != "parent"){\r
+                                       if (typeof myObj[i] == 'object') {\r
+                                               myNewObj[i] = clone(myObj[i]);\r
+                                       } else {\r
+                                               myNewObj[i] = myObj[i];\r
+                                       }\r
+                               }\r
+                       }\r
+                       return myNewObj;\r
+               }\r
+               var path1arr = path1.split('.');\r
+               var lastNodeName = path1arr[path1arr.length-1];\r
+               var treeNode1 = getTreeNode(path1);\r
+               var treeNode2 = getTreeNode(path2);\r
+\r
+               if (treeNode1.parent != null) {\r
+                       treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2);\r
+                       //treeNode1.parent.childNodes[lastNodeName].extTsObjTree = extTsObjTree;\r
+               } else {\r
+                       tsTree.childNodes[lastNodeName] = this.clone(treeNode2);\r
+                       //tsTree[lastNodeName].extTsObjTree = extTsObjTree;\r
+               }\r
+\r
+       }\r
+}
\ No newline at end of file
diff --git a/typo3/sysext/t3editor/jslib/ts_codecompletion/tsref.js b/typo3/sysext/t3editor/jslib/ts_codecompletion/tsref.js
new file mode 100644 (file)
index 0000000..0ec9c33
--- /dev/null
@@ -0,0 +1,191 @@
+/***************************************************************\r
+*  Copyright notice\r
+*\r
+*  (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de> \r
+*  All rights reserved\r
+*\r
+*  This script is part of the TYPO3 project. The TYPO3 project is\r
+*  free software; you can redistribute it and/or modify\r
+*  it under the terms of the GNU General Public License as published by\r
+*  the Free Software Foundation; either version 2 of the License, or\r
+*  (at your option) any later version.\r
+*\r
+*  The GNU General Public License can be found at\r
+*  http://www.gnu.org/copyleft/gpl.html.\r
+*  A copy is found in the textfile GPL.txt and important notices to the license\r
+*  from the author is found in LICENSE.txt distributed with these scripts.\r
+*\r
+*\r
+*  This script is distributed in the hope that it will be useful,\r
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+*  GNU General Public License for more details.\r
+*\r
+*  This copyright notice MUST APPEAR in all copies of the script!\r
+***************************************************************/\r
+/**\r
+ * @fileoverview contains the TsRef class \r
+ * and the TsRefProperty and TsRefType helper classes\r
+ */ \r
+\r
+/**\r
+ * @class Represents a TsRefProperty in the tree\r
+ *  \r
+ * @constructor\r
+ */\r
+var TsRefProperty = function(parentType,name,value) {\r
+       this.parentType = parentType;\r
+       this.name = name;\r
+       this.value = value;\r
+       var descriptionCache = null;\r
+       this.getDescription = function(callBack) {\r
+               if(descriptionCache == null){\r
+                       var urlParameters = '&ajaxID=tx_t3editor_TSrefLoader::getDescription' +\r
+                               '&typeId=' + this.parentType +\r
+                               '&parameterName=' + this.name;\r
+\r
+                       new Ajax.Request(\r
+                               URL_typo3 + 'ajax.php',\r
+                               {\r
+                                       method: 'get',\r
+                                       parameters: urlParameters,\r
+                                       onSuccess: function(transport) {\r
+                                         descriptionCache = transport.responseText;\r
+                                         callBack(transport.responseText);\r
+                                       }\r
+                               }\r
+                       );\r
+               } else {\r
+                       callBack(descriptionCache);\r
+               }\r
+       }\r
+}\r
+\r
+/**\r
+ * @class Represents a TsRefType in the tree\r
+ *  \r
+ * @constructor\r
+ */\r
+var TsRefType = function(typeId) {\r
+       this.typeId = typeId;                   \r
+       this.properties = new Array();\r
+\r
+       // todo: types can have descriptions too!\r
+       this.getDescription = function() {\r
+       }\r
+}\r
+\r
+/**\r
+ * Construct a new TsRef object.\r
+ * @class This class receives the TsRef from the server and represents it as a tree\r
+ * also supplies methods for access to treeNodes \r
+ *  \r
+ * @constructor\r
+ * @return A new TsRef instance\r
+ */\r
+var TsRef = function() {\r
+       var typeTree = new Array();     \r
+\r
+       var doc;\r
+\r
+       this.loadTsrefAsync = function() {\r
+               var urlParameters = '&ajaxID=tx_t3editor_TSrefLoader::getTypes';\r
+               new Ajax.Request(\r
+                       URL_typo3 + 'ajax.php',\r
+                       {\r
+                               method: 'get',\r
+                               parameters: urlParameters,\r
+                               onSuccess: function(transport) {\r
+                                       doc = eval('('+ transport.responseText +')');\r
+                                       buildTree();\r
+                               }\r
+                       }\r
+               );\r
+       }\r
+\r
+\r
+\r
+       function buildTree() { \r
+         \r
+               typeTree = new Array();\r
+               for (var typeId in doc) {\r
+                 \r
+                       var arr = doc[typeId];\r
+                       typeTree[typeId] = new TsRefType(typeId);\r
+                 \r
+\r
+                       if (arr['extends'] != null) {\r
+                               typeTree[typeId]['extends'] = arr['extends'];\r
+                       }\r
+                       for (propName in arr.properties) {\r
+                               var propType = arr.properties[propName].type;\r
+                               typeTree[typeId].properties[propName] = new TsRefProperty(typeId,propName,propType);\r
+                       }\r
+               }\r
+               for (var typeId in typeTree) {\r
+                       if (typeTree[typeId]['extends'] != null) {\r
+                               //console.log(typeId+" | "+typeTree[typeId].extends+" |");\r
+                               addPropertiesToType(typeTree[typeId], typeTree[typeId]['extends'], 100);\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+       function addPropertiesToType(addToType,addFromTypeNames,maxRecDepth){\r
+               if(maxRecDepth<0){\r
+                       throw "Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!";\r
+                       return;\r
+               }\r
+               var exts = addFromTypeNames.split(',');\r
+               var i;\r
+               for(i=0;i<exts.length;i++){\r
+                       //"Type 'array' which is used to extend 'undefined', was not found in the TSREF!"\r
+                       if(typeTree[exts[i]]==null){\r
+                               //console.log("Error: Type '"+exts[i]+"' which is used to extend '"+addToType.typeId+"', was not found in the TSREF!");\r
+                       }else{\r
+                               if(typeTree[exts[i]]['extends'] != null){   \r
+                                       addPropertiesToType(typeTree[exts[i]],typeTree[exts[i]]['extends'],maxRecDepth-1);\r
+                               }\r
+                               var properties = typeTree[exts[i]].properties;\r
+                               for(propName in properties){\r
+                                       // only add this property if it was not already added by a supertype (subtypes override supertypes)\r
+                                       if(addToType.properties[propName] == null){\r
+                                               addToType.properties[propName] = properties[propName];\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       this.getPropertiesFromTypeId = function(tId) {\r
+               if (typeTree[tId] != null) {\r
+                       // clone is needed to assure that nothing of the tsref is overwritten by user setup\r
+                       typeTree[tId].properties.clone = function() {\r
+                               var result = new Array();\r
+                               for (key in this) {\r
+                                       result[key] = new TsRefProperty(this[key].parentType,this[key].name,this[key].value);\r
+                               }\r
+                               return result;\r
+                       }        \r
+                       return typeTree[tId].properties;\r
+               } else {\r
+                       return new Array();\r
+               } \r
+       }\r
+\r
+       this.typeHasProperty = function(typeId,propertyName) {\r
+               if (typeTree[typeId] != null && typeTree[typeId].properties[propertyName] != null) {\r
+                       return true;\r
+               } else {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       this.getType = function(typeId){\r
+               return typeTree[typeId];\r
+       }\r
+       this.isType = function(typeId){\r
+               return (typeTree[typeId] != null);\r
+       }\r
+}
\ No newline at end of file
diff --git a/typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_codecompletion.php b/typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_codecompletion.php
new file mode 100644 (file)
index 0000000..d16b901
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+class tx_t3editor_codecompletion {
+       /** @var TYPO3AJAX */
+       protected $ajaxObj;
+
+       /**
+        * General processor for AJAX requests.
+        * (called by typo3/ajax.php)
+        *
+        * @param       array           $params: additional parameters (not used here)
+        * @param       TYPO3AJAX       &$ajaxObj: the TYPO3AJAX object of this request
+        * @return      void
+        * @author      Oliver Hader <oliver@typo3.org>
+        */
+       public function processAjaxRequest($params, TYPO3AJAX &$ajaxObj) {
+               $this->ajaxObj = $ajaxObj;
+
+               $ajaxIdParts = explode('::', $ajaxObj->getAjaxID(), 2);
+               $ajaxMethod = $ajaxIdParts[1];
+               $response = array();
+
+               // Process the AJAX requests:
+               if ($ajaxMethod == 'loadTemplates') {
+                       $ajaxObj->setContent($this->loadTemplates(
+                               intval(t3lib_div::_GP('pageId')))
+                       );
+                       $ajaxObj->setContentFormat('jsonbody');
+               }
+       }
+
+       /**
+        * Loads all templates up to a given page id (walking the rootline) and
+        * cleans parts that are not required for the t3editor codecompletion.
+        *
+        * @param       integer         $pageId: id of the page 
+        * @param       integer         $templateId: currently unused (default: 0)
+        * @return      array           Cleaned array of TypoScript information
+        * @author      Oliver Hader <oliver@typo3.org>
+        */
+       protected function loadTemplates($pageId, $templateId = 0) {
+               $templates = array();
+
+                       // Check whether access is granted (only admin have access to sys_template records):
+               if ($GLOBALS['BE_USER']->isAdmin()) {
+                               // Check whether there is a pageId given:
+                       if ($pageId) {
+                               $templates = $this->getMergedTemplates($pageId);
+                               // Otherwise, set an error: 
+                       } else {
+                               $this->ajaxObj->setError('Syntax error: Parameter pageId must be a valid integer.');
+                       }
+                       // Set an error if user has no access to sys_template records:
+               } else {
+                       $this->ajaxObj->setError('Access denied: No permission to template records.');
+               }
+
+               return $templates;
+       }
+
+       /**
+        * Gets merged templates by walking the rootline to a given page id.
+        *
+        * @todo        oliver@typo3.org: Refactor this method and comment what's going on there
+        * @param       integer         $pageId
+        * @param       integer         $templateId
+        * @return      array           Setup part of merged template records
+        */
+       protected function getMergedTemplates($pageId, $templateId = 0) {
+               $result = array();
+
+               /** @var $tsParser t3lib_tsparser_ext */
+               $tsParser = t3lib_div::makeInstance('t3lib_tsparser_ext');
+               $tsParser->tt_track = 0;
+               $tsParser->init();
+                       // Gets the rootLine
+               $page = t3lib_div::makeInstance('t3lib_pageSelect');
+               $rootLine = $page->getRootLine($pageId);
+
+                       // This generates the constants/config + hierarchy info for the template.
+               $tsParser->runThroughTemplates($rootLine);
+
+               // ts-setup & ts-constants of the currently edited template should not be included
+               // therefor we have to delete the last template from the stack
+               array_pop($tsParser->config);
+               array_pop($tsParser->constants);
+
+               // some of the lines are not clear to me... do we need them?
+               //$tsParser->matchAlternative[] = 'dummydummydummydummydummydummydummydummydummydummydummy';            // This is just here to make sure that at least one element is in the array so that the tsparser actually uses this array to match.
+               //$tsParser->regexMode = $this->pObj->MOD_SETTINGS["ts_browser_regexsearch"];
+               // ??
+               //$tsParser->fixedLgd=$this->pObj->MOD_SETTINGS["ts_browser_fixedLgd"];
+               //$tsParser->matchAlternative = $this->pObj->MOD_SETTINGS['tsbrowser_conditions'];
+               $tsParser->linkObjects = TRUE;
+               $tsParser->ext_regLinenumbers = FALSE;
+               $tsParser->bType=$bType;
+               $tsParser->resourceCheck=1;
+               $tsParser->uplPath = PATH_site . $tsParser->uplPath;
+               $tsParser->removeFromGetFilePath = PATH_site;
+               $tsParser->generateConfig();
+
+               $result = $this->treeWalkCleanup($tsParser->setup);
+
+               return $result;
+       }
+
+       /**
+        * Walks through a tree of TypoScript configuration an cleans it up.
+        *
+        * @TODO        oliver@typo3.org: Define and comment why this is necessary and exactly happens below
+        * @param       array           $treeBranch: TypoScript configuration or sub branch of it
+        * @return      array           Cleaned TypoScript branch
+        */
+       private function treeWalkCleanup(array $treeBranch){
+               $cleanedTreeBranch = array();
+
+               foreach ($treeBranch as $key => $value) {
+                       $dotCount = substr_count($key, '.');
+                       if ($dotCount == 0){    //type definition or value-assignment
+                               if ($value != '') {
+                                       if (strlen($value) > 20) {
+                                               $value = substr($value, 0, 20);
+                                       }
+                                       if (!isset($cleanedTreeBranch[$key])) {
+                                               $cleanedTreeBranch[$key] = array();
+                                       }
+                                       $cleanedTreeBranch[$key]['v'] = $value;
+                               }
+                       } else if ($dotCount == 1) { // subtree (definition of properties)
+                               $subBranch = $this->treeWalkCleanup($value);
+                               if ($subBranch) {
+                                       $key = str_replace('.', '', $key);
+                                       if (!isset($cleanedTreeBranch[$key])) {
+                                               $cleanedTreeBranch[$key] = array();
+                                       }
+                                       $cleanedTreeBranch[$key]['c'] = $subBranch;
+                               }
+                       } //in other cases do nothing (this information (lineNo,..) is not needed in the editor)
+               }
+
+               return $cleanedTreeBranch;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php b/typo3/sysext/t3editor/lib/ts_codecompletion/class.tx_t3editor_tsrefloader.php
new file mode 100644 (file)
index 0000000..7a7774e
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2008 Stephan Petzl <spetzl@gmx.at> and Christian Kartnig <office@hahnepeter.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+/**
+ * Loads TSref information from a XML file an responds to an AJAX call.
+ *
+ * @TODO Refactor and correct phpDoc comments
+ * @package TYPO3
+ * @author Stephan Petzl <spetzl@gmx.at>
+ * @author Christian Kartnig <office@hahnepeter.de>
+ */
+class tx_t3editor_TSrefLoader {
+       /** @var DOMDocument */
+       protected $xmlDoc;
+       
+       /** @var TYPO3AJAX */
+       protected $ajaxObj;
+       
+       /**
+        * General processor for AJAX requests.
+        * (called by typo3/ajax.php)
+        *
+        * @param       array           $params: additional parameters (not used here)
+        * @param       TYPO3AJAX       &$ajaxObj: the TYPO3AJAX object of this request
+        * @return      void
+        * @author      Oliver Hader <oliver@typo3.org>
+        */
+       public function processAjaxRequest($params, TYPO3AJAX &$ajaxObj) {
+               $this->ajaxObj = $ajaxObj;
+
+               // Load the TSref XML information:
+               $this->loadFile(t3lib_extMgm::extPath('t3editor') . 'tsref/tsref.xml');
+
+               $ajaxIdParts = explode('::', $ajaxObj->getAjaxID(), 2);
+               $ajaxMethod = $ajaxIdParts[1];
+               $response = array();
+
+               // Process the AJAX requests:
+               if ($ajaxMethod == 'getTypes') {
+                       $ajaxObj->setContent($this->getTypes());
+                       $ajaxObj->setContentFormat('jsonbody');
+               } elseif ($ajaxMethod == 'getDescription') {
+                       $ajaxObj->addContent(
+                               '',
+                               $this->getDescription(
+                                       t3lib_div::_GP('typeId'),
+                                       t3lib_div::_GP('parameterName')
+                               )
+                       );
+                       $ajaxObj->setContentFormat('plain');
+               }
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @param       string          $filepath
+        * @return      void
+        */
+       protected function loadFile($filepath) {
+               $this->xmlDoc = new DOMDocument('1.0', 'utf-8');
+               $this->xmlDoc->load($filepath);
+
+               // @TODO: oliver@typo3.org: I guess this is not required here
+               $this->xmlDoc->saveXML();
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @return      array
+        */
+       protected function getTypes() {
+               $types = $this->xmlDoc->getElementsByTagName('type');
+               $typeArr = array();
+               foreach($types as $type){
+                       $typeId = $type->getAttribute('id');
+                       $typeName = $type->getAttribute('name');
+                       if(!$typeName) {
+                               $typeName = $typeId;
+                       }
+                       $properties = $type->getElementsByTagName('property');
+                       $propArr = array();
+                       foreach($properties as $property) {
+                               $p = array();
+                               $p['name'] = $property->getAttribute('name');
+                               $p['type'] = $property->getAttribute('type');
+                               $propArr[$property->getAttribute('name')] = $p;
+                       }
+                       $typeArr[$typeId] = array();
+                       $typeArr[$typeId]['properties'] = $propArr;
+                       $typeArr[$typeId]['name'] = $typeName;
+                       if($type->hasAttribute('extends')) {
+                               $typeArr[$typeId]['extends'] = $type->getAttribute('extends');
+                       }
+               }
+               return $typeArr;
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @param       string          $typeId
+        * @param       string          $parameterName
+        * @return      string
+        */
+       protected function getDescription($typeId, $parameterName = '') {
+               if (!$typeId) {
+                       $this->ajaxObj->setError('Syntax error: At least parameter typeId has to be supplied.');
+                       return '';
+               }
+
+               // getElementById does only work with schema
+               $type = $this->getType($typeId);
+               if ($parameterName) {  //retrieve propertyDescription
+                       $properties = $type->getElementsByTagName('property');
+                       foreach ($properties as $propery) {
+                               $propName = $propery->getAttribute('name');
+                               if ($propName == $parameterName) {
+                                       $descriptions = $propery->getElementsByTagName('description');
+                                       if ($descriptions->length) {
+                                               $description = $descriptions->item(0)->textContent;
+                                               $description = htmlspecialchars($description);
+                                               $description = nl2br($description);
+                                               return $description;
+                                       }
+                               }
+                       }
+               } else {  // retrieve typedescription
+                       /*
+                       $descriptions = $type->getElementsByTagName('description');
+                       if($descriptions->length){
+                               $description = $descriptions->item(0)->textContent;
+
+                               return htmlspecialchars($description);
+                       }*/
+               }
+
+               return '';
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @param       string          $typeId
+        * @return      DOMNode
+        */
+       protected function getType($typeId) {
+               $types = $this->xmlDoc->getElementsByTagName('type');
+               foreach ($types as $type) {
+                       if ($type->getAttribute('id') == $typeId) {
+                               return $type;
+                       }
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/t3editor/tsref/tsref.xml b/typo3/sysext/t3editor/tsref/tsref.xml
new file mode 100644 (file)
index 0000000..20b8b7f
--- /dev/null
@@ -0,0 +1,7863 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tsRef>
+       <type id="cObj"/>
+       <type id="array"/>
+       <type id="int"/>
+       <type id="intList"/>
+       <type id="double"/>
+       <type id="boolean"/>
+       <type id="string"/>
+       <type id="ADMPANEL"/>
+       <type id="ARR_languages_strings" name="ARR_languages_strings">
+               <property name="default" type="string"/>
+               <property name="en" type="string"/>
+               <property name="dk" type="string"/>
+               <property name="de" type="string"/>
+               <property name="no" type="string"/>
+               <property name="it" type="string"/>
+               <property name="fr" type="string"/>
+               <property name="nl" type="string"/>
+               <property name="cz" type="string"/>
+               <property name="pl" type="string"/>
+               <property name="si" type="string"/>
+               <property name="fi" type="string"/>
+               <property name="tr" type="string"/>
+               <property name="se" type="string"/>
+               <property name="pt" type="string"/>
+               <property name="ru" type="string"/>
+               <property name="ro" type="string"/>
+               <property name="ch" type="string"/>
+               <property name="sk" type="string"/>
+               <property name="lt" type="string"/>
+               <property name="is" type="string"/>
+               <property name="hr" type="string"/>
+               <property name="hu" type="string"/>
+               <property name="gl" type="string"/>
+               <property name="th" type="string"/>
+               <property name="gr" type="string"/>
+               <property name="hk" type="string"/>
+               <property name="eu" type="string"/>
+               <property name="bg" type="string"/>
+               <property name="br" type="string"/>
+               <property name="et" type="string"/>
+               <property name="ar" type="string"/>
+               <property name="he" type="string"/>
+               <property name="ua" type="string"/>
+               <property name="lv" type="string"/>
+               <property name="jp" type="string"/>
+               <property name="vn" type="string"/>
+               <property name="ca" type="string"/>
+               <property name="ba" type="string"/>
+               <property name="kr" type="string"/>
+               <property name="eo" type="string"/>
+               <property name="my" type="string"/>
+               <property name="hi" type="string"/>
+       </type>
+       <type id="CARRAY" extends="stdWrap" name="CARRAY">
+               <property name="1" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). The order by which you specific the objects is not important as the array will be sorted before it's parsed!
+
+]]></description>
+               </property>
+               <property name="2" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). The order by which you specific the objects is not important as the array will be sorted before it's parsed!
+
+]]></description>
+               </property>
+               <property name="3" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). The order by which you specific the objects is not important as the array will be sorted before it's parsed!
+
+]]></description>
+               </property>
+               <property name="4" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). The order by which you specific the objects is not important as the array will be sorted before it's parsed!
+
+]]></description>
+               </property>
+       </type>
+       <type id="CARRAY+TDParams" extends="CARRAY" name="CARRAY+TDParams">
+               <property name="TDParams" type="string">
+                       <description><![CDATA[<TD>-params 
+      NOTE: This applies ONLY if "CARRAY +TDParams" is set to be data type
+This property is used only in some cases where CARRAY is used. Please look out for a note about that in the various cases.
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="CASE" extends="cObjArray" name="CASE">
+               <property name="default" type="cObj">
+                       <description><![CDATA[The default object, if not defined, nothing is returned in the default case.
+]]></description>
+               </property>
+               <property name="if" type="if">
+                       <description><![CDATA[if "if" returns false nothing is returned
+
+]]></description>
+               </property>
+               <property name="key" type="stdWrap">
+                       <description><![CDATA[If the value of this key is defined, that object will be returned, otherwise the default-object will be returned.
+<pre>key = helloWorld
+helloWorld = <a href="/index.php/TSref/TEXT" title="TSref/TEXT">TEXT</a>
+
+helloWorld.value = this item will be returned
+</pre> 
+]]></description>
+               </property>
+               <property name="setCurrent" type="stdWrap">
+                       <description><![CDATA[Sets the "current"-value. 
+
+]]></description>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[stdwrap properties, applied on the returned object.
+]]></description>
+               </property>
+       </type>
+       <type id="CLEARGIF" name="CLEARGIF">
+               <property name="height" type="stdWrap">
+                       <description><![CDATA[<img>-data:height /stdWrap
+]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="width" type="stdWrap">
+                       <description><![CDATA[<img>-data:width /stdWrap
+]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[ 
+]]></description>
+                       <default><![CDATA[ | <BR>]]></default>
+               </property>
+       </type>
+       <type id="cObjArray">
+               <property name="1" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). 
+]]></description>
+               </property>
+               <property name="2" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). 
+]]></description>
+               </property>
+               <property name="3" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). 
+]]></description>
+               </property>
+               <property name="4" type="cObj">
+                       <description><![CDATA[This is a numerical "array" of content-objects (cObjects). 
+]]></description>
+               </property>
+       </type>
+       <type id="COBJ_ARRAY" extends="cObjArray">
+               <property name="if" type="if">
+                       <description><![CDATA[if "if" returns false the COA is NOT rendered]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="COA" extends="COBJ_ARRAY">
+  </type>
+       <type id="COA_INT" extends="COBJ_ARRAY">
+               <property name="includeLibs" type="stringList">
+                       <description><![CDATA[list of resources(This property is used only if the object is COA_INT!, See introduction.)
+This is a comma-separated list of resources that are included as PHP-scripts (with include_once() function) if this script is included.
+This is possible to do because any include-files will be known before the scripts are included. That's not the case with the regular PHP_SCRIPT cObject.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="COLUMNS">
+               <property name="TDparams" type="string">
+                       <description><![CDATA[<TD>-params
+]]></description>
+                       <default><![CDATA[valign=top]]></default>
+               </property>
+               <property name="1" type="cObj">
+                       <description><![CDATA[This is the content-object for each column!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="2" type="cObj">
+                       <description><![CDATA[This is the content-object for each column!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="3" type="cObj">
+                       <description><![CDATA[This is the content-object for each column!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="4" type="cObj">
+                       <description><![CDATA[This is the content-object for each column!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="after" type="cObj">
+                       <description><![CDATA[This is a cObject placed after the columns-table!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="gapBgCol" type="stdWrap">
+                       <description><![CDATA[HTML-color /stdWrap
+background-color for the gap-tablecells]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="gapLineCol" type="stdWrap">
+                       <description><![CDATA[HTML-color /stdWrap
+      Line color]]></description>
+                       <default><![CDATA[black]]></default>
+               </property>
+               <property name="gapLineThickness" type="stdWrap">
+                       <description><![CDATA[int /stdWrap
+      lineThickness of the dividerline in the gap between cells
+0 = no line]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="gapWidth" type="stdWrap">
+                       <description><![CDATA[int /stdWrap
+      Width of the gap between columns. 
+0 = no gap]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="if" type="if">
+                       <description><![CDATA[if "if" returns false the columns are not rendered!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="rows" type="int">
+                       <description><![CDATA[int (Range: 2-20)
+      The number of rows  in the columns.]]></description>
+                       <default><![CDATA[2]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="tableParams" type="string">
+                       <description><![CDATA[<TABLE>-params
+]]></description>
+                       <default><![CDATA[border=0 cellspacing=0 cellpadding=0]]></default>
+               </property>
+               <property name="totalWidth" type="int">
+                       <description><![CDATA[The total-width of the columns+gaps]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="CONFIG">
+               <property name="ATagParams" type="string">
+                       <description><![CDATA[<A>-params
+      Additional parameters to all links in TYPO3 (excluding menu-links)
+
+Example:
+To blur links, insert: 
+onFocus="blurLink(this)"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="MP_defaults" type="string">
+                       <description><![CDATA[Allows you to set a list of page id numbers which will always have a certain “&MP=...” parameter added.
+
+Syntax:
+[id],[id],... : [MP-var] | [id],[id],... : [MP-var] | ... 
+
+Example:
+config.MP_defaults = 36,37,48 : 2-207
+
+This will by default add “&MP=2-207” to all links pointing to pages 36,37 and 48]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="MP_disableTypolinkClosestMPvalue" type="boolean">
+                       <description><![CDATA[If set, the typolink function will not try to find the closest MP value for the id.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="MP_mapRootPoints" type="string">
+                       <description><![CDATA[list of PIDs/string
+      Defines a list of ID numbers from which the MP-vars are automatically calculated for the branch.
+The result is used just like MP_defaults are used to find MP-vars if none has been specified prior to the call to t3lib_tstemplate::linkData().
+You can specify “root” as a special keyword in the list of IDs and that will create a map-tree for the whole site (but this may be VERY processing intensive if there are many pages!).
+The order of IDs specified may have a significance; Any ID in a branch which is processed already (by a previous ID root point) will not be processed again.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="USERNAME_substToken" type="string">
+                       <description><![CDATA[The is the token used on the page, which should be substituted with the current username IF a front-end user is logged in! If no login, the substitution will not happen.]]></description>
+                       <default><![CDATA[<!--###USERNAME###-->]]></default>
+               </property>
+               <property name="USERUID_substToken" type="string">
+                       <description><![CDATA[The is the token used on the page, which should be substituted with the current users UID IF a front-end user is logged in! If no login, the substitution will not happen.
+This value has no default value and only if you specify a value for this token will a substitution process take place.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="absRefPrefix" type="string">
+                       <description><![CDATA[If this value is set, then all relative links in TypoScript are prepended with this string. Used to convert relative paths to absolute paths.
+
+Note: This values is automatically set to the dirname of the index.php script in case simulateStaticDocuments is set to “PATH_INFO”.
+If you're working on a server where you have both internal and external access, you might to yourself a favour and set the absRefPrefix to the url and path of you site, eg. http://www.typo3.com/. If you do not, you risk to render pages to cache from the internal network and thereby prefix image-references and links with a non-accesible path from outside.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="additionalHeaders" type="string">
+                       <description><![CDATA[strings divided by &quot;|&quot;
+      This is additional headers. You separate each header by a vertical line "|".  Normally TYPO3 does not send any headers with the Header()-function in PHP.
+
+Examples:
+Content-type: text/vnd.wap.wml
+(this will sent a content-header for a WAP-site)
+
+Content-type: image/gif | Expires: Mon, 26 Jul 1997 05:00:00 GMT
+(this will sent a content-header for a GIF-file and a Expires header)
+
+Location: www.typo3.com
+(This redirects the page to www.typo3.com)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="admPanel" type="ADMPANEL">
+                       <description><![CDATA[boolean / ADMPANEL properties
+      If set, the admin panel appears in the bottom of pages.
+
+NOTE: In addition the panel must be enabled for the user as well, using the TSconfig for the user! See adminguide documentation.
+
+SEE: Admin Panel section]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="baseURL" type="string">
+                       <description><![CDATA[This writes the <base> tag in the header of the document. Set this to the value that is expected to be the URL, and append a “/” to the end of the string.
+
+Example:
+config.baseURL = http://typo3.org/sub_dir/]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="beLoginLinkIPList" type="string">
+                       <description><![CDATA[[IP-number]
+      If set and REMOTE_ADDR matches one of the listed IP-numbers (Wild-card, *, allowed) then a link to the typo3/ login scrip with redirect pointing back to the page is shown.
+
+NOTE: beLoginLinkIPList_login and/or beLoginLinkIPList_logout (see below) must be defined if the link should show up!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="beLoginLinkIPList_login" type="string">
+                       <description><![CDATA[HTML code wrapped with the login link, see 'beLoginLinkIPList'
+
+Example:
+<HR><B>LOGING</B>]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="beLoginLinkIPList_logout" type="string">
+                       <description><![CDATA[HTML code wrapped with the logout link, see above]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="cache_clearAtMidnight" type="boolean">
+                       <description><![CDATA[With this setting the cache always expires at midnight of the day, the page is scheduled to expire.]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="cache_period" type="int">
+                       <description><![CDATA[int, seconds
+      The number of second a page may remain in cache.
+This value is overridden by the value set in the page-record (field="cache_timeout") if this value is greater than zero.]]></description>
+                       <default><![CDATA[86400 (=24H)]]></default>
+               </property>
+               <property name="compensateFieldWidth" type="double">
+                       <description><![CDATA[this floating point value will be used by the FORMS cObject to compensate the length of the formfields text and input.
+This feature is useful, if the page-option "smallFormFields" is set. In that case Netscape renders formfields much longer than IE. If you want the two browsers to display the same size formfields, use a value of approx "0.6" for netscape-browsers.
+
+Example:
+[browser = netscape]
+  config.compensateFieldWidth = 0.6
+[global]
+
+This option may be overridden in the FORMS-cObject.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="content_from_pid_allowOutsideDomain" type="boolean">
+                       <description><![CDATA[Using the “Show content from this page instead” feature allows you to insert content from the current domain only. Setting this option will allow content included from anywhere in the page tree!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="debug" type="boolean">
+                       <description><![CDATA[If set any debug-information in the TypoScript code is output. Currently this applies only to the menu-objects]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="disableAllHeaderCode" type="boolean">
+                       <description><![CDATA[If this is set, none of the features of the PAGE-object is processed and the content of the page will be the result of the cObject array (1,2,3,4...) of the PAGE-object.  This means that the result of the cObject should include everything from the <HTML> .... to the </HTML> tag !!
+Use this feature in templates supplying other content-types than HTML. That could be an image or a WAP-page!]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="disableCharsetHeader" type="boolean">
+                       <description><![CDATA[By default a header "content-type:text/html; charset..." is sent. This option will disable that.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="disablePageExternalUrl" type="boolean">
+                       <description><![CDATA[If set, pages with doktype “External Url” will not trigger jumpUrl in TSFE. This may help you to have external urls open inside you framesets.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="disablePrefixComment" type="boolean">
+                       <description><![CDATA[If set, the stdWrap property “prefixComment” will be disabled, thus preventing any revealing and spaceconsuming comments in the HTML source code.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="doctype" type="string">
+                       <description><![CDATA[If set, then a document type declaration (and an XML prologue) will be generated. The value can either be a complete doctype or one of the following keywords:
+
+"xhtml_trans" for XHTML 1.0 Transitional doctype.
+"xhtml_frames" for XHTML 1.0 Frameset doctype.
+"xhtml_strict" for XHTML 1.0 Strict doctype.
+"xhtml_basic" for XHTML basic doctype.
+"xhtml_11" for XHTML 1.1 doctype.
+"xhtml_2" for XHTML 2 doctype.
+"none" for NO doctype at all.
+
+Note that the keywords also change the way TYPO3 generates some of the XHTML tags to ensure valid XML. If you set doctype to a string, then you must also set config.xhtmlDoctype (see below).
+
+See "config.htmlTag_setParams" and "config.htmlTag_langKey" for more details on the effect on the html tag.
+]]></description>
+                       <default><![CDATA[Default is a DOCTYPE like this:
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+]]></default>
+               </property>
+               <property name="doctypeSwitch" type="boolean">
+                       <description><![CDATA[If set, the order of <?xml...> and <!DOCTYPE...> will be reversed. This is needed for MSIE to be standards compliant with XHTML.
+
+Background:
+By default TYPO3 outputs the XML/DOCTYPE in compliance with the standards of XHTML. However a browser like MSIE will still run in “quirks-mode” unless the <?xml> and <DOCTYPE> tags are ordered opposite. But this breaks CSS validation... 
+With this option designers can decide for themselves what they want then.
+
+If you want to check the compatibility-mode of your webbrowser you can do so with a simple JavaScript that can be inserted on a TYPO3 page like this:
+
+page.headerData.1 = TEXT
+page.headerData.1.value = <script>alert(document.compatMode);</script>
+
+If your browser has detected the DOCTYPE correctly it will report “CSS1Compat”
+If you are not running in compliance mode you will get some other message. MSIE will report “BackCompat” for instance - this means it runs in quirks-mode, supporting all the old “browser-bugs”.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="enableContentLengthHeader" type="boolean">
+                       <description><![CDATA[If set, a header "content-length: [bytes of content]" is sent.
+
+If a PHP_SCRIPT_EXT object is detected on the page or if the Backend user is logged in, this is disabled. The reason is that the content length header cannot include the lenght of these objects and the content-length will cut of the lenght of the document in some browsers.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="extTarget" type="string">
+                       <description><![CDATA[default external target. Used by typolink if no extTarget is set]]></description>
+                       <default><![CDATA[_top]]></default>
+               </property>
+               <property name="forceTypeValue" type="int">
+                       <description><![CDATA[Force the &type value of all TYPO3 generated links to a specific value (except if overruled by local forceTypeValue values).
+Useful if you run a template with special content at - say &type=95 - but still wants to keep your targets neutral. Then you set your targets to blank and this value to the type value you wish.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="frameReloadIfNotInFrameset" type="boolean">
+                       <description><![CDATA[If set, then the current page will check if the page object name (eg. “page” or “frameset”) exists as “parent.[name]” (eg. “parent.page”) and if not the page will be reloaded in top frame. This secures that links from search engines to pages inside a frameset will load the frameset.
+Works only with type-values different from zero.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="ftu" type="boolean">
+                       <description><![CDATA[If set, the "&ftu=...." GET-fallback identification is inserted.
+"&ftu=[hash]" is always inserted in the links on the first page a user hits. If it turns out in the next hit that the user has cookies enabled, this variable is not set anymore as the cookies does the job. If no cookies is accepted the "ftu" remains set for all links on the site and thereby we can still track the user.
+
+You should not set this feature if grabber-spiders like Teleport are going to grab your site!
+You should not set this feature if you want search-engines to index your site (in conjunction with the simulateStaticDocuments feature!)
+
+You can also ignore this feature if you're certain, website users will use cookies.
+ "ftu" means fe_typo_user ("fe" is "frontend").]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="headerComment " type="string">
+                       <description><![CDATA[The content is added before the “TYPO3 Content Management Framework” comment in the <head> section of the page. Use this to insert a note like that “Programmed by My-Agency” ...]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="htmlTag_dir" type="string">
+                       <description><![CDATA[Sets text direction for whole document (useful for display of Arabic, Hebrew pages).
+
+Basically the value becomes the attribute value of "dir" for the <html> tag.
+
+Values:
+rtl = Right-To-Left (for Arabic / Hebrew)
+ltr = Left-To-Right (Default for other languages)
+
+Example:
+config.htmlTag_dir = rtl]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="htmlTag_langKey" type="string">
+                       <description><![CDATA[Allows you to set the language value for the attributes "xml:lang" and "lang" in the <html> tag (when using "config.doctype = xhtml*").
+
+The values must follow the format specified in IETF RFC 3066
+
+Example:
+config.htmlTag_langKey = en-US]]></description>
+                       <default><![CDATA[en]]></default>
+               </property>
+               <property name="htmlTag_setParams" type="string">
+                       <description><![CDATA[Sets the attributes for the <html> tag on the page. If you set "config.doctype" to a keyword enabling XHTML then some attributes are already set. This property allows you to override any preset attributes with you own content if needed.
+
+Special: If you set it to "none" then no attributes will be set at any event.
+
+Example:
+config.htmlTag_setParams =  xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="incT3Lib_htmlmail " type="boolean">
+                       <description><![CDATA[Include t3lib/class.t3lib_htmlmail.php]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="includeLibrary" type="string">
+                       <description><![CDATA[This includes a phpfile.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="index_descrLgd" type="int">
+                       <description><![CDATA[This indicates how many chars to preserve as description for an indexed page. This may be used in the search result display.]]></description>
+                       <default><![CDATA[200]]></default>
+               </property>
+               <property name="index_enable" type="boolean">
+                       <description><![CDATA[Enables cached pages to be indexed.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="index_externals" type="boolean">
+                       <description><![CDATA[If set, external media linked to on the pages is indexed as well.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="inlineStyle2TempFile" type="boolean">
+                       <description><![CDATA[If set, the inline styles TYPO3 controls in the core are written to a file,  typo3temp/stylesheet_[hashstring].css, and the header will only contain the link to the stylesheet.
+The file hash is based solely on the content of the styles.
+
+Depends on the compatibility mode (see Tools>Install>Update wizard):
+compatibility mode < 4.0:   0
+compatibility mode >= 4.0:   1
+
+Example:
+config.inlineStyle2TempFile = 1]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="insertDmailerBoundaries" type="boolean">
+                       <description><![CDATA[If set, boundary marks will be set around all records inserted on the page with cObjects CONTENT and RECORD. They are inserted as HTML-comments and do no harm.
+Used by the Direct Mail module in TYPO3 to segmentize a page by categories.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="intTarget" type="string">
+                       <description><![CDATA[default internal target. Used by typolink if no target is set]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="jumpurl_enable" type="boolean">
+                       <description><![CDATA[Jumpurl is a concept where external links are redirected from the index_ts.php script, which first logs which url it was. This logging of external links is only interesting if you use the internal stat-table in TYPO3.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="jumpurl_mailto_disable" type="boolean">
+                       <description><![CDATA[Disables the use of jumpUrl when linking to email-adresses.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="language" type="string">
+                       <description><![CDATA[Language key. See stdWrap.lang for more information.
+Select between:
+English  (default) = [empty]
+Danish = dk
+German = de
+Norwegian = no
+Italian = it
+etc... 
+
+Value must correspond with the key used for backend system language if there is one. See inside config_default.php or look at the translation page on TYPO3.org for the official 2-byte key for a given language. Notice that selecting the official key is important if you want labels in the correct language from "locallang" files.
+If the language you need is not yet a system language in TYPO3 you can use an artificial string of your choice and provide values for it via the TypoScript template where the property “_LOCAL_LANG” for most plugins will provide a way to override/add values for labels. The keys to use must be looked up in the locallang-file used by the plugin of course.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="language_alt" type="string">
+                       <description><![CDATA[If “config.language” (above) is used, this can be set to another language key which will be used for labels if a label was not found for the main language. For instance a brazil portuguese website might specify “pt” as alternative language which means the portuguese label will be shown if none was available in the main language, brazil portuguese. This feature makes sense if one language is incompletely translated and close to another language.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="linkVars" type="string">
+                       <description><![CDATA[HTTP_GET_VARS, which should be passed on with links in TYPO3. This is compiled into a string stored in $GLOBALS["TSFE"]->linkVars
+
+The values are rawurlencoded in PHP.
+
+You can specify a range of valid values by appending a () after each value. If this range does not match, the variable won't be appended to links. This is very important to prevent that the cache system gets flooded with forged values.
+
+The range may containing one of these values:
+[a]-[b] - A range of allowed integer valuesint - Only integer values are allowed[a]|[b]|[c] - A list of allowed strings (whitespaces will be removed)/[regex]/ - Match against a regular expression (PCRE style)
+
+Example:
+config.linkVars = L, print
+This will add "&L=[L-value]&print=[print-value]" to all links in TYPO3.
+
+config.linkVars = L(1-3), print
+Same as above, but “&L=[L-value]” will only be added if the current value is 1, 2 or 3.
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="locale_all" type="string">
+                       <description><![CDATA[PHP: setlocale("LC_ALL", [value]);
+value-examples: deutsch, de_DE, danish, portuguese, spanish, french, norwegian, italian. See www.php.net for other value. Also on linux, look at /usr/share/locale/
+
+TSFE->localeCharset is intelligently set to the assumed charset of the locale strings. This is used in stdWrap.strftime to convert locale strings to the renderCharset of the frontend.
+
+Example:
+This will render dates in danish made with stdWrap/strftime:
+locale_all = danish
+locale_all = da_DK]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="lockFilePath" type="string">
+                       <description><![CDATA[This is used to lock paths to be "inside" this path.
+Used by "filelist" in stdWrap]]></description>
+                       <default><![CDATA[fileadmin/]]></default>
+               </property>
+               <property name="mainScript" type="string">
+                       <description><![CDATA[This lets you specify an alternative "mainScript" which is the document that TYPO3 expects to be the default doc. This is used in form-tags and other places where TYPO3 needs to refer directly to the main-script of the application]]></description>
+                       <default><![CDATA[index.php]]></default>
+               </property>
+               <property name="meaningfulTempFilePrefix" type="boolean">
+                       <description><![CDATA[If set it will try to render a meaningful prefix before temporary image files.
+Works with GIFBUILDER files (taking content from the Gifbuilder TEXT objects), menus (taking the title of the menu item) and scaled images (using original filename base).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="message_page_is_being_generated" type="string">
+                       <description><![CDATA[Alternative HTML message that appears if a page is being generated.
+Normally when a page is being generated a temporary copy is stored in the cache-table with an expire-time of 30 seconds.
+
+It is possible to use some keywords that are replaced with the corresponding values. Possible keywords are: ###TITLE###, ###REQUEST_URI###]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="message_preview" type="string">
+                       <description><![CDATA[Alternative message in HTML that appears when the preview function is active!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="message_preview_workspace" type="string ">
+                       <description><![CDATA[Alternative message in HTML that appears when the preview function is active in a draft workspace. You can use sprintf() placeholders for Workspace title (first) and number (second).
+
+Examples:
+config.message_preview_workspace = <div class=”previewbox”>Displaying workspace named "%s" (number %s)!</div>
+config.message_preview_workspace = <div class=”previewbox”>Displaying workspace number %2$s named "%1$s"!</div>]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="metaCharset" type="string">
+                       <description><![CDATA[Charset used for the output document. For example in the meta tag:
+<meta http-equiv="Content-Type" content="text/html; charset=...>
+
+Is used for a) HTML meta-tag, b) HTTP header (unless disabled with .disableCharsetHeader) and c) xhtml prologues (if available)
+
+If renderCharset and metaCharset are different the output content is automatically converted to metaCharset before output and likewise are values posted back to the page converted from metaCharset to renderCharset for internal processing. This conversion takes time of course so there is another good reason to use the same charset for both.]]></description>
+                       <default><![CDATA[value of ".renderCharset"]]></default>
+               </property>
+               <property name="noPageTitle" type="int">
+                       <description><![CDATA[If you only want to have the sitename (from the template record) in your <title> tag, set this to 1. If the value is 2 then the <title> tag is not printed at all.
+Please take note that this tag is required for XHTML compliant output, so you should only disable this tag if you generate it manually already.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="noScaleUp" type="boolean">
+                       <description><![CDATA[Normally images are scaled to the size specified via TypoScript. This also forces small images to be scaled to a larger size. This is not always a good thing. 
+If this property is set, images are not allowed to be scaled up in size. This parameter clears the $this->mayScaleUp var of the class t3lib_stdgraphics (often "gifbuilder").]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="no_cache" type="boolean">
+                       <description><![CDATA[If this is set to true, the page will not be cached. If set to false, it's ignored. Other parameters may have set it to true of other reasons.]]></description>
+                       <default><![CDATA[-]]></default>
+               </property>
+               <property name="notification_email_charset" type="string">
+                       <description><![CDATA[Alternative charset for the notification mails.]]></description>
+                       <default><![CDATA[ISO-8859-1]]></default>
+               </property>
+               <property name="notification_email_encoding" type="string">
+                       <description><![CDATA[This sets the encoding of plaintext emails (notification messages). The default encoding is “quoted-printable”. But setting this to eg. “base64” will encode the content with base64 encoding.
+
+Values possible:
+base64
+quoted-printable
+8bit]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="notification_email_urlmode" type="string">
+                       <description><![CDATA[This option allows you to handle URL's in plain text emails so long URLS of more than 76 chars are not broken. This option can be either empty or “76” or “all”. 
+If the string is blank, all links in plaintext emails are untouched. 
+If it's set to 76 then all links longer then 76 characters are stored in the database and a hash is sent in the GET-var ?RDCT=[md5/20] to the index.php script which finds the proper link in the database and issues a location header (redirection). 
+If the value is “all” then ALL “http://” links in the message are converted.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="pageGenScript" type="string">
+                       <description><![CDATA[Alternative page generation script for applications using index_ts.php for initialization, caching, stating and so on. This script is included in the global scope of index_ts.php-script and thus you may include libraries here. Always use include_once for libraries.
+Remember not to output anything from such an included script. All content must be set into $TSFE->content. Take a look at typo3/sysext/cms/tslib/pagegen.php
+
+NOTE: This option is ignored if 
+
+$TYPO3_CONF_VARS["FE"]["noPHPscriptInclude"]=1;
+
+is set in localconf.php.]]></description>
+                       <default><![CDATA[typo3/sysext/cms/tslib/pagegen.php]]></default>
+               </property>
+               <property name="pageTitleFirst" type="boolean">
+                       <description><![CDATA[If set (and the page title is printed) then the page-title will be printed BEFORE the template title.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="prefixLocalAnchors" type="string">
+                       <description><![CDATA[If set to one of the keywords, the content will have all local anchors in links prefixed with the path of the script. Basically this means that <a href=”#”> will be transformed to <a href=”path/path/script?params#”>. This procedure is necessary if the <base> tag is set in the script (eg. if “realurl” extension is used to produce Speaking URLs).
+
+Keywords are the same as for “xhtml_cleaning”, see above.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="removeDefaultJS" type="string">
+                       <description><![CDATA[If set, the default JavaScript in the header will be removed.
+The default JavaScript is the blurLink function and browser detection variables.
+
+Special case: if the value is "external" then the default JavaScript is written to a temporary file and included from that file. See "inlineStyle2TempFile" below.
+
+Depends on the compatibility mode (see Tools>Install>Update wizard):
+compatibility mode < 4.0:   0
+compatibility mode >= 4.0:   1
+
+Example:
+config.removeDefaultJS = external
+config.removeDefaultJS = 1]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="renderCharset" type="string">
+                       <description><![CDATA[Charset used for rendering internally of the page content. It is highly recommended that this value is the same as the charset of the content coming from the main data source (eg. the database). Thus you don't need to do any other conversion.
+All strings from locallang files and locale strings are (and should be) converted to "renderCharset" during rendering. 
+
+If you need another output charset than the render charset, see "metaCharset" below. 
+
+If you set TYPO3_CONF_VARS['BE']['forceCharset'] that value is used by default for "renderCharset". It is highly recommended to use TYPO3_CONF_VARS['BE']['forceCharset'] for multilingual websites in TYPO3. If you set that you don't have to worry about renderCharset and metaCharset - the same charset is used in the whole system.]]></description>
+                       <default><![CDATA[TYPO3_CONF_VARS[BE][forceCharset] if found, otherwise
+"iso-8859-1"]]></default>
+               </property>
+               <property name="sendCacheHeaders" type="boolean">
+                       <description><![CDATA[If set, TYPO3 will output cache-control headers to the client based mainly on  whether the page was cached internally. This feature allows client browsers and/or reverse proxies to take load of TYPO3 websites.
+
+The conditions for allowing client caching are:
+page was cachedNo *_INT or *_EXT objects were on the page (eg. USER_INT)No frontend user is logged inNo backend user is logged in
+
+If these conditions are met, the headers sent are:
+Last-Modified [SYS_LASTCHANGED of page id]Expires [expire time of page cache]Etag [md5 of content]Cache-Control: max-age: [seconds til expiretime]Pragma: public
+
+In case caching is not allowed, these headers are sent to avoid client caching:
+Cache-Control: private
+
+Notice that enabling the browser caches means you have to consider how log files are written. Because when a page is cached on the client it will not invoke a request to the webserver, thus not writing the request to the log. There should be ways to circumvent these problems but they are outside the domain of TYPO3 in any case.
+
+Tip: Enabling cache-control headers might confuse editors seeing old content served from the browser cache. “Shift-Reload” will bypass both browser- and reverse-proxy caches and even make TYPO3 regenerate the page. Teach them that trick!
+
+Thanks to Ole Tange, www.forbrug.dk for co-authoring this feature.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sendCacheHeaders_onlyWhenLoginDeniedInBranch" type="boolean">
+                       <description><![CDATA[If this is set, then cache-control headers allowing client caching is sent only if user-logins are disabled for the branch. This feature makes it easier to manage client caching on sites where you have a mixture of static pages and dynamic sections with user logins. 
+
+The background problem is this: In TYPO3 the same URL can show different content depending on whether a user is logged in or not. If a user is logged in, cache-headers will never allow client caching. But if the same URL was visited without a login prior to the login (allowing caching) the user will still see the page from cache when logged in (and so thinks he is not logged in anyway)! The only general way to prevent this is to have a different URL for pages when users are logged in (which the extension “realurl” can accomplish).
+
+Another way to solve the problem is using this option in combination with disabling and enabling logins in various sections of the site. In the page records (“Advanced” page types) you can disable frontend user logins for branches of the page tree. Since many sites only needs the login in a certain branch of the page tree, disabling it in all other branches makes it much easier to use cache-headers in combination with logins; Cache-headers should simply be sent when logins are not allowed and never be send when logins are allowed! Then there will never be problems with logins and same-URLs.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="setJS_mouseOver" type="boolean">
+                       <description><![CDATA[If set, the over() and out() JavaScript functions are forced to be included]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="setJS_openPic" type="boolean">
+                       <description><![CDATA[If set, the openPic JavaScript function is forced to be included]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments" type="string">
+                       <description><![CDATA[boolean/string
+                       If set TYPO3 makes all links in another way than usual. This can be used with Apache compiled with mod_rewrite and configured in httpd.conf for use of this in the ".htaccess"-files.
+Include this in the .htaccess file
+RewriteEngine On
+RewriteRule   ^[^/]*\.html$  index.php
+
+This means that any "*.html"-documents should be handled by index.php. 
+Now if is done, TYPO3 will interprete the url of the html-document like this:
+[title].[id].[type].html
+Title is optional and only usefull for the entries in the apache log-files. You may omit both [title] and [type] but if title is present, type must also be there!. 
+
+Example:
+TYPO3 will interprete this as page with uid=23 and type=1 :
+Startpage.23.1.html
+
+TYPO3 will interprete this as the page with alias = "start" and the type is zero (default):
+start.html
+
+Alternative option (PATH_INFO):
+Instead of using the rewrite-module in apache (eg. if you're running Windows!) you can use the PATH_INFO variable from PHP.
+It's very simple. Just set simulateStaticDocuments to “PATH_INFO” and you're up and running!
+
+Also: See below, .absRefPrefix
+
+Example (put in Setup-field of your template):
+config.simulateStaticDocuments = PATH_INFO]]></description>
+                       <default><![CDATA[default is defined by a configuration option in localconf.php. It's 
+$TYPO3_CONF_VARS["FE"]["simulateStaticDocuments"] = 1;
+This affects all sites in the database.
+You can also set this value to the string  “PATH_INFO”]]></default>
+               </property>
+               <property name="simulateStaticDocuments_addTitle" type="int">
+                       <description><![CDATA[If not zero, TYPO3 generates urls with the title in, limited to the first [simulateStaticDocuments_addTitle] number of chars.
+
+Example:
+Startpage.23.1.html
+instead of the default, "23.1.html", without the title.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments_dontRedirectPathInfoError" type="boolean">
+                       <description><![CDATA[Regarding PATH_INFO mode:
+When a page is requested by “PATH_INFO” method it must be configured in order to work properly. If PATH_INFO is not configured, the index_ts.php script sends a location header to the correct page. However if you better like an error message outputted, just set this option.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments_noTypeIfNoTitle" type="boolean">
+                       <description><![CDATA[If set, then the type-value will not be set in the simulated filename if the type value is zero anyways. However the filename must be without a title. 
+
+Example:
+“Startpage.23.0.html” would still be “Startpage.23.0.html”
+“23.0.html” would be “23.html” (that is without the zero)
+“23.1.html” would still be “23.1.html” ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments_pEnc" type="string">
+                       <description><![CDATA[Allows you to also encode additional parameters into the simulated filename. 
+
+Example: 
+You have a news-plugin. The main page has the url “Page_1.228.0.html” but when one clicks on a news item the url will be “Page_1.228.0.html?&tx_mininews_pi1[showUid]=2&cHash=b8d239c224” instead.
+Now, this URL will not be indexed by external search-engines because of the query-string (everything after the “?” mark). This property avoids this problem by encoding the parameters. These are the options:
+
+Value set to “base64”:
+This will transform the filename used to this value: “Page_1.228+B6JnR4X21pbmluZXdzX3BpMVtzaG93VWlkXT0yJmNIYXNoPWI4ZDIzOWMyMjQ_.0.html”. The querystring has simply been base64-encoded (and some more...) and added to the HTML-filename (so now external search-engines will find this!). The really great thing about this that the filename is self-reliant because the filename contains the parameters. The downside to it is the very very long filename.
+
+Value set to “md5”:
+This will transform the filename used to this value:
+“Page_1.228+M57867201f4a.0.html”. Now, what a lovely, short filename! Now all the parameters has been hashed into a 10-char string inserted into the filename. At the same time an entry has been added to a cache table in the database so when a request for this filename reaches the frontend, then the REAL parameter string is found in the database! The really great thing about this is that the filename is very short (opposite to the base64-method). The downside to this is that IF you clear the database cache table at any time, the URL here does NOT work until a page with the link has been generated again (re-inserting the parameter list into the database).
+
+NOTICE: From TYPO3 3.6.0 the encoding will work only on parameters that are manually entered in the list set by .simulateStaticDocuments_pEnc_onlyP (see right below) or those parameters that various plugins might allow in addition. This is to limit the run-away risk when many parameters gets combined.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments_pEnc_onlyP" type="string">
+                       <description><![CDATA[A list of variables that may be a part of the md5/base64 encoded part of a simulate_static_document virtual filename (see property in the row above).
+
+Example:
+simulateStaticDocuments_pEnc_onlyP = tx_maillisttofaq_pi1[pointer], L, print
+
+-> this will allow the "pointer" parameter for the extension "maillisttofaq" to be included (in addition to whatever vars the extension sets itself) and further the parameter "L" (could be language selection) and "print" (could be print-version).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="simulateStaticDocuments_replacementChar" type="string">
+                       <description><![CDATA[Word separator for URLs generated by simulateStaticDocuments. If set to
+hyphen, this option allows search engines to index keywords in URLs. Before TYPO3 4.0 this character was hard-coded to underscore.
+
+Depends on the compatibility mode (see Tools>Install>Update wizard):
+compatibility mode < 4.0:   underscore “_”
+compatibility mode >= 4.0:   hyphen “-”]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="spamProtectEmailAddresses" type="string">
+                       <description><![CDATA[&quot;ascii&quot; / -10 to 10
+                       If set, then all email addresses in typolinks will be encrypted so spam bots cannot detect them.
+
+If you set this value to a number, then the encryption is simply an 
+offset of character values. If you set this value to "-2" then all 
+characters will have their ASCII value offset by "-2". To make this 
+possible, a little JavaScript code is added to every generated web page!
+(It is recommended to set the value in the range from -5 to 1 since setting it to >= 2 means a “z” is converted to “|” which is a special character in TYPO3 tables syntax – and that might confuse columns in tables. Now hardcoded range)
+
+Alternatively you can set this value to the keyword "ascii". This way every 
+character of the "mailto:" address will be translated to a Unicode HTML 
+notation. Have a look at the example to see how this works.
+
+Example:
+mailto:a@b.c will be converted to
+mailto:&#97;&#64;&#98;&#46;&#99;
+The big advantage of this method is that it doesn't need any JavaScript!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="spamProtectEmailAddresses_atSubst" type="string">
+                       <description><![CDATA[Substitute label for the at-sign (@).]]></description>
+                       <default><![CDATA[(at)]]></default>
+               </property>
+               <property name="spamProtectEmailAddresses_lastDotSubst" type="string">
+                       <description><![CDATA[Substitute label for the last dot in the email address.
+Example: (dot)]]></description>
+                       <default><![CDATA[Default: . ( <= just a simple dot)]]></default>
+               </property>
+               <property name="stat" type="boolean">
+                       <description><![CDATA[Enable stat logging at all.]]></description>
+                       <default><![CDATA[true]]></default>
+               </property>
+               <property name="stat_apache" type="boolean">
+                       <description><![CDATA[Enable logging to the logfile "stat_apache_logfile"]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="stat_apache_logfile" type="string">
+                       <description><![CDATA[This defines the name of the logfile where TYPO3 writes an Apache-style logfile to. The location of the directory is defined by $TYPO3_CONF_VARS["FE"]["logfile_dir"]  which must exist and be writable. It can be relative (to PATH_site) or absolute, but in any case it must be within the regular allowed paths of TYPO3 (meaning for absolute paths that it must be within the “lockRootDir” set up in $TYPO3_CONF_VARS).
+
+It is also possible to use date markers in the filename as they are provided by the PHP function strftime(). This will enable a natural rotation of the logfiles.
+
+Example:
+config.stat_apache_logfile = typo3_%Y%m%d.log
+
+This will create daily log files (eg. typo3_20060321.log).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_apache_niceTitle" type="string">
+                       <description><![CDATA[boolean / string
+                       If set, the URL will be transliterated from the renderCharset to ASCII (eg ä => ae, à => a, &#945; "alpha" => a), which yields nice and readable page titles in the log. All non-ASCII characters that cannot be converted will be changed to underscores.
+
+If set to “utf-8”, the page title will be converted to UTF-8 which results 
+in even more readable titles, if your log analyzing software supports it.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_apache_noHost" type="boolean">
+                       <description><![CDATA[If true the HTTP_HOST is - if available - NOT inserted instead of the IP-address]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_apache_noRoot" type="boolean">
+                       <description><![CDATA[If set, the root part (level 0) of the path will be removed from the path. This makes a shorter name in case you have only a redundant part like "home" or "my site".]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_apache_notExtended" type="boolean">
+                       <description><![CDATA[If true the logfile is NOT written in Apache extended format]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_apache_pagenames" type="string">
+                       <description><![CDATA[The "pagename" simulated for apache.
+Default:    "[path][title]--[uid].html"
+Codes:
+[title] = inserts title, no special characters and shortend to 30 chars.
+[uid] = the id
+[alias] = any alias
+[type] = the type (typeNum)
+[path] = the path of the page.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_excludeBEuserHits" type="boolean">
+                       <description><![CDATA[If set a pagehit is not logged if a user is logged in into TYPO3.]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="stat_excludeIPList" type="string">
+                       <description><![CDATA[list of strings
+                       If the REMOTE_ADDR is in the list of IP-addresses, it's also not logged.
+Can use wildcard, eg. “192.168.1.*”]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stat_mysql" type="boolean">
+                       <description><![CDATA[Enable logging to the MySQL table sys_stat.]]></description>
+                       <default><![CDATA[false]]></default>
+               </property>
+               <property name="stat_pageLen" type="int">
+                       <description><![CDATA[int 1-100
+                       The length of the page name (at the end of the path) written to the logfile/database.]]></description>
+                       <default><![CDATA[30]]></default>
+               </property>
+               <property name="stat_titleLen" type="int">
+                       <description><![CDATA[int 1-100
+                       The length of the page names in the path written to logfile/database]]></description>
+                       <default><![CDATA[20]]></default>
+               </property>
+               <property name="stat_typeNumList" type="intList">
+                       <description><![CDATA[List of pagetypes that should be registered in the statistics table, sys_stat.
+If no types are listed, all types are logged.
+Default is "0,1" which normally logs all hits on framesets and hits on content keeping pages. Of course this depends on the template design.]]></description>
+                       <default><![CDATA[0,1]]></default>
+               </property>
+               <property name="sword_noMixedCase" type="boolean">
+                       <description><![CDATA[Used by the parseFunc-substitution of search Words (sword):
+If set, the words MUST be the exact same case as the search word was.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sword_standAlone" type="boolean">
+                       <description><![CDATA[Used by the parseFunc-substitution of search Words (sword):
+If set, the words MUST be surrounded by whitespace in order to be marked up.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sys_language_mode" type="string">
+                       <description><![CDATA[Setting various modes of handling localization.
+The syntax is "[keyword] ; [value]".
+
+Possible keywords are:
+
+[default] - The system will look for a translation of the page (from “Alternative Page Language” table) and if it is not found it will fall back to the default language and display that.
+
+content_fallback - [ Recommended ] The system will always operate with the selected language even if the page is not translated with a page overlay record. This will keep menus etc. translated. However, the content on the page can still fall back to another language, defined by the value of this keyword, eg. "content_fallback ; 1,0" to fall back to the content of sys_language_uid 1 and if that is not present either, to default (0)
+
+strict - The system will report an error if the requested translation does not exist. Basically this means that all pages with gray background in the Web>Info / Localization overview module will fail (they would otherwise fall back to default language in one or another way)
+
+ignore - The system will stay with the selected language even if the page is not translated and there's no content available in this language, so you can handle that situation on your own then.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sys_language_overlay" type="string">
+                       <description><![CDATA[boolean / keyword
+                       If set, records from certain tables selected by the CONTENT cObject using the “languageField” setting will select the default language (0) instead of any language set by sys_language_uid / sys_language_mode. In addition the system will look for a translation of the selected record and overlay configured fields.
+The requirements for this is that the table is configured with “languageField” and “transOrigPointerField” in the [ctrl] section of $TCA. Also, exclusion of certain fields can be done with the “l10n_mode” directive in the field-configuration of $TCA.
+
+For backend administration this requires that you configure the “Web>Page” module to display content elements accordingly; That each default element is shown and next to it any translation found. This configuration can be done with Page TSconfig for a section of the website using the object path “mod.web_layout.defLangBinding = 1”.
+
+Keyword: 
+hideNonTranslated : If this keyword is used a record that has no translation will not be shown. The default is that records with no translation will show up in the default language.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sys_language_softExclude" type="string">
+                       <description><![CDATA[Setting additional "exclude" flags for l10n_mode in TCA for frontend rendering. Works exactly like sys_language_softMergeIfNotBlank (see that for details - same Syntax!).
+
+Fields set in this property will override if the same field is set for "sys_language_softMergeIfNotBlank".]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sys_language_softMergeIfNotBlank" type="string">
+                       <description><![CDATA[Setting additional “mergeIfNotBlank” fields from TypoScript.
+
+Background:
+In TCA you can configure “l10n_mode” - localization mode - for each field. Two of the options affect how the frontend displays content; The values “exclude” and “mergeIfNotBlank” (see “TYPO3 Core API” document for details). The first (“exclude”) simply means that the field when found in a translation of a record will not be overlaid the default records field value. The second (“mergeIfNotBlank”) means that it will be overlaid only if it has a non-blank value.
+Since it might be practical to set up fields for “mergeIfNotBlank” on a per-site basis this options allows you to override additional fields from tables.
+
+Syntax:
+ [table]:[field],  [table]:[field],  [table]:[field], ...
+
+Example:
+config.sys_language_softMergeIfNotBlank = tt_content:image , tt_content:header
+
+This setting means that the header and image field of content elements will be used from the translation only if they had a non-blank value. For the image field this might be very practical because it means that the image(s) from the default translation will be used unless other images are inserted!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sys_language_uid" type="int">
+                       <description><![CDATA[This value points to the uid of a record from the “sys_language” table and if set, this means that various parts of the frontend display code will select records which are assigned to this language. See ->SELECT
+
+Internally, the value is depending on whether a Alternative Page Language record can be found with that language. If not, the value will default to zero (default language) except if “sys_language_mode” is set to a value like “content_fallback”.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="titleTagFunction " type="string">
+                       <description><![CDATA[function-name
+                       Passes the default <title>-tag content to this function. No typoScript parameters are passed though.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="typolinkCheckRootline" type="boolean">
+                       <description><![CDATA[If set, then every “typolink” is checked whether it's linking to a page within the current rootline of the site.
+If not, then TYPO3 searches for the first found domain record (without redirect) in that rootline from out to in. 
+If found (another domain), then that domain is prepended the link, the external target is used instead and thus the link jumps to the page in the correct domain.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="typolinkLinkAccessRestrictedPages" type="string">
+                       <description><![CDATA[integer (page id) / keyword “NONE"
+                       If set, typolinks pointing to access restricted pages will still link to the page even though the page cannot be accessed. If the value of this setting is an integer it will be interpreted as a page id to which the link will be directed. 
+If the value is “NONE” the original link to the page will be kept although it will generate a page-not-found situation (which can of course be picked up properly by the page-not-found handler and present a nice login form).
+
+See “showAccessRestrictedPages” for menu objects as well (similar feature for menus)
+
+Example:
+config.typolinkLinkAccessRestrictedPages = 29
+config.typolinkLinkAccessRestrictedPages_addParams = &return_url=###RETURN_URL###&pageId=###PAGE_ID###
+
+Will create a link to page with id 29 and add GET parameters where the return URL and original page id is a part of it.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="typolinkLinkAccessRestrictedPages_addParams" type="string">
+                       <description><![CDATA[See “typolinkLinkAccessRestrictedPages” above]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="uniqueLinkVars" type="boolean">
+                       <description><![CDATA[It might happen that TYPO3 generates links with the same parameter twice or more. This is no problem because only the last parameter is used, thus the problem is just a cosmetical one.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="xhtmlDoctype" type="string">
+                       <description><![CDATA[Sets the document type for the XHTML version of the generated page.
+
+If config.doctype is set to a string then config.xhtmlDoctype must be set to one of these keywords:
+
+"xhtml_trans" for XHTML 1.0 Transitional doctype.
+"xhtml_frames" for XHTML 1.0 Frameset doctype.
+"xhtml_strict" for XHTML 1.0 Strict doctype.
+"xhtml_basic" for XHTML basic doctype.
+"xhtml_11" for XHTML 1.1 doctype.
+"xhtml_2" for XHTML 2 doctype.
+
+
+This is an example to use MathML 2.0 in an XHTML 1.1 document:
+
+config.doctype (
+<!DOCTYPE html
+PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
+"http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd">
+)
+config.xhtmlDoctype = xhtml_11
+
+Default:
+same as config.doctype if set to a keyword]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="xhtml_cleaning" type="string">
+                       <description><![CDATA[Tries to clean up the output to make it XHTML compliant and a bit more. THIS IS NOT COMPLETE YET, but a “pilot” to see if it makes sense anyways. For now this is what is done:
+
+What it does at this point:
+- All tags (img,br,hr) is ended with "/>" - others?
+- Lowercase for elements and attributes
+- All attributes in quotes
+- Add "alt" attribute to img-tags if it's not there already.
+
+What it does NOT do (yet) according to XHTML specs.:
+- Wellformedness: Nesting is NOT checked
+- name/id attribute issue is not observed at this point.
+- Certain nesting of elements not allowed. Most interesting, <PRE> cannot contain img, big,small,sub,sup ...
+- Wrapping scripts and style element contents in CDATA - or alternatively they should have entitites converted.
+- Setting charsets may put some special requirements on both XML declaration/ meta-http-equiv. (C.9)
+- UTF-8 encoding is in fact expected by XML!!
+- stylesheet element and attribute names are NOT converted to lowercase
+- ampersands (and entities in general I think) MUST be converted to an entity reference! (&amps;). This may mean further conversion of non-tag content before output to page. May be related to the charset issue as a whole.
+- Minimized values not allowed: Must do this: selected="selected"
+
+Please see the class t3lib_parsehtml for details.
+You can enable this function by the following values:
+
+all = the content is always processed before it may be stored in cache. 
+cached = only if the page is put into the cache, 
+output = only the output code just before it's echoed out.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="xmlprologue" type="string">
+                       <description><![CDATA[If empty (not set) then the default XML 1.0 prologue is set, when the doctype is set to a known keyword (eg xhtml_11):
+
+<?xml version="1.0" encoding="[config.renderCharset]">
+
+If set to one of the know keywords then a standard prologue will be set:
+“xml_10” XML 1.0 prologue (see above)
+“xml_11” XML 1.1 prologue
+
+If "none" then the default XML prologue is not set.
+Any other string is used as the XML prologue itself.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="CONTENT">
+               <property name="renderObj" type="cObj">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[< [tablename]]]></default>
+               </property>
+               <property name="select" type="string">
+                       <description><![CDATA[The SQL-statement is set here!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="slide" type="int">
+                       <description><![CDATA[If set and no content element is found by the select command, then the rootLine will be traversed back until some content is found.
+
+Possible values are “-1” (slide back up to the siteroot), “1” (only the current level) and “2” (up from one level back).
+
+Use -1 in combination with collect.
+
+.collect (integer): If set, all content elements found on current and parent pages will be collected. Otherwise, the sliding would stop after the first hit. Set this value to the amount of levels to collect on, or use “-1” to collect up to the siteroot.
+.collectFuzzy (boolean): Only useful in collect mode. If no content elements have been found for the specified depth in collect mode, traverse further until at least one match has occurred.
+.collectReverse (boolean): Change order of elements in collect mode. If set, elements of the current page will be on the bottom.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="table" type="string">
+                       <description><![CDATA[The table, the content should come from. 
+In standard-configurations this will be "tt_content"
+NOTE: Only tables allowed are “pages” or tables prefixed with one of these: “tt_”, “tx_”, “ttx_”, “fe_”, “user_”]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[Wrap the whole content-story...]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="CTABLE">
+               <property name="bm" type="CARRAY+TDParams">
+                       <description><![CDATA[bottomMenu]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="c" type="CARRAY+TDParams">
+                       <description><![CDATA[content-cell ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="cMargins" type="string">
+                       <description><![CDATA[margins
+                       Distance around the content-cell "c"]]></description>
+                       <default><![CDATA[0,0,0,0]]></default>
+               </property>
+               <property name="cWidth" type="string">
+                       <description><![CDATA[pixels
+                       Width of the content-cell "c"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="lm" type="CARRAY+TDParams">
+                       <description><![CDATA[leftMenu]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y 
+                       Offset from upper left corner]]></description>
+                       <default><![CDATA[0,0 = intet]]></default>
+               </property>
+               <property name="rm" type="CARRAY+TDParams">
+                       <description><![CDATA[rightMenu]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="tableParams" type="string">
+                       <description><![CDATA[<TABLE>-params
+]]></description>
+                       <default><![CDATA[border=0 cellspacing=0 cellpadding=0]]></default>
+               </property>
+               <property name="tm" type="CARRAY+TDParams">
+                       <description><![CDATA[topMenu]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="EDITPANEL">
+               <property name="allow" type="string">
+                       <description><![CDATA[Define which functions are accessible. Further this list may be reduced, if the BE_USER does not have permission to perform the action
+Values should be listed separated by comma. This is the options you can choose between:
+toolbar,edit,new,delete,move,hide 
+(toolbar is a general list of icons regarding the page, so use this for pagerecords only)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="edit.displayRecord" type="boolean">
+                       <description><![CDATA[If set, then the record edited is displayed above the editing form.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="innerWrap" type="wrap">
+                       <description><![CDATA[Wraps the edit panel]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="label" type="string">
+                       <description><![CDATA[Title for the panel. You can insert the record title with %s
+
+Example:
+Section: <B>%s</B>]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="line" type="int">
+                       <description><![CDATA[boolean / int
+                       If set, a black line will appear after the panel. This value will indicate the distance from the black line to the panel]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="newRecordFromTable" type="string">
+                       <description><![CDATA[Will display a panel for creation of new element (in the top of list) on the page from that table.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="newRecordInPid" type="int">
+                       <description><![CDATA[Define a page ID where new records (except new pages) will be created.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="onlyCurrentPid" type="boolean">
+                       <description><![CDATA[If set, only records with a pid matching the current id (TSFE->id) will be shown with the panel.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="outerWrap" type="wrap">
+                       <description><![CDATA[Wraps the whole edit panel including the black line (if configured)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="previewBorder" type="int">
+                       <description><![CDATA[boolean / int 
+                       If set, the hidden/starttime/endtime/fe_user elements which are previewed will have a border around.
+The integer value denotes the thickness of the border]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="previewBorder.innerWrap" type="string">
+                       <description><![CDATA[wrap / HTML color
+                       innerWrap wraps the content elements (including the icons) inside the preview border (an HTML table). 
+
+outerWrap wraps the whole content element including the border. 
+
+color denotes the color of the border.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="FE_TABLE">
+               <property name="allowEdit" type="string">
+                       <description><![CDATA[allowEdit.[field]
+                       Same as above ("allowNew") but this controls which fields that may be written in case of an update of a record (and not a new submission)
+Please pay attension to the property below!  ("overrideEdit")]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="allowNew" type="string">
+                       <description><![CDATA[allowNew.[field]
+                       This property is in charge of which fields that may be written from the frontend.
+
+Example:
+This defines that subject is a field, that may be submitted from the frontend. If a value is not submitted, subject is filled with the default value (see above). 
+The field "hidden" on the other hand cannot be changed from the frontend. "hidden" will gain the value from the default definition (see above). If fields are set to "0" (zero) it's the same as if they were not defined in this array.
+
+allowNew {
+  subject = 1
+  hidden = 0
+}]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="autoInsertPID" type="boolean">
+                       <description><![CDATA[Works with new records: Insert automatically the PID of the page, where the submitted data is sent to. Any "pid" supplied from the submitted data will override. This is for convenience.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="default" type="string">
+                       <description><![CDATA[default.[field] This property is in charge of which default-values is used for the table:
+
+Example:
+This defines the default values used for new records. These values will be overridden with any value submitted instead (as long as the submitted fields are allowed due to "allowNew")
+default {
+  subject = This is the default subject value!
+  hidden = 1
+  parent = 0
+}]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="doublePostCheck" type="string">
+                       <description><![CDATA[string (fieldname)
+                       Specifies a fieldname (integer) into which an integer-hash compiled of the submitted data is inserted. If the field is set, then submissions are checked whether another record with this value already exists. If so, the record is NOT inserted, because it's expected to be a “double post” (posting the same data more than once)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="overrideEdit" type="string">
+                       <description><![CDATA[This works like default-values above but is values inserted after the submitted values has beed processed. This means that opposite to default-values overwritten by the submitted values, these values override the submitted values.
+
+Example:
+In this case overrideEdit secures that if a user updates his record (if he "own" it) the "hidden"-field will be set no matter what.
+
+overrideEdit {
+  hidden = 1
+}]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="processScript" type="string">
+                       <description><![CDATA[Include-script to be used for processing of incoming data to the table. The script is included from a function in the class tslib_fetce
+This is the really important option, because whether or not you are going to utilize the "cleaning"/"authorization" features of the properties above depend on how you write your script to process data and put it in the database.
+A very good example is to look at "media/scripts/guest_submit.inc", included from static_template "plugin.tt_guest" (Used for the default guestbook feature)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="separator" type="string">
+                       <description><![CDATA[Separator character used when the submitted data is an array from eg. a multiple selector box.]]></description>
+                       <default><![CDATA[chr(10) (linebreak)]]></default>
+               </property>
+               <property name="userIdColumn" type="string">
+                       <description><![CDATA[string (field)
+                       This is a string that points to the column of a record where the user-id of the current fe_user should be inserted. This fe_user-uid is inserted/updated both by "new" and "edit"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="FILE">
+               <property name="altText" type="stdWrap">
+                       <description><![CDATA[For <img> output only!
+
+If no titltext is specified, it will use the alttext insteadIf no alttext is specified, it will use an empty alttext]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="file" type="string">
+                       <description><![CDATA[resource
+                       If the resource is jpg,gif,jpeg,png the image is inserted as an image-tag. Al other formats is read and inserted into the HTML-code.
+The maximum filesize of documents to be read is set to 1024 kb internally!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="linkWrap" type="wrap">
+                       <description><![CDATA[(before ".wrap")]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="longdescURL" type="stdWrap">
+                       <description><![CDATA[For <img> output only!
+
+"longdesc" attribute (URL pointing to document with extensive details about image).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="FORM_dataArray">
+               <property name="10" type="FORM_dataArray_element">
+                       <description><![CDATA[alternative way to define form Elements]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="20" type="FORM_dataArray_element">
+                       <description><![CDATA[alternative way to define form Elements]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="30" type="FORM_dataArray_element">
+                       <description><![CDATA[alternative way to define form Elements]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="40" type="FORM_dataArray_element">
+                       <description><![CDATA[alternative way to define form Elements]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+       </type>
+       <type id="FORM_dataArray_element">
+               <property name="label" type="string">
+                       <description><![CDATA[]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="type" type="string">
+                       <description><![CDATA[]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="name" type="string">
+                       <description><![CDATA[]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="value" type="string">
+                       <description><![CDATA[]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+               <property name="required" type="boolean">
+                       <description><![CDATA[]]></description>
+                       <default><![CDATA[]]></default>
+               </property>
+       </type>
+       <type id="FORM">
+               <property name="CHECK.layout" type="string">
+                       <description><![CDATA[Alternative layout for checkboxes]]></description>
+                       <default><![CDATA[the "layout"-property]]></default>
+               </property>
+               <property name="COMMENT.layout" type="string">
+                       <description><![CDATA[Alternative layout for comments.]]></description>
+                       <default><![CDATA[the "layout"-property]]></default>
+               </property>
+               <property name="LABEL.layout" type="string">
+                       <description><![CDATA[Alternative layout for label types]]></description>
+                       <default><![CDATA[the "layout"-property]]></default>
+               </property>
+               <property name="RADIO.layout" type="string">
+                       <description><![CDATA[Alternative layout for radiobuttons]]></description>
+                       <default><![CDATA[the "layout"-property]]></default>
+               </property>
+               <property name="REQ" type="REQ">
+                       <description><![CDATA[boolean 
+                       Defines if required-fields should be checked and marked up]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="accessibility" type="boolean">
+                       <description><![CDATA[If set, then the form will be compliant with accessibility guidelines (XHTML compliant). This includes:
+
+label string will be wrapped in <label for="formname[fieldname-hash]"> ... </label>All form elements will have an id-attribute carrying the formname with the md5-hashed fieldname appended
+
+Notice: In TYPO3 4.0 and later, CSS Styled Content is configured to produce accessible forms by default.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="arrayReturnMode" type="boolean">
+                       <description><![CDATA[If set, the <form> tags and the form content will be returned in an array as separate elements including other pratical values. This mode is for use in extensions where the array return value can be more useful.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="badMess" type="string">
+                       <description><![CDATA[Prefixed Message for the formevaluation in case of missing required fields. 
+This message is shown above the list of fields.
+
+NOTE: May be overridden by the property override feature of the formdata (see above)]]></description>
+                       <default><![CDATA[No message]]></default>
+               </property>
+               <property name="commentWrap" type="stdWrap">
+                       <description><![CDATA[Comments: Wrap for comments IF you use ###COMMENT###]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="compensateFieldWidth" type="double">
+                       <description><![CDATA[Overriding option to the config-value of the same name. See "CONFIG" above.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="data" type="stdWrap">
+                       <description><![CDATA[This is the data that sets up the form. See above.
+"||" can be used instead of linebreaks]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="dataArray" type="FORM_dataArray">
+                       <description><![CDATA[This is an alternative way to define the form-fields. Instead of using the syntax with vertical separator bars suggested by the .data property, you can define the elements in regular TypoScript style arrays.
+.dataArray is added to the input in .data if any.
+Every entry in the dataArray is numeric and has three main properties, label, type, value and required. 'label' and 'value' has stdWrap properties. 
+There is an alternative property to .value, which is .valueArray. This is also an array in the same style with numeric entries which has properties label, value and selected. 'label' has stdWrap properties.
+
+Example:
+  dataArray {
+    10.label = Name:
+    10.type = name=input
+    10.value = [Enter name]
+    10.required = 1
+    20.label = Eyecolor
+    20.type = eyecolor=select
+    20.valueArray {
+      10.label = Blue
+      10.value = 1
+      20.label = Red
+      20.value = 2
+      20.selected = 1
+    }
+    40.type = submit=submit
+    40.value = Submit
+  }
+
+
+This is the same as this line in the .data property:
+
+Name: | *name=input | [Enter name]
+Eyecolor: | eyecolor=select | Blue=1, *Red=2
+| submit=submit | Submit
+
+Why do it this way?  Good question, but doing it this way has a tremendous advantage because labels are all separated from the codes. In addition it's much easier to pull out or insert new elements in the form.
+Inserting an email-field after the name field would be like this:
+  dataArray {
+    15.label = Email:
+    15.type = input
+    15.value = your@email.com
+    15.specialEval = EMAIL
+  }
+
+Or translating the form to danish (setting config.language to 'dk'):
+
+  dataArray {
+    10.label.lang.dk = Navn:
+    10.value.lang.dk = [Indtast dit navn]
+    20.label.lang.dk = Øjenfarve
+    20.valueArray {
+      10.label.lang.dk = Blå
+      20.label.lang.dk = Rød
+    }
+    40.value.lang.dk = Send
+  }
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="dontMd5FieldNames" type="boolean">
+                       <description><![CDATA[The IDs generated for all elements in a form are md5 hashes from the fieldname. Setting this to true will disable this behaviour and use a cleaned fieldname, prefixed with the form name as the ID, instead.
+This can be useful to style specifically named fields with CSS.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="emailMess" type="string">
+                       <description><![CDATA[Message if a field evaluated to be an email adresse did not validate.
+
+NOTE: May be overridden by the property override feature of the formdata (see above)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="fieldPrefix" type="string">
+                       <description><![CDATA[Alternative prefix for the name of the fields in this form. Otherwise, all fields are prefixed with the form name (either a unique hash or the name set in the “formName” property). If set to “0”, there will be no prefix at all.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="fieldWrap" type="stdWrap">
+                       <description><![CDATA[Field: Wraps the fields]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="formName" type="string">
+                       <description><![CDATA[An alternative name for this form. Default will be a unique (random) hash.
+
+<form name=”...”>]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="goodMess" type="string">
+                       <description><![CDATA[Message for the formevaluation function in case of correctly filled form.
+
+NOTE: May be overridden by the property override feature of the formdata (see above)]]></description>
+                       <default><![CDATA[No message]]></default>
+               </property>
+               <property name="hiddenFields" type="cObjArray">
+                       <description><![CDATA[Used to set hiddenFields from TS.
+
+Example:
+hiddenFields.pid = TEXT
+hiddenFields.pid.value = 2
+
+This makes a hidden-field with the name “pid” and value “2”.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="image" type="IMAGE">
+                       <description><![CDATA[If this is a valid image the submitbutton is rendered as this image!!
+
+NOTE: CurrentValue is set to the caption-label before generating the image.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="labelWrap" type="stdWrap">
+                       <description><![CDATA[Labels: Wraps the label]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="layout" type="string">
+                       <description><![CDATA[This defines how the label and the field are placed towards each other.
+
+Example:
+This substitutes the "###FIELD###" with the field data and the "###LABEL###' with labeldata. 
+
+<tr><td>###FIELD###</td><td> ###LABEL###</td></tr>
+
+You can also use the marker ###COMMENT### which is ALSO the label value inserted, but wrapped in .commentWrap stdWrap-properties (see below)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="locationData" type="string">
+                       <description><![CDATA[boolean / string
+                       If this value is true, then a hidden-field called "locationData" is added to the form. This field wil be loaded with a value like this:
+[page id]:[current record table]:[current record id]
+For example, if a formfield is inserted on page with uid = "100", as a page-content item from the table "tt_content" with id "120", then the value would be "100:tt_content:120".
+The value is use by eg. the cObject SEARCHRESULT. If the value $GLOBALS["HTTP_POST_VARS"]["locationData"] is detected here, the search is done as if it was performed on this page! This is very usefull if you want a search functionality implemented on a page with the "stype" field set to "L1" which means that the search is carried out from the first level in the rootline. 
+Suppose you want the search to submit to a dedicated searchpage where ever. This page will then know - because of locationData - that the search was submittet from another place on the website.
+If "locationData" is not only true but also set to "HTTP_POST_VARS" then the value will insert the content of $GLOBALS["HTTP_POST_VARS"]["locationData"] instead of the true location data of the page. This should be done with search-fields as this will carry the initial searching start point with.
+NOTE: May be overridden by the property override feature of the formdata (see above)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="method" type="string">
+                       <description><![CDATA[form-method
+                       
+                       Example: 
+GET]]></description>
+                       <default><![CDATA[POST]]></default>
+               </property>
+               <property name="noValueInsert" type="boolean">
+                       <description><![CDATA[By default values that are submitted to the same page (and thereby same form, eg. at searchforms) are re-inserted in the form instead of any default-data that might be set up. 
+This, however, applies ONLY if the "no_cache=1" is set! (a page being cached may not include user-specific defaults in the fields of course...) 
+If you set this flag, "noValueInsert", the content will always be the default content.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="noWrapAttr" type="boolean">
+                       <description><![CDATA[If this value is true then all wrap attributes of textarea elements are suppressed. This is needed for XHTML-compliancy.
+
+The wrap attributes can also be disabled on a per-field basis by using the special keyword "disabled" as the value of the wrap attribute.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="no_cache" type="string">
+                       <description><![CDATA[Default no_cache-option]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="params" type="string">
+                       <description><![CDATA[form-element tag parameters
+                       Extra parameters to form elements
+
+Example:
+params = style=”width:200px;”
+params.textarea = style=”width:300px;”
+params.check = 
+
+This sets the default to 200 px width, but excludes check-boxes and sets textareas to 300.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="radioWrap" type="stdWrap">
+                       <description><![CDATA[Wraps the labels for radiobuttons]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="recipient" type="stdWrap">
+                       <description><![CDATA[(list of) string /stdWrap
+                       Email recipient of the formmail content (generates the hiddenfield "recipient")]]></description>
+                       <default><![CDATA[No email]]></default>
+               </property>
+               <property name="redirect" type="stdWrap">
+                       <description><![CDATA[URL to redirect to (generates the hidden field "redirect")
+
+Integer: this is regarded to be a page in TYPO3
+String: this is regarded to be a normal url
+Empty; the current page is chosen.
+
+NOTE: If this value is set the target of this overriddes the target of the "type".]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[Wraps the hole form (before formtags is added)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="target" type="string">
+                       <description><![CDATA[target
+                       Default target of the form. ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="type" type="int">
+                       <description><![CDATA[Type (action="" of the form):
+
+Integer: this is regarded to be a page in TYPO3
+String: this is regarded to be a normal URL (eg. "formmail.php" or "fe_tce_db.php")
+Empty: the current page is chosen.
+
+NOTE: If type is integer/empty the form will be submitted to a page in TYPO3 and if this page has a value for target/no_cache, then this will be used instead of the default target/no_cache below.
+
+NOTE: If the redirect-value is set, the redirect-target overrides the target set by the action-url
+
+NOTE: May be overridden by the property override feature of the formdata (see above)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrapFieldName" type="wrap">
+                       <description><![CDATA[This wraps  the fieldnames before they are applied to the form-field tags.
+
+Example:
+If value is tx_myextension[input][  |  ]  then the fieldname "email" would be wrapped to this value: tx_myextension[input][email]]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="REQ">
+               <property name="fieldWrap" type="stdWrap">
+                       <description><![CDATA[Field: Wraps the fields, but for reuired fields]]></description>
+                       <default><![CDATA[the "fieldWrap"-property]]></default>
+               </property>
+               <property name="labelWrap" type="stdWrap">
+                       <description><![CDATA[Labels: Wraps the label, but for reuired fields]]></description>
+                       <default><![CDATA[the "labelWrap"-property]]></default>
+               </property>
+               <property name="layout" type="string">
+                       <description><![CDATA[The same as "layout" above, but for reuired fields]]></description>
+                       <default><![CDATA[the "layout"-property]]></default>
+               </property>
+       </type>
+       <type id="FRAMESET">
+               <property name="1" type="FRAME">
+                       <description><![CDATA[Configuration of frames and nested framesets.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="2" type="FRAME">
+                       <description><![CDATA[Configuration of frames and nested framesets.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="3" type="FRAME">
+                       <description><![CDATA[Configuration of frames and nested framesets.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="4" type="FRAME">
+                       <description><![CDATA[Configuration of frames and nested framesets.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="cols" type="string">
+                       <description><![CDATA[<frameset>-data:cols
+                       Cols]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="params" type="string">
+                       <description><![CDATA[<frameset>-params
+                       Example:
+border="0" framespacing="0" frameborder="NO"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="rows" type="string">
+                       <description><![CDATA[<frameset>-data:rows
+                       Rows]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="FRAME">
+               <property name="name" type="string">
+                       <description><![CDATA[<frame>-data:name
+                       Manually set name of frame
+
+NOTE: Is set automatically and should not be overridden under normal conditions!]]></description>
+                       <default><![CDATA[value of ".obj"]]></default>
+               </property>
+               <property name="obj" type="string">
+                       <description><![CDATA[pointer to toplevel object-name
+                       toplevel object-name of a PAGE / FRAMESET
+
+Example:
+"left", "page", "frameset"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="options" type="string">
+                       <description><![CDATA[url-parameters
+                       Example:
+print=1&othervar=anotherthing
+would add '&print=1&othervar=anotherthing' to the ".src"-content (if not ".src" is set manually!!)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="params" type="string">
+                       <description><![CDATA[<frame>-params
+                       Example:
+scrolling="AUTO" noresize frameborder="NO"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="src" type="string">
+                       <description><![CDATA[<frame>-data:src
+                       Manually set the src of the frame
+
+NOTE: Is set automatically and should not be overridden under normal conditions!]]></description>
+                       <default><![CDATA[could be index.php?$id&$type ]]></default>
+               </property>
+       </type>
+       <type id="GifBuilderObj">
+               <property name="if" type="if">
+                       <description><![CDATA[.if (->if)  is a property of all gifbuilder-objects. If the property is present and NOT set, the object is NOT rendered! This corresponds to the functionallity of ".if" of the stdWrap-function.]]></description>
+               </property>
+       </type>
+       <type id="GIFBUILDER">
+               <property name="1" type="GifBuilderObj">
+                       <description><![CDATA[.if (->if)  is a property of all gifbuilder-objects. If the property is present and NOT set, the object is NOT rendered! This corresponds to the functionallity of ".if" of the stdWrap-function.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="2" type="GifBuilderObj">
+                       <description><![CDATA[.if (->if)  is a property of all gifbuilder-objects. If the property is present and NOT set, the object is NOT rendered! This corresponds to the functionallity of ".if" of the stdWrap-function.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="3" type="GifBuilderObj">
+                       <description><![CDATA[.if (->if)  is a property of all gifbuilder-objects. If the property is present and NOT set, the object is NOT rendered! This corresponds to the functionallity of ".if" of the stdWrap-function.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="4" type="GifBuilderObj">
+                       <description><![CDATA[.if (->if)  is a property of all gifbuilder-objects. If the property is present and NOT set, the object is NOT rendered! This corresponds to the functionallity of ".if" of the stdWrap-function.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="XY" type="string">
+                       <description><![CDATA[x,y +calc
+                       Size of the gif-file. ]]></description>
+                       <default><![CDATA[100,20]]></default>
+               </property>
+               <property name="backColor" type="string">
+                       <description><![CDATA[GraphicColor 
+                       Background color for the gif]]></description>
+                       <default><![CDATA[white]]></default>
+               </property>
+               <property name="format" type="string">
+                       <description><![CDATA[&quot;gif&quot; / &quot;jpg&quot;
+                       Output type. 
+"jpg"/"jpeg" = jpg-image]]></description>
+                       <default><![CDATA[gif]]></default>
+               </property>
+               <property name="maxHeight" type="int">
+                       <description><![CDATA[pixels
+                       Maximal heigth of gif-file]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="maxWidth" type="int">
+                       <description><![CDATA[pixels
+                       Maximal width of gif-file]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y +calc
+                       Offset all objects on the gif.]]></description>
+                       <default><![CDATA[0,0]]></default>
+               </property>
+               <property name="quality" type="int">
+                       <description><![CDATA[posint (10-100)
+                       JPG-quality (if “.format” = jpg/jpeg)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="reduceColors" type="int">
+                       <description><![CDATA[posint (1-255)
+                       Reduce the number of colors (if gif-file)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="transparentBackground" type="boolean">
+                       <description><![CDATA[Set this flag to render the background transparent. TYPO3 makes the color found at position 0,0 of the image (upper left corner) transparent.
+If you render text you should leave the niceText option OFF as the result with probably be more precise without the niceText antialiasing hack]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="transparentColor" type="stdWrap">
+                       <description><![CDATA[HTMLColor /stdWrap 
+                       Specify a color that should be transparent
+
+Example-values:
+#ffffcc 
+red 
+255,255,127
+
+Option:
+transparentColor.closest = 1
+This will allow for the closest color to be matched instead. You may need this if you image is not garanteed "clean".
+
+NOTE: You may experience that this doesn't work if you use reduceColors-option or render text with niceText-option.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="workArea" type="string">
+                       <description><![CDATA[x,y,w,h + calc
+                       Define the workarea on the giffile. All the GifBuilderObj's will see this as the dimensions of the gif-file regarding alignment, overlaying of images an so on. Only will TEXT-objects exceeding the boundaries of the workarea print outside this area.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_ADJUST" extends="GifBuilderObj">
+               <property name="value" type="string">
+                       <description><![CDATA[This lets you adjust the input-levels like in Photoshops "levels"-dialog. If you need to adjust gamma, look at the EFFECT-object.
+Example:
+
+20 = ADJUST
+20.value = inputLevels = 13,230
+
+properties:
+
+inputLevels: low,high
+outputLevels: low, high
+autoLevels: -
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_BOX" extends="GifBuilderObj">
+               <property name="align" type="string">
+                       <description><![CDATA[VHalign
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="color" type="string">
+                       <description><![CDATA[GraphicColor
+                       fill-color]]></description>
+                       <default><![CDATA[black]]></default>
+               </property>
+               <property name="dimensions" type="string">
+                       <description><![CDATA[x,y,w,h +calc
+                       Dimensions of a filled box. 
+x,y    is the offset. 
+w,h    is the dimensions. Dimensions of 1 will result in 1-pixel wide lines!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_CROP" extends="GifBuilderObj">
+               <property name="align" type="string">
+                       <description><![CDATA[VHalign
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="backColor" type="string">
+                       <description><![CDATA[GraphicColor
+]]></description>
+                       <default><![CDATA[The original backColor]]></default>
+               </property>
+               <property name="crop" type="string">
+                       <description><![CDATA[x,y,v,h + calc
+                       x,y is offset of the crop-frame, 
+v,h  is the dimensions]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_EFFECT" extends="GifBuilderObj">
+               <property name="value" type="string">
+                       <description><![CDATA[.value = [Varnavn] = [value] | [Varnavn] = [value]
+
+Example:
+20 = EFFECT
+20.value = gamme=1.3 | flip | rotate=180
+
+
+gamma: 0.5 - 3.0
+blur: 1-99
+sharpen: 1-99
+solarize: 0-99
+swirl: 0-100
+wave: ampli , length
+charcoal: 0-100
+gray: -
+edge: 0-99
+emboss: -
+flip: - (Vertical flipping)
+flop: - (Horizontal flipping)
+rotate: 0-360 (Rotation)
+colors: 2-255
+shear: -90 - 90 (Horizontal shearing)
+invert: - (invert the colors)
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_EMBOSS" extends="GifBuilderObj">
+               <property name="blur" type="int">
+                       <description><![CDATA[posint (1-99)
+                       Blurring of the shadow. Above 40 only values of 40,50,60,70,80,90 means something.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="highColor" type="string">
+                       <description><![CDATA[GraphicColor
+                       Upper border-color]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="intensity" type="int">
+                       <description><![CDATA[posint(0-100)
+                       How "massive" the emboss is. This value can - if it has a high value combined with a blurred shadow - create a kind of soft-edged outline.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="lowColor" type="string">
+                       <description><![CDATA[GraphicColor
+                       lower border-color]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y
+                       Offset of the emboss]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="opacity" type="int">
+                       <description><![CDATA[posint (1-100)
+                       Opacity (transparency^-1) 
+100% opacity = 0% transparency). Only active with a value for blur.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="textObjNum" type="int">
+                       <description><![CDATA[pos-int
+                       Must point to the TEXT-object if these shadow-properties are not properties to a TEXT-object directly ("stand-alone-shadow"). Then the shadow needs to know which TEXT-object it should be a shadow of!
+If - on the other hand - the shadow is a property to a text-object, this property is not needed.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_IMAGE" extends="GifBuilderObj">
+               <property name="align" type="string">
+                       <description><![CDATA[VHalign
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="file" type="imgResource">
+                       <description><![CDATA[The imagefile]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="mask" type="imgResource">
+                       <description><![CDATA[Optional mask-image for the imagefile.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y +calc
+                       Offset ]]></description>
+                       <default><![CDATA[0,0]]></default>
+               </property>
+               <property name="tile" type="string">
+                       <description><![CDATA[x,y
+                       tile x,y times. 
+Maximum times is 20 each direction. If you need more, use a larger image.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_OUTLINE" extends="GifBuilderObj">
+               <property name="color" type="string">
+                       <description><![CDATA[GraphicColor
+                       Outline color]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="textObjNum" type="int">
+                       <description><![CDATA[pos-int
+                       Must point to the TEXT-object if these shadow-properties are not properties to a TEXT-object directly ("stand-alone-shadow"). Then the shadow needs to know which TEXT-object it should be a shadow of!
+If - on the other hand - the shadow is a property to a text-object, this property is not needed.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="thickness" type="string">
+                       <description><![CDATA[x,y
+                       Thickness in each direction, range 1-2]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_SCALE" extends="GifBuilderObj">
+               <property name="height" type="string">
+                       <description><![CDATA[pixels + calc
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="params" type="string">
+                       <description><![CDATA[ImageMagickParams
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="width" type="string">
+                       <description><![CDATA[pixels + calc
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_SHADOW" extends="GifBuilderObj">
+               <property name="blur" type="int">
+                       <description><![CDATA[posint (1-99)
+                       Blurring of the shadow. Above 40 only values of 40,50,60,70,80,90 means something.
+
+NOTE: Unfortunately the blurring capabilities of ImageMagick is not very mature in the version 4.2.9. This is addressed in the later version 5.2.0 where a gaussian blur-function is added. BUT as we do cannot use the latest ImageMagick development yet, this is not utilized so far.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="color" type="string">
+                       <description><![CDATA[GraphicColor
+                       Shadow color]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="intensity" type="int">
+                       <description><![CDATA[posint(0-100)
+                       How "massive" the shadow is. This value can - if it has a high value combined with a blurred shadow - create a kind of soft-edged outline.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y
+                       Shadow offset]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="opacity" type="int">
+                       <description><![CDATA[posint (1-100) 
+                       Opacity (transparency^-1) 
+100% opacity = 0% transparency). Only active with a value for blur.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="textObjNum" type="int">
+                       <description><![CDATA[pos-int
+                       Must point to the TEXT-object if these shadow-properties are not properties to a TEXT-object directly ("stand-alone-shadow"). Then the shadow needs to know which TEXT-object it should be a shadow of!
+If - on the other hand - the shadow is a property to a text-object, this property is not needed.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GB_TEXT" extends="GifBuilderObj">
+               <property name="align" type="string">
+                       <description><![CDATA[align 
+                       Alignment of the text]]></description>
+                       <default><![CDATA[left]]></default>
+               </property>
+               <property name="angle" type="string">
+                       <description><![CDATA[degree
+                       Rotation degrees of the text. 
+
+NOTE: Angle is not available if spacing/wordSpacing is set.]]></description>
+                       <default><![CDATA[0
+Range: -90 til 90]]></default>
+               </property>
+               <property name="antiAlias" type="boolean">
+                       <description><![CDATA[FreeType antialiasing. Notice, the default mode is "on"!
+
+Note: This option is not available if .niceText is enabled]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="doNotStripHTML" type="boolean">
+                       <description><![CDATA[If set, HTML-tags in the string inserted are NOT removed. Any other way HTML-code is removed by default!]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="emboss" type="GB_EMBOSS">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="fontColor" type="stdWrap">
+                       <description><![CDATA[GraphicColor /stdWrap
+                       Font color]]></description>
+                       <default><![CDATA[black]]></default>
+               </property>
+               <property name="fontFile" type="string">
+                       <description><![CDATA[Font face (truetype font you can upload!!)]]></description>
+                       <default><![CDATA[Nimbus (Arial-clone)]]></default>
+               </property>
+               <property name="fontSize" type="int">
+                       <description><![CDATA[posint
+                       Font size]]></description>
+                       <default><![CDATA[12]]></default>
+               </property>
+               <property name="hide" type="boolean">
+                       <description><![CDATA[If this is true, the text is NOT printed. 
+This feature may be used if you need a shadow-object to base a shadow on the text, but do not want the text to print.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="hideButCreateMap" type="boolean">
+                       <description><![CDATA[If this option is set, the text will not be rendered. Shadows and emboss will, though, so don't apply these!! But this feature is also meant only to enable a text to generate the imageMap coordinates without rendering itself.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="imgMap" type="IMGMAP">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="iterations" type="int">
+                       <description><![CDATA[posint
+                       How many times the text should be "printed" onto it self. This will add the effect of bold text.
+
+Note: This option is not available if .niceText is enabled]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="maxWidth" type="int">
+                       <description><![CDATA[pixels
+                       Sets the maximum width in pixels, the text must be. Reduces the fontSize if the text does not fit within this width.
+
+Does not support setting alternative fontSizes in splitRendering options.
+
+(By Rene Fritz <r.fritz@colorcube.de>)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="niceText" type="boolean">
+                       <description><![CDATA[This is a very popular feature that helps to render small letters much nicer than the freetype library can normally do. But it also loads the system very much!
+The principle of this function is to create a black/white giffile in twice or more times the size of the actual gif-file and then print the text onto this is a scaled dimension. Afterwards ImageMagick (IM) scales down the mask and masks the font color down on the original gif-file through the temporary mask. 
+The fact that the font  is  actually rendered in the double size and scaled down adds a more homogenous shape to the lettes. Some fonts are more critical than others though.  If you do not need the quality, then don't use the function.
+
+Some properties:
+.before = IM-params before scale
+.after = IM-params after scale
+.sharpen = sharpen-value for the mask (after scaling), integer 0-99 (this enables you to make the text crisper if it's too blurred!)
+.scaleFactor = scaling-factor, int 2-5]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="offset" type="string">
+                       <description><![CDATA[x,y +calc
+                       Offset of the text]]></description>
+                       <default><![CDATA[0,0]]></default>
+               </property>
+               <property name="outline" type="GB_OUTLINE">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="shadow" type="GB_SHADOW">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="spacing" type="int">
+                       <description><![CDATA[posint
+                       Pixel-distance between letters. This may render ugly!]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="splitRendering.compX" type="string">
+                       <description><![CDATA[Split the rendering of a string into separate processes with individual configurations. By this method a certain range of characters can be rendered with another font face or size. This is very useful if you want to use separate fonts for strings where you have latin characters combined with eg. Japanese and there is a separate font file for each.
+You can also render keywords in another font/size/color.
+
+Properties:
+splitRendering.compX = Additional pixelspace between parts, x direction
+splitRendering.compY = Additional pixelspace between parts, y direction
+splitRendering.[array] = keyword  [charRange, highlightWord]
+splitRendering.[array] {
+  fontFile = Alternative font file for this rendering
+  fontSize = Alternative font size for this rendering
+  color = Alternative color for this rendering, works ONLY without “niceText”
+  xSpaceBefore = x-Space before this part
+  xSpaceAfter = x-Space after this part
+  ySpaceBefore = y-Space before this part
+  ySpaceAfter =  y-Space after this part
+}
+
+Keyword: charRange
+splitRendering.[array].value = Commaseparated list of character ranges (eg. “100-200”) given as Unicode character numbers. The list accepts optional starting and ending points, eg. “ - 200” or “ 200 -” and single values, eg. “65, 66, 67”
+
+Keyword: highlightWord
+splitRendering.[array].value = Word to highlight, makes a case sensitive search for this.
+
+Limitations:
+The pixelcompensation values are not corrected for scale factor used with niceText. Basically this means that when niceText is used, these values will have only the half effect.When word spacing is used the “highlightWord” mode doesn't work.The color override works only without “niceText”.
+
+Example:
+  10.splitRendering.compX = 2
+  10.splitRendering.compY = -2
+  10.splitRendering.10 = charRange
+  10.splitRendering.10 {
+    value = 200-380 , 65, 66
+    fontSize = 50
+    fontFile =  t3lib/fonts/nimbus.ttf
+    xSpaceBefore = 30
+  }
+  10.splitRendering.20 = highlightWord
+  10.splitRendering.20 {
+    value = TheWord
+    color = red
+  }]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="splitRendering.compY" type="string">
+                       <description><![CDATA[Split the rendering of a string into separate processes with individual configurations. By this method a certain range of characters can be rendered with another font face or size. This is very useful if you want to use separate fonts for strings where you have latin characters combined with eg. Japanese and there is a separate font file for each.
+You can also render keywords in another font/size/color.
+
+Properties:
+splitRendering.compX = Additional pixelspace between parts, x direction
+splitRendering.compY = Additional pixelspace between parts, y direction
+splitRendering.[array] = keyword  [charRange, highlightWord]
+splitRendering.[array] {
+  fontFile = Alternative font file for this rendering
+  fontSize = Alternative font size for this rendering
+  color = Alternative color for this rendering, works ONLY without “niceText”
+  xSpaceBefore = x-Space before this part
+  xSpaceAfter = x-Space after this part
+  ySpaceBefore = y-Space before this part
+  ySpaceAfter =  y-Space after this part
+}
+
+Keyword: charRange
+splitRendering.[array].value = Commaseparated list of character ranges (eg. “100-200”) given as Unicode character numbers. The list accepts optional starting and ending points, eg. “ - 200” or “ 200 -” and single values, eg. “65, 66, 67”
+
+Keyword: highlightWord
+splitRendering.[array].value = Word to highlight, makes a case sensitive search for this.
+
+Limitations:
+The pixelcompensation values are not corrected for scale factor used with niceText. Basically this means that when niceText is used, these values will have only the half effect.When word spacing is used the “highlightWord” mode doesn't work.The color override works only without “niceText”.
+
+Example:
+  10.splitRendering.compX = 2
+  10.splitRendering.compY = -2
+  10.splitRendering.10 = charRange
+  10.splitRendering.10 {
+    value = 200-380 , 65, 66
+    fontSize = 50
+    fontFile =  t3lib/fonts/nimbus.ttf
+    xSpaceBefore = 30
+  }
+  10.splitRendering.20 = highlightWord
+  10.splitRendering.20 {
+    value = TheWord
+    color = red
+  }]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="text" type="stdWrap">
+                       <description><![CDATA[This is text text-string on the gif-file. The item is rendered only if this string is not empty.
+The cObj->data-array is loaded with the page-record, if for example the GIFBUILDER-object is used by GMENU or IMGMENU]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="textMaxLength" type="int">
+                       <description><![CDATA[The maximum length of the text.  This is just a natural break that prevents incidental rendering of very long texts!]]></description>
+                       <default><![CDATA[100]]></default>
+               </property>
+               <property name="wordSpacing" type="int">
+                       <description><![CDATA[posint
+                       Pixel-distance between words.]]></description>
+                       <default><![CDATA[= ".spacing"*2]]></default>
+               </property>
+       </type>
+       <type id="GB_WORKAREA" extends="GifBuilderObj">
+               <property name="clear" type="string">(isset)
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="set" type="string">
+                       <description><![CDATA[x,y,w,h + calc
+                       Sets another workarea
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="HMENU">
+               <property name="1" type="mObj">
+                       <description><![CDATA[Required!
+Defines which menuObj that should render the menuitems on the various levels. 
+1 is the first level, 2 is the second level, 3 is the third level, 4 is ....
+
+Example:
+temp.sidemenu = HMENU
+temp.sidemenu.1 = GMENU  ]]></description>
+                       <default><![CDATA[ (no menu)]]></default>
+               </property>
+               <property name="2" type="mObj">
+                       <description><![CDATA[Defines which menuObj that should render the menuitems on the various levels. 
+1 is the first level, 2 is the second level, 3 is the third level, 4 is ....
+
+Example:
+temp.sidemenu = HMENU
+temp.sidemenu.1 = GMENU  ]]></description>
+                       <default><![CDATA[ (no menu)]]></default>
+               </property>
+               <property name="3" type="mObj">
+                       <description><![CDATA[Defines which menuObj that should render the menuitems on the various levels. 
+1 is the first level, 2 is the second level, 3 is the third level, 4 is ....
+
+Example:
+temp.sidemenu = HMENU
+temp.sidemenu.1 = GMENU  ]]></description>
+                       <default><![CDATA[ (no menu)]]></default>
+               </property>
+               <property name="4" type="mObj">
+                       <description><![CDATA[Defines which menuObj that should render the menuitems on the various levels. 
+1 is the first level, 2 is the second level, 3 is the third level, 4 is ....
+
+Example:
+temp.sidemenu = HMENU
+temp.sidemenu.1 = GMENU  ]]></description>
+                       <default><![CDATA[ (no menu)]]></default>
+               </property>
+               <property name="addQueryString" type="string">
+                       <description><![CDATA[see typolink.addQueryString
+
+Notice: This works only for special=language.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="alwaysActivePIDlist" type="intList">
+                       <description><![CDATA[List of Integers
+                       This is a list of page UID numbers that will always be regarded as active menu items and thereby automatically opened regardless of the rootline.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="begin" type="int">
+                       <description><![CDATA[int +calc
+                       The first item in the menu. 
+
+Example:
+This results in a menu, where the first two items are skipped starting with item number 3:
+  begin = 3  
+
+Notice: Affects all sub menus as well. (See “minItems” for notice)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="entryLevel" type="int">
+                       <description><![CDATA[Defines at which level in the rootLine, the menu should start. 
+Default is "0" which gives us a menu of the very first pages on the site.
+If the value is < 0, entryLevel is chosen from "behind" in the rootLine. Thus "-1" is a menu with items from the outermost level, "-2" is the level before the outermost...]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="excludeDoktypes" type="intList">
+                       <description><![CDATA[list of integers
+                       Enter the list of page document types (doktype) to exclude from menus. By default pages that are “not in menu” (5) are excluded and those marked for backend user access only (6). ]]></description>
+                       <default><![CDATA[5,6]]></default>
+               </property>
+               <property name="excludeUidList" type="int">
+                       <description><![CDATA[list of integers
+                       This is a list of page uid's to exclude when the select statement is done. Comma-separated. You may add “current” to the list to exclude the current page.
+
+Example:
+The pages with these uid-number will NOT be within the menu!! Additionally the current page is always excluded too.
+  excludeUidList = 34,2,current]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="if" type="if">
+                       <description><![CDATA[If "if" returns false, the menu is not generated]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="includeNotInMenu" type="boolean">
+                       <description><![CDATA[If set, pages with type “Not in menu” will be included in menus.
+The number “5” will simply be removed from the current dok-type list (which is by default “5,6” but can be changed by “excludeDoktypes”, see above).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="maxItems" type="int">
+                       <description><![CDATA[The maximum items in the menu. More items will be ignored.
+
+Notice: Affects all sub menus as well. (See “minItems” for notice)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="minItems" type="int">
+                       <description><![CDATA[The minimum items in the menu. If the number of pages does not reach this level, a dummy-page with the title "..." and uid=[currentpage_id] is inserted.
+
+Notice: Affects all sub menus as well. To set the value for each menu level individually, set the properties in the menu objects (see “Common properties” table).]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="protectLvar" type="string">
+                       <description><![CDATA[boolean / keyword
+                       If set, then for each page in the menu it will be checked if an Alternative Page Language record for the language defined in "config.sys_language_uid" (typically defined via &L) exists for the page. If that is not the case and the pages “Localization settings” have the “Hide page if no translation for current language exists” flag set, then the menu item will link to a non accessible page that will yield an error page to the user. Setting this option will prevent that situation by simply adding “&L=0” for such pages, meaning that they will switch to the default language rather than keeping the current language.
+The check is only carried out if a translation is requested ("config.sys_language_uid" is not zero).
+
+Keyword: “all”
+When set to “all” the same check is carried out but it will not look if “Hide page if no translation for current language exists” is set - it always reverts to default language if no translation is found.
+
+For these options to make sense, they should only be used when “config.sys_language_mode” is not set to “content_fallback”.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="special" type="HMENU_SPECIAL">
+                       <description><![CDATA[&quot;directory&quot; / &quot;list&quot; / &quot;updated&quot; / &quot;browse&quot; / &quot;rootline&quot; / &quot;keywords&quot; / “language”
+                       (See tsref for details: 
+                       <a href="http://typo3.org/documentation/document-library/references/doc_core_tsref/4.1.0/view/8/11/#id4080403">
+                       http://typo3.org/documentation/document-library/references/doc_core_tsref/4.1.0/view/8/11/#id4080403</a> )]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="HMENU_SPECIAL">
+               <property name="value" type="stdWrap">
+                       <description><![CDATA[list of page-uid's /stdWrap]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="directory" extends="HMENU_SPECIAL"/>
+       <type id="list" extends="HMENU_SPECIAL"/>
+       <type id="updated" extends="HMENU_SPECIAL">
+               <property name="mode" type="string">
+                       <description><![CDATA[Which field in the pages-table to use. Default is "SYS_LASTCHANGED" (which is updated when a page is generated to the youngest tstamp of the records on the page), "manual" or “lastUpdated” will use the field "lastUpdated" (set manually in the page-record) and "tstamp" will use the "tstamp"-field of the pagerecord, which is set automatically when the record is changed. "crdate" will use "crdate"-field of the pagerecord. “starttime” will use the starttime field.
+
+Fields with zero value is not selected anyway.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="depth" type="string">
+                       <description><![CDATA[By default (if the value is not an integer) the depth is 20 levels. The range is 1-20. A depth of 1 means only the start id, depth of 2 means start-id + first level. NOTE: depth is relative to beginAtLevel.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="beginAtLevel" type="int">
+                       <description><![CDATA[Determines starting level for the pagetrees generated based on .value and .depth. Zero is default and includes the start id. 1=starts with the first row of subpages, 2=starts with the second row of subpages. Depth is relative to this starting point.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="maxAge" type="string">
+                       <description><![CDATA[Seconds+calc.  
+                       Pages with update-dates older than currenttime minus this number of seconds will not be shown in the menu no matter what. Default is "not used". You may use +-*/ for calculations.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="limit" type="int">
+                       <description><![CDATA[Max number of items in the menu. Default is 10, max is 100.
+                       ]]></description>
+                       <default><![CDATA[10
+]]></default>
+               </property>
+               <property name="excludeNoSearchPages" type="boolean">
+                       <description><![CDATA[If set, pages marked "No search" is not included into special-menus.
+Support for Mount Pages: Yes.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="rootline" extends="HMENU_SPECIAL">
+               <property name="range" type="string">
+                       <description><![CDATA[rootline creates a menu with pages from the "rootline" (see earlier in this reference)
+
+.range = [begin-level] | [end-level] (same way as you reference the .entryLevel for HMENU)
+
+This...
+
+page.2 = HMENU
+page.2.special = rootline
+page.2.special.range = 1|-2
+page.2.special.targets.3 = page
+page.2.1 = TMENU
+page.2.1.target = _top
+page.2.1.wrap = <HR> | <HR>
+page.2.1.NO {
+  linkWrap = | >
+}
+... creates a menu like this:
+
+Page level 1 > Page level 2 > Page level 3 > Page level 4 >
+
+(The menu starts at level 1 and does NOT link to the current page (-2 is the level before). Further all pages on level 3 will have "page" as target and all other "_top")
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="targets" type="string">
+                       <description><![CDATA[.targets.[0-x]  targets
+                       
+                       This...
+
+page.2 = HMENU
+page.2.special = rootline
+page.2.special.range = 1|-2
+page.2.special.targets.3 = page
+page.2.1 = TMENU
+page.2.1.target = _top
+page.2.1.wrap = <HR> | <HR>
+page.2.1.NO {
+  linkWrap = | >
+}
+
+... creates a menu like this:
+
+Page level 1 > Page level 2 > Page level 3 > Page level 4 >
+
+(The menu starts at level 1 and does NOT link to the current page (-2 is the level before). Further all pages on level 3 will have "page" as target and all other "_top")
+                       
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="browse" extends="HMENU_SPECIAL">
+               <property name="items" type="string">
+                       <description><![CDATA[.items  ( "|" separated list of "itemnames")
+                       This kind of menu is built of items given by a list from the property ".item". Each element in the list (sep. by "|") is either a reserved itemname (see list) with a predefined function or a userdefined name which you can assign a link to any page. Note that the current page cannot be the root-page of a site.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="items.prevnextToSection" type="boolean">
+                       <description><![CDATA[items.prevnextToSection (boolean) - if set, the "prev" and "next" navigation will jump to the next section when it reaches the end of pages in the current section.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="next" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[next / prev : links to next page / previous page. Next and previous pages are from the same "pid" as the current page id (or "value") - that is the next item in a menu with the current page. Also referred to as current level.
+
+If ".prevnextToSection" is set then next/prev will link to the first page of next section / last page of previous section.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="prev" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[next / prev : links to next page / previous page. Next and previous pages are from the same "pid" as the current page id (or "value") - that is the next item in a menu with the current page. Also referred to as current level.
+
+If ".prevnextToSection" is set then next/prev will link to the first page of next section / last page of previous section.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="nextsection" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[nextsection / prevsection : links to next section / previous section. A section is defined as the subpages of a page on the same level as the parent (pid) page of the current page. Will not work if parent page of current page is the root page of the site.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="prevsection" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[nextsection / prevsection : links to next section / previous section. A section is defined as the subpages of a page on the same level as the parent (pid) page of the current page. Will not work if parent page of current page is the root page of the site.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="nextsection_last" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[Where nextsection/prevsection links to the first page in a section, these links to the last pages. If there is only one page in the section that will be both first and last. Will not work if parent page of current page is the root page of the site.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="prevsection_last" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[Where nextsection/prevsection links to the first page in a section, these links to the last pages. If there is only one page in the section that will be both first and last. Will not work if parent page of current page is the root page of the site.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="first" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[First / Last page on current level. If there is only one page on the current level that page will be both first and last.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="last" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[First / Last page on current level. If there is only one page on the current level that page will be both first and last.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="up" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[Links to the parent (pid) page of the current page. (up 1 level) Will always be available
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="index" type="HMENU_SPECIAL_browseItem">
+                       <description><![CDATA[Links to the parent of the parent page of the current page (up 2 levels). May not be available if that page is out of the rootline.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="HMENU_SPECIAL_browseItem">
+               <property name="target" type="string">
+                       <description><![CDATA[optional/alternative target of the item]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="uid" type="int">
+                       <description><![CDATA[.  (uid of page) - optional/alternative page-uid to link to
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="fields" type="string">
+                       <description><![CDATA[.[itemnames].fields.[fieldname]  (string)
+ override field "fieldname" in pagerecord.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="keywords" extends="HMENU_SPECIAL">
+               <property name="mode" type="string">
+                       <description><![CDATA[Which field in the pages-table to use for sorting. Default is "SYS_LASTCHANGED" (which is updated when a page is generated to the youngest tstamp of the records on the page), "manual" or “lastUpdated” will use the field "lastUpdated" (set manually in the page-record) and "tstamp" will use the "tstamp"-field of the pagerecord, which is set automatically when the record is changed. "crdate" will use "crdate"-field of the pagerecord. “starttime” will use the starttime field.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="depth" type="string">
+                       <description><![CDATA[By default (if the value is not an integer) the depth is 20 levels. The range is 1-20. A depth of 1 means only the start id, depth of 2 means start-id + first level. NOTE: depth is relative to beginAtLevel.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="beginAtLevel" type="int">
+                       <description><![CDATA[Determines starting level for the pagetrees generated based on .value and .depth. Zero is default and includes the start id. 1=starts with the first row of subpages, 2=starts with the second row of subpages. Depth is relative to this starting point.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="limit" type="int">
+                       <description><![CDATA[Max number of items in the menu. Default is 10, max is 100.
+                       ]]></description>
+                       <default><![CDATA[10
+]]></default>
+               </property>
+               <property name="excludeNoSearchPages" type="boolean">
+                       <description><![CDATA[If set, pages marked "No search" is not included into special-menus.
+Support for Mount Pages: Yes.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="entryLevel" type="string">
+                       <description><![CDATA[.entryLevel = where in the rootline the search begins. Standard rootline syntax (-x to x)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="setKeywords" type="stdWrap">
+                       <description><![CDATA[.setKeywords (/stdWrap) = lets you define the keywords manually by defining them as a commaseparated list. If this property is defined, it overrides the default, which is the keywords of the current page.
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="keywordsField" type="string">
+                       <description><![CDATA[.keywordsField = defines the field in the pages-table in which to search for the keywords. Default is the fieldname “keyword”. No check is done to see if the field you enter here exists, so enter an existing field, OK?!]]></description>
+                       <default><![CDATA[“keyword”
+]]></default>
+               </property>
+               <property name="keywordsField.sourceField" type="string">
+                       <description><![CDATA[.keywordsField.sourceField = defines the field from the current page from which to take the keywords being matched. The default is “keyword”. (Notice that “.keywordsField” is only setting the page-record field to search in !)]]></description>
+                       <default><![CDATA[“keyword”
+]]></default>
+               </property>
+       </type>
+       <type id="language" extends="HMENU_SPECIAL"/>
+       <type id="userdefined" extends="HMENU_SPECIAL">
+               <property name="file" type="string">
+                       <description><![CDATA[.file  [resource]  =  filename of the php-file to include. (Just like cObject PHP_SCRIPT)
+                       ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="userfunction" extends="HMENU_SPECIAL">
+               <property name="userFunc" type="string">
+                       <description><![CDATA[.userFunc = function-name
+                       Calls a user function/method in class which should (as with “userdefined” above) return an array with page records for the menu.
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="mObj">
+               <property name="alternativeSortingField" type="string">
+                       <description><![CDATA[Normally the menuitems are sorted by the fields "sorting" in the pages- and tt_content-table. Here you can enter a list of fields that is used in the SQL- "ORDER BY" statement instead.
+
+Examples (for "pages" table):
+alternativeSortingField = title desc
+(This will render the menu in reversed alphabetical order)
+
+LIMITATIONS: 
+This property works with normal menus, sectionsIndex menus and special-menus of type "directory".]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="begin" type="int">
+                       <description><![CDATA[int +calc
+                       The first item in the menu. 
+
+Example:
+This results in a menu, where the first two items are skipped starting with item number 3:
+  begin = 3  
+
+Takes precedence over HMENU.begin]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="imgNameNotRandom" type="boolean">
+                       <description><![CDATA[If set, the image names of menuitems is not randomly assigned. Usefull switch if you're manipulating these images with some external JavaScript
+
+NOTE: Don't set this if you're working with a menu with sectionIndex! In that case you need special unique names of items based on something else than the uid of the parent page of course!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="imgNamePrefix" type="string">
+                       <description><![CDATA[prefix for the imagenames. This prefix is appended with the uid of the page.]]></description>
+                       <default><![CDATA["img"]]></default>
+               </property>
+               <property name="itemArrayProcFunc" type="string">
+                       <description><![CDATA[function-name
+                       The first variable passed to this function is the “menuArr” array with the menuitems as they are collected based on the type of menu.
+You're free to manipulate or add to this array as you like. Just remember to return the array again!
+
+Note:
+.parentObj property is hardcoded to be a reference to the calling tslib_menu object. Here you'll find eg. ->id to be the uid of the menu item generating a submenu and such.
+
+Presetting element state
+You can override element states like SPC, IFSUB, ACT, CUR or USR by setting the key ITEM_STATE in the page records. See cObject HMENU/special=userdefined for more information.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="maxItems" type="int">
+                       <description><![CDATA[The maximum items in the menu. More items will be ignored.
+
+Takes precedence over HMENU.maxItems]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="minItems" type="int">
+                       <description><![CDATA[The minimum items in the menu. If the number of pages does not reach this level, a dummy-page with the title "..." and uid=[currentpage_id] is inserted.
+
+Takes precedence over HMENU.minItems]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="sectionIndex" type="string">
+                       <description><![CDATA[This is a property that all menuObj's share. If it's set, then the menu will not consist of links to pages on the "next level" but rather links to the parent page to the menu, but in addition "#"-links to the cObjects rendered on the page. In other words, the menuitems will be links to the content elements (with colPos=0!) on the page. A section index.
+
+.sectionIndex = [boolean]
+
+If you set this, all content elements (from tt_content table) of "Column" = "Normal" and the "Index"-check box clicked are selected. This corresponds to the "Menu/Sitemap" content element when "Section index" is selected as type.
+
+.sectionIndex.type = "all" / "header"
+
+If you set this additional property to "all", then the "Index"-checkbox is not considered and all content elements with colPos=0 is selected.
+
+If this property is "header" then only content elements with a visible header-layout (and a non-empty 'header'-field!) is selected. In other words, if the header layout of an element is set to "Hidden" then the page will not appear in the menu.
+
+The data-record /Behind the scene:
+
+When the menu-records are selected it works like this: The parent page record is used as the "base" for the menu-record. That means that any "no_cache" or "target"-properties of the parent page is used for the whole menu.
+
+But of course some fields from the tt_content records are transfered: This is how it mapped:
+
+$temp[$row[uid]]=$basePageRow;
+
+$temp[$row[uid]]["title"]=$row["header"];
+
+$temp[$row[uid]]["subtitle"]=$row["subheader"];
+
+$temp[$row[uid]]["starttime"]=$row["starttime"];
+
+$temp[$row[uid]]["endtime"]=$row["endtime"];
+
+$temp[$row[uid]]["fe_group"]=$row["fe_group"];
+
+$temp[$row[uid]]["media"]=$row["media"];
+
+$temp[$row[uid]]["header_layout"]=$row["header_layout"];
+
+$temp[$row[uid]]["bodytext"]=$row["bodytext"];
+
+$temp[$row[uid]]["image"]=$row["image"];
+
+$temp[$row[uid]]["sectionIndex_uid"]=$row["uid"];
+
+Basically this shows that
+
+- the field "header" and "subheader" from tt_content are mapped to "title" and "subtitle" in the pages-record. Thus you shouldn't need to change your standard menu-objects to fit this thing...
+
+- the fields "starttime", "endtime", "fe_group", "media" from tt_content are mapped to the same fields in a pages-record.
+
+- the fields "header_layout", "bodytext" and "image" are mapped to non-existing fields in the page-record
+
+- a new field, "sectionIndex_uid" is introduced in the page-record which is detected by the function t3lib_tstemplate->linkData(). If this field is present in a pagerecord, the linkData()-function will prepend a hash-mark and the number of the field.
+
+NOTE:
+
+You cannot create submenus to sectionIndex-menus. That doesn't make any sense as these elements are not pages and thereby have no "childs".
+]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="showAccessRestrictedPages" type="string">
+                       <description><![CDATA[integer (page id) / keyword “NONE”
+                       If set, pages in the menu will include pages with frontend user group access enabled.  However the page is of course not accessible and therefore the URL in the menu will be linked to the page with the ID of this value. On that page you could put a login form or other message.
+If the value is “NONE” the link will not be changed and the site will perform page-not-found handling when clicked (which can be used to capture the event and act accordingly of course).
+
+Properties:
+.addParam = Additional parameter for the URL, which can hold two markers; ###RETURN_URL### which will be substituted with the link the page would have had if it had been accessible and ###PAGE_ID### holding the page id of the page coming from (could be used to look up which fe_groups was required for access.
+
+Example:
+showAccessRestrictedPages = 22
+showAccessRestrictedPages.addParams = &return_url=###RETURN_URL###&pageId=###PAGE_ID###
+
+The example will link access restricted menu items to page id 22 with the return URL in the GET var “return_url” and the page id in the GET var “pageId”.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="submenuObjSuffixes" type="string">
+                       <description><![CDATA[Defines a suffix for alternative sub-level menu objects. Useful to create special submenus depending on their parent menu element. See example below.
+
+Example:
+This example will generate a menu where the menu objects for the second level will differ depending on the number of the first level item for which the submenu is rendered. The second level objects used are “2” (the default), “2a” and “2b” (the alternatives). Which of them is used is defined by “1.submenuObjSuffixes” which has the configuration “a |*| |*| b”. This configuration means that the first menu element will use configuration “2a” and the last will use “2b” while anything in between will use “2” (no suffix applied)
+
+page.200 = HMENU
+page.200 {
+  1 = TMENU
+  1.wrap = <div style="width:200px; border: 1px solid;">|</div>
+  1.expAll = 1
+  1.submenuObjSuffixes = a |*|  |*| b
+  1.NO.allWrap = <b>|</b><br/>
+
+  2 = TMENU
+  2.NO.allWrap = <div style="background:red;">|</div>
+
+  2a = TMENU
+  2a.NO.allWrap = <div style="background:yellow;">|</div>
+
+  2b = TMENU
+  2b.NO.allWrap = <div style="background:green;">|</div>
+}
+
+The result can be seen in the image below (applied on the testsite package):
+
+
+
+Applies to GMENU, TMENU, GMENU_LAYERS, TMENU_LAYERS and GMENU_FOLDOUT on >= 2nd level in a menu.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GMENU">
+               <property name="ACT" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config) 
+                       Enable/Configuration for menu items which are found in the rootLine]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="ACTRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config) 
+                       Enable/Configuration for menu items which are found in the rootLine]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="ACTIFSUB" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which are found in the rootLine and has subpages]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="ACTIFSUBRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which are found in the rootLine and has subpages]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="CUR" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for a menu item if the item is the current page.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="CURRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for a menu item if the item is the current page.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="CURIFSUB" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for a menu item if the item is the current page and has subpages.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="CURIFSUBRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for a menu item if the item is the current page and has subpages.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="IFSUB" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which has subpages]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="IFSUBRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which has subpages]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="NO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       The default “Normal” state rendering of Item. This is required for all menus.
+If you specify properties for the “NO” property you do not have to set it “1”. Otherwise with no properties setting “NO=1” will render the menu anyways (for TMENU this may make sense).
+
+The simplest menu TYPO3 can generate is then:
+
+page.20 = HMENU
+page.20.1 = TMENU
+page.20.1.NO = 1
+
+That will be pure <a> tags wrapped around page titles.]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="SPC" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for 'Spacer' pages.
+Spacers are pages of the doktype "Spacer". These are not viewable pages but "placeholders" which can be used to divide menuitems.
+
+Note: Rollovers doesn't work with spacers, if you use GMENU!]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="USERDEF1" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Userdefined, see .itemArrayProcFunc for details on how to use this.
+You can set the ITEM_STATE values USERDEF1 and USERDEF2 (+...RO) from a script/userfunction processing the menu item array. See HMENU/special=userdefined or the property .itemArrayProcFunc of the menu objects.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="USERDEF1RO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Userdefined, see .itemArrayProcFunc for details on how to use this.
+You can set the ITEM_STATE values USERDEF1 and USERDEF2 (+...RO) from a script/userfunction processing the menu item array. See HMENU/special=userdefined or the property .itemArrayProcFunc of the menu objects.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="USERDEF2" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       (See above)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="USERDEF2RO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       (See above)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="USR" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which are access restricted pages that a user has access to.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="USRRO" type="GMENU_itemState">
+                       <description><![CDATA[Boolean / (config)
+                       Enable/Configuration for menu items which are access restricted pages that a user has access to.]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="addParams" type="string">
+                       <description><![CDATA[Additional parameter for the menu-links. 
+Example:
+"&some_var=some%20value"
+Must be rawurlencoded.
+Applies to GMENU, TMENU, IMGMENU]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="IProcFunc" type="string">
+                       <description><![CDATA[The internal array “I” is passed to this function and expected returned as well. Subsequent to this function call the menu item is compiled by implode()'ing the array $I[parts] in the passed array. Thus you may modify this if you need to.
+See example on the testsite and in media/scripts/example_itemArrayProcFunc.php]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="RO" type="boolean">
+                       <description><![CDATA[RollOver configuration enabled / disabled. 
+If this is true, RO becomes a GIFBUILDER-object defining the layout of the menuitem when the mouse rolls over it]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="[Common Item States, see above]" type="GIFBUILDER">
+                       <description><![CDATA[This is the GIFBUILDER-options for each category of menuitem that can be generated.
+
+NOTE: For the GMENU series you can also define the RollOver configuration for the item states. This means that you define the GIFBUILDER object for the 'Active' state by ACT and the RollOver GIFBUILDER object for the 'Active' state by ACTRO.
+This pattern goes for ALL the states except the SPC state.
+
+SPECIAL:
+The ->OptionSplit function is run on the whole GIFBUILDER-configuration before the items are generated.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="accessKey" type="boolean">
+                       <description><![CDATA[If set access-keys are set on the menu-links]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="applyTotalH" type="string">
+                       <description><![CDATA[objNumsList (offset)
+                       
+                       This adds the total height of the previously generated menuitems to the offset of the GifBuilderObj's mentioned in this list.
+
+Example:
+This is useful it you want to create a menu with individual items but a common background image that extends to the whole area behind the menu. Then you should setup the background image in each GIFBUILDER-object and include the object-number in this list. 
+Look at the implementation in static_template "styles.gmenu.bug"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="applyTotalW" type="string">
+                       <description><![CDATA[objNumsList (offset)
+                       This adds the total width of the previously generated menuitems to the offset of the GifBuilderObj's mentioned in this list.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="collapse" type="boolean">
+                       <description><![CDATA[If set, "active" menuitems that has expanded the next level on the menu will now collapse that menu again.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="debugItemConf" type="string">
+                       <description><![CDATA[Outputs (by the debug()-function) the configuration arrays for each menuitem. Useful to debug optionSplit things and such...
+Applies to GMENU, TMENU, IMGMENU]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="disableAltText" type="boolean">
+                       <description><![CDATA[If set, the alt-parameter of the images are not set. You can do it manually by “imgParams” (see below)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="distributeX" type="int">
+                       <description><![CDATA[int+
+                       If set, the total width of all the menuitems will be equal to this number of pixels by adding/subtracting an equal amount of pixels to each menu items width.
+Will overrule any setting for ".useLargestItemX"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="distributeY" type="int">
+                       <description><![CDATA[int+
+                       If set, the total height of all the menuitems will be equal to this number of pixels by adding/subtracting an equal amount of pixels to each menu items height.
+Will overrule any setting for ".useLargestItemY"]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="expAll" type="Boolean">
+                       <description><![CDATA[If this is true, the menu will always show the menu on the level underneath the menuitem. This corresponds to a situation where a user has clicked a menuitem and the menu folds out the next level. This can enable that to happen on all items as default.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="forceTypeValue" type="int">
+                       <description><![CDATA[If set, the &type parameter of the link is forced to this value regardless of target. Overrides the global equivalent in 'config' if set.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="JSWindow" type="boolean">
+                       <description><![CDATA[If set, the links of the menu-items will open by JavaScript in a pop-up window. 
+
+.newWindow boolean, that lets every menuitem open in its own window opposite to opening in the same window for each click.
+
+.params is the list of parameters sent to the JavaScript open-window function, eg: 
+width=200,height=300,status=0,menubar=0
+
+NOTE: Does not work with JSMENU's]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="max" type="string">
+                       <description><![CDATA[x,y (calcInt)"
+                       
+                       Forces the menu as a whole to these maximum dimensions]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="min" type="x,y (calcInt)">
+                       <description><![CDATA[Forces the menu as a whole to these minimum dimensions]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="noBlur" type="boolean">
+                       <description><![CDATA[Normally graphical links are "blurred" if the browser is MSIE. Blurring removes the ugly box around a clicked link. 
+If this property is set, the link is NOT blurred (browser-default) with "onFocus".]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="overrideId" type="int">
+                       <description><![CDATA[integer (page-id)
+                       If set, then all links in the menu will point to this pageid. Instead the real uid of the page is sent by the parameter "&real_uid=[uid]".
+This feature is smart, if you have inserted a menu from somewhere else, perhaps a shared menu, but wants the menuitems to call the same page, which then generates a proper output based on the real_uid.
+Applies to GMENU, TMENU, IMGMENU]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="removeObjectsOfDummy" type="string">
+                       <description><![CDATA[objNumsList
+                       
+                       If the menu is forced to a certain minimum dimension, this is a list of objects in the gifbuilder-object that is removed for this last item. This is important to do if the menuitems has elements that should only be applied if the item is actually a menuitem!!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="stdWrap" type="stdWrap">
+                       <description><![CDATA[Wraps the whole item using stdWrap
+
+Example:
+2 = TMENU
+2 {
+  stdWrap.dataWrap = <ul class=”{register :
+     parentProperty}”> | </ul>
+  NO {
+    ...
+  }
+}]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="target" type="string">
+                       <description><![CDATA[target
+                       
+                       Target of the menulinks]]></description>
+                       <default><![CDATA[self]]></default>
+               </property>
+               <property name="submenuObjSuffixes" type="string">
+                       <description><![CDATA[Defines a suffix for alternative sub-level menu objects. Useful to create special submenus depending on their parent menu element. See example below.
+
+Example:
+This example will generate a menu where the menu objects for the second level will differ depending on the number of the first level item for which the submenu is rendered. The second level objects used are “2” (the default), “2a” and “2b” (the alternatives). Which of them is used is defined by “1.submenuObjSuffixes” which has the configuration “a |*| |*| b”. This configuration means that the first menu element will use configuration “2a” and the last will use “2b” while anything in between will use “2” (no suffix applied)
+
+page.200 = HMENU
+page.200 {
+  1 = TMENU
+  1.wrap = <div style="width:200px; border: 1px solid;">|</div>
+  1.expAll = 1
+  1.submenuObjSuffixes = a |*|  |*| b
+  1.NO.allWrap = <b>|</b><br/>
+
+  2 = TMENU
+  2.NO.allWrap = <div style="background:red;">|</div>
+
+  2a = TMENU
+  2a.NO.allWrap = <div style="background:yellow;">|</div>
+
+  2b = TMENU
+  2b.NO.allWrap = <div style="background:green;">|</div>
+}
+
+The result can be seen in the image below (applied on the testsite package):
+
+
+
+Applies to GMENU, TMENU, GMENU_LAYERS, TMENU_LAYERS and GMENU_FOLDOUT on >= 2nd level in a menu.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="useLargestItemX" type="boolean">
+                       <description><![CDATA[If set, then the width of all menuitems will be equal to the largest of them all.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="useLargestItemY" type="boolean">
+                       <description><![CDATA[If set, then the height of all menuitems will be equal to the largest of them all.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[Wraps only if there were items in the menu!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GMENU_itemState" extends="GIFBUILDER">
+               <property name="ATagParams" type="string">
+                       <description><![CDATA[Additional parameters]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="ATagTitle" type="stdWrap">
+                       <description><![CDATA[string /stdWrap
+                       
+                       which defines the title attribute of the a-tag. (See TMENUITEM also)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="additionalParams" type="string">
+                       <description><![CDATA[string /stdWrap
+                       
+                       Define parameters that are added to the end of the URL. This must be code ready to insert after the last parameter.
+
+For details, see typolink->additionalParams]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="allStdWrap" type="stdWrap">
+                       <description><![CDATA[stdWrap of the whole item]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="allWrap" type="stdWrap">
+                       <description><![CDATA[wrap /stdWrap
+                       
+                       Wraps the whole item]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="altImgResource" type="imgResouce">
+                       <description><![CDATA[Defines an alternative image to use. If an image returns here, it will override any GIFBUILDER configuration.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="altTarget" type="string">
+                       <description><![CDATA[Alternative target which overrides the target defined for the GMENU]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="imgParams" type="string">
+                       <description><![CDATA[params
+                       
+                       Parameters for the <img>-tag]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="noLink" type="boolean">
+                       <description><![CDATA[If set, the item is NOT linked!]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="subst_elementUid" type="boolean">
+                       <description><![CDATA[If set, "{elementUid}" is substituted with the item uid.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="wrap" type="wrap">
+                       <description><![CDATA[Wrap of the menu item]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+       </type>
+       <type id="GMENU_FOLDOUT" extends="GMENU">
+               <property name="adjustItemsH" type="int">
+                       <description><![CDATA[Adjusts the height calculation of the menulayers of the first level (called Top)
+
+Example:
+-10
+
+This value will substract 10 pixels from the height of the layer in calculations.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="adjustSubItemsH" type="int">
+                       <description><![CDATA[Adjusts the height calculation of the menulayers of the second level (subitems, called Sub)
+See above]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="arrowImgParams" type="string">
+                       <description><![CDATA[<img> params
+                       Parameters to the arrow-image.
+
+Example:
+hspace=5 vspace=7]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="arrowNO" type="imgResource">
+                       <description><![CDATA[If both arrowNO and arrowACT is defined and valid imgResources then these images are use as “traditional arrows” that indicates whether an item is expanded (active) or not. 
+NO is normal, ACT is expanded
+The image is inserted just before the menuitem. If you want to change the position, put the marker ###ARROW_IMAGE### into the wrap of the item and the image will be put there instead.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="bottomContent" type="cObj">
+                       <description><![CDATA[Content for the bottom layer that covers the end of the menu. ]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="bottomHeight" type="int">
+                       <description><![CDATA[pixels 
+                       Sets the height of the bottom layer. Is important if the bottomlayer  contains either content or a background color: Else the layer will be clipped.]]></description>
+                       <default><![CDATA[100]]></default>
+               </property>
+               <property name="displayActiveOnLoad" type="boolean">
+                       <description><![CDATA[If set, then the active menu items will fold out “onLoad”]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="dontLinkIfSubmenu" type="boolean">
+                       <description><![CDATA[If set, items that has a submenu is not linked. Items without a submenu are always linked in the regular ways.]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="dontWrapInTable" type="boolean">
+                       <description><![CDATA[By default every menuitem on the first level is wrapped in a table:
+<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0><TR><TD>
+[menu item HTML here..]
+</TD></TR></TABLE>
+Doing this ensures that the layers renders equally in the supported browsers. However you might need to disable that which is what you can do by setting this flag.
+Note: Using <TBODY> in this tables seems to break Netscape 4+]]></description>
+                       <default><![CDATA[0]]></default>
+               </property>
+               <property name="foldSpeed" type="int">
+                       <description><![CDATA[int, range 1-100
+                       
+                       How many steps in an animation? Choose 1 for no animation.]]></description>
+                       <default><![CDATA[1]]></default>
+               </property>
+               <property name="foldTimer" type="int">
+                       <description><![CDATA[The timeout in the animation, these are milliseconds.]]></description>
+                       <default><![CDATA[40]]></default>
+               </property>
+               <property name="JSWindow" type="boolean">
+                       <description><![CDATA[If set, the links of the menu-items will open by JavaScript in a pop-up window. 
+
+.newWindow boolean, that lets every menuitem open in its own window opposite to opening in the same window for each click.
+
+.params is the list of parameters sent to the JavaScript open-window function, eg: 
+width=200,height=300,status=0,menubar=0
+
+NOTE: Does not work with JSMENU's]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="menuBackColor" type="string">
+                       <description><![CDATA[HTML-color
+                       
+                       Background color behind menu. If not set, transparent (which will not work very well in case .foldSpeed is set to something else than 1. But see for yourself)]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="menuHeight" type="int">
+                       <description><![CDATA[Height of the whole menulayer. Seems to be not so important.]]></description>
+                       <default><![CDATA[400]]></default>
+               </property>
+               <property name="menuOffset" type="string">
+                       <description><![CDATA[x,y
+                       
+                       Offset of the menu main layer on the page. From upperleft corner]]></description>
+                       <default><![CDATA[
+]]></default>
+               </property>
+               <property name="menuWidth" type="int">
+ &n