[BUGFIX] Adjustments to FAL-enabled RTE image and link dialogues
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / class.tx_rtehtmlarea_base.php
index e25b196..f45ece2 100644 (file)
@@ -2,9 +2,9 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004 Kasper Skaarhoj (kasper@typo3.com)
-*  (c) 2004 Philipp Borgmann <philipp.borgmann@gmx.de>
-*  (c) 2004-2008 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2011 Kasper Skårhøj (kasper@typo3.com)
+*  (c) 2004-2011 Philipp Borgmann <philipp.borgmann@gmx.de>
+*  (c) 2004-2012 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  *
  * @author     Philipp Borgmann <philipp.borgmann@gmx.de>
  * @author     Stanislas Rolland <typo3(arobas)sjbr.ca>
- *
- * $Id$  *
  */
 
-require_once(PATH_t3lib.'class.t3lib_rteapi.php');
-require_once(PATH_t3lib.'class.t3lib_cs.php');
-
 class tx_rtehtmlarea_base extends t3lib_rteapi {
-
                // Configuration of supported browsers
        var $conf_supported_browser = array (
                        'msie' => array (
-                               1 => array (
-                                       'version' => 5.5,
-                                       'system' => 'win'
-                               )
+                               array (
+                                       'version' => 6.0,
+                                       'system' => array(
+                                               'allowed' => array(
+                                                       'winNT',
+                                                       'win98',
+                                                       'win95',
+                                               ),
+                                       ),
+                               ),
                        ),
                        'gecko' => array (
-                               1 => array (
-                                       'version' => 1.3
-                               )
+                               array (
+                                       'version' => 1.8,
+                               ),
                        ),
-                       'safari' => array (
-                               1 => array (
-                                       'version' => 523
-                               )
+                       'webkit' => array (
+                               array (
+                                       'version' => 523,
+                                       'system' => array(
+                                               'disallowed' => array(
+                                                       'iOS',
+                                                       'android',
+                                               ),
+                                       ),
+                               ),
                        ),
                        'opera' => array (
-                               1 => array (
-                                       'version' => 9.5
-                               )
+                               array (
+                                       'version' => 9.62,
+                                       'system' => array(
+                                               'disallowed' => array(
+                                                       'iOS',
+                                                       'android',
+                                               ),
+                                       ),
+                               ),
                        )
                );
 
@@ -69,48 +81,38 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
        var $conf_toolbar_hide = array (
                'showhelp',             // Has no content yet
                );
-       
-               // Always show these toolbar buttons (TYPO3 button name)
-       var $conf_toolbar_show = array (
-               'undo',
-               'redo',
-               //'showhelp',
-               'about',
-               );
-       
+
                // The order of the toolbar: the name is the TYPO3-button name
        var $defaultToolbarOrder;
-       
+
                // Conversion array: TYPO3 button names to htmlArea button names
        var $convertToolbarForHtmlAreaArray = array (
-               'line'                  => 'InsertHorizontalRule',
-               'chMode'                => 'HtmlMode',
                'showhelp'              => 'ShowHelp',
-               'textindicator'         => 'TextIndicator',
                'space'                 => 'space',
                'bar'                   => 'separator',
                'linebreak'             => 'linebreak',
                );
-       
-       var $pluginList;
+
        var $pluginButton = array();
        var $pluginLabel = array();
-       
-               // External:
-       var $RTEdivStyle;                       // Alternative style for RTE <div> tag.
-       public $httpTypo3Path;
-       var $extHttpPath;                       // full Path to this extension for http (so no Server path). It ends with "/"
-       var $siteURL;                           // TYPO3 site url
-       var $hostURL;                           // TYPO3 host url
-       var $typoVersion;                       // Typo3 version
-
-               // Internal, static:
-       var $ID = 'rtehtmlarea';                // Identifies the RTE as being the one from the "rte" extension if any external code needs to know...
-       var $debugMode = FALSE;                 // If set, the content goes into a regular TEXT area field - for developing testing of transformations. (Also any browser will load the field!)
-
+               // Alternative style for RTE <div> tag.
+       public $RTEdivStyle;
+               // Relative path to this extension. It ends with "/"
+       public $extHttpPath;
+       public $backPath = '';
+               // TYPO3 site url
+       public $siteURL;
+               // TYPO3 host url
+       public $hostURL;
+               // Typo3 version
+       public $typoVersion;
+               // Identifies the RTE as being the one from the "rtehtmlarea" extension if any external code needs to know
+       var $ID = 'rtehtmlarea';
+               // If set, the content goes into a regular TEXT area field - for developing testing of transformations.
+       var $debugMode = FALSE;
                // For the editor
        var $client;
-       
+
        /**
         * Reference to parent object, which is an instance of the TCEforms
         *
@@ -128,65 +130,88 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
        public $language;
        public $contentTypo3Language;
        public $contentISOLanguage;
-       public $contentCharset;
-       public $OutputCharset;
+       public $charset = 'utf-8';
+       public $contentCharset = 'utf-8';
+       public $OutputCharset = 'utf-8';
        var $editorCSS;
        var $specConf;
        var $toolbar = array();                                 // Save the buttons for the toolbar
-       var $toolbar_level_size;                                // The size for each level in the toolbar:
        var $toolbarOrderArray = array();
        protected $pluginEnabledArray = array();                // Array of plugin id's enabled in the current RTE editing area
        protected $pluginEnabledCumulativeArray = array();      // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form
        public $registeredPlugins = array();                    // Array of registered plugins indexed by their plugin Id's
-       
+       protected $fullScreen = FALSE;
+       protected $pageRenderer;
+
        /**
-        * Returns true if the RTE is available. Here you check if the browser requirements are met.
+        * Returns TRUE if the RTE is available. Here you check if the browser requirements are met.
         * If there are reasons why the RTE cannot be displayed you simply enter them as text in ->errorLog
         *
         * @return      boolean         TRUE if this RTE object offers an RTE in the current browser environment
         */
-       
        function isAvailable()  {
-               global $TYPO3_CONF_VARS;
-               
+
                $this->client = $this->clientInfo();
                $this->errorLog = array();
                if (!$this->debugMode)  {       // If debug-mode, let any browser through
-                       $rteIsAvailable = 0;
+                       $rteIsAvailable = FALSE;
                        $rteConfBrowser = $this->conf_supported_browser;
-                       if (!$TYPO3_CONF_VARS['EXTCONF']['rtehtmlarea']['enableInOpera9']) unset($rteConfBrowser['opera']);
                        if (is_array($rteConfBrowser)) {
                                foreach ($rteConfBrowser as $browser => $browserConf) {
-                                       if ($browser == $this->client['BROWSER']) {
+                                       if ($browser == $this->client['browser']) {
                                                        // Config for Browser found, check it:
                                                if (is_array($browserConf)) {
-                                                       foreach ($browserConf as $browserConfNr => $browserConfSub) {
-                                                               if ($browserConfSub['version'] <= $this->client['VERSION'] || empty($browserConfSub['version'])) {
-                                                                       // Version is correct
-                                                                       if ($browserConfSub['system'] == $this->client['SYSTEM'] || empty($browserConfSub['system'])) {
-                                                                                       // System is correctly
-                                                                               $rteIsAvailable = 1;
+                                                       foreach ($browserConf as $browserConfSub) {
+                                                               if ($browserConfSub['version'] <= $this->client['version'] || empty($browserConfSub['version'])) {
+                                                                               // Version is supported
+                                                                       if (is_array($browserConfSub['system'])) {
+                                                                                       // Check against allowed systems
+                                                                               if (is_array($browserConfSub['system']['allowed'])) {
+                                                                                       foreach ($browserConfSub['system']['allowed'] as $system) {
+                                                                                               if (in_array($system, $this->client['all_systems'])) {
+                                                                                                       $rteIsAvailable = TRUE;
+                                                                                                       break;
+                                                                                               }
+                                                                                       }
+                                                                               } else {
+                                                                                               // All allowed
+                                                                                       $rteIsAvailable = TRUE;
+                                                                               }
+                                                                                       // Check against disallowed systems
+                                                                               if (is_array($browserConfSub['system']['disallowed'])) {
+                                                                                       foreach ($browserConfSub['system']['disallowed'] as $system) {
+                                                                                               if (in_array($system, $this->client['all_systems'])) {
+                                                                                                       $rteIsAvailable = FALSE;
+                                                                                                       break;
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                       } else {
+                                                                                       // No system config: system is supported
+                                                                               $rteIsAvailable = TRUE;
+                                                                               break;
                                                                        }// End of System
                                                                }// End of Version
                                                        }// End of foreach-BrowserSubpart
                                                } else {
                                                        // no config for this browser found, so all versions or system with this browsers are allow
-                                                       $rteIsAvailable = 1;
+                                                       $rteIsAvailable = TRUE;
+                                                       break;
                                                }
                                        } // End of Browser Check
                                } // foreach: Browser Check
                        } else {
-                               // no Browser config for this RTE-Editor, so all Clients are allow                         
+                               // no Browser config for this RTE-Editor, so all Clients are allow
                        }
                        if (!$rteIsAvailable) {
-                               $this->errorLog[] = 'rte: Browser not supported. Only msie Version 5 or higher and Mozilla based client 1. and higher.';
+                               $this->errorLog[] = 'RTE: Browser not supported.';
                        }
-                       if (t3lib_div::int_from_ver(TYPO3_version) < 4000000) {
-                               $rteIsAvailable = 0;
+                       if (t3lib_utility_VersionNumber::convertVersionNumberToInteger(TYPO3_version) < 4000000) {
+                               $rteIsAvailable = FALSE;
                                $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
                        }
                }
-               if ($rteIsAvailable)    return true;
+               return $rteIsAvailable;
        }
 
        /**
@@ -204,45 +229,37 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         * @param       integer         PID value of record (true parent page id)
         * @return      string          HTML code for RTE!
         */
-       
+
        function drawRTE($parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
-               global $BE_USER, $LANG, $TYPO3_DB, $TYPO3_CONF_VARS;
-               
-               $this->TCEform =& $parentObject;
-               $inline =& $this->TCEform->inline;
+               global $LANG, $TYPO3_DB, $TYPO3_CONF_VARS;
+
+               $this->TCEform = $parentObject;
+               $inline = $this->TCEform->inline;
                $LANG->includeLLFile('EXT:' . $this->ID . '/locallang.xml');
                $this->client = $this->clientInfo();
-               $this->typoVersion = t3lib_div::int_from_ver(TYPO3_version);
-               $this->userUid = 'BE_' . $BE_USER->user['uid'];
-               
+               $this->typoVersion = t3lib_utility_VersionNumber::convertVersionNumberToInteger(TYPO3_version);
+               $this->userUid = 'BE_' . $GLOBALS['BE_USER']->user['uid'];
+
                        // Draw form element:
                if ($this->debugMode)   {       // Draws regular text area (debug mode)
                        $item = parent::drawRTE($this->TCEform, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
                } else {        // Draw real RTE
-               
+
                        /* =======================================
                         * INIT THE EDITOR-SETTINGS
                         * =======================================
                         */
-
-                               // first get the http-path to typo3:
-                       $this->httpTypo3Path = substr( substr( t3lib_div::getIndpEnv('TYPO3_SITE_URL'), strlen( t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST') ) ), 0, -1 );
-                       if (strlen($this->httpTypo3Path) == 1) {
-                               $this->httpTypo3Path = '/';
-                       } else {
-                               $this->httpTypo3Path .= '/';
-                       }
+                               // Set backPath
+                       $this->backPath = $this->TCEform->backPath;
                                // Get the path to this extension:
-                       $this->extHttpPath = $this->httpTypo3Path . t3lib_extMgm::siteRelPath($this->ID);
+                       $this->extHttpPath = $this->backPath . t3lib_extMgm::extRelPath($this->ID);
                                // Get the site URL
                        $this->siteURL = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
                                // Get the host URL
-                       $this->hostURL = t3lib_div::getIndpEnv('TYPO3_REQUEST_HOST');
-
+                       $this->hostURL = $this->siteURL . TYPO3_mainDir;
                                // Element ID + pid
                        $this->elementId = $PA['itemFormElName']; // Form element name
-                       $this->elementParts = explode('][',ereg_replace('\]$','',ereg_replace('^(TSFE_EDIT\[data\]\[|data\[)','',$this->elementId)));
-
+                       $this->elementParts = explode('][',preg_replace('/\]$/','',preg_replace('/^(TSFE_EDIT\[data\]\[|data\[)/','',$this->elementId)));
                                // Find the page PIDs:
                        list($this->tscPID,$this->thePid) = t3lib_BEfunc::getTSCpid(trim($this->elementParts[0]),trim($this->elementParts[1]),$thePidValue);
 
@@ -251,19 +268,22 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
 
                                // Find "thisConfig" for record/editor:
                        unset($this->RTEsetup);
-                       $this->RTEsetup = $BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($this->tscPID));
+                       $this->RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', t3lib_BEfunc::getPagesTSconfig($this->tscPID));
                        $this->thisConfig = $thisConfig;
 
                                // Special configuration and default extras:
                        $this->specConf = $specConf;
-                       
+
                        if ($this->thisConfig['forceHTTPS']) {
-                               $this->httpTypo3Path = preg_replace('/^(http|https)/', 'https', $this->httpTypo3Path);
                                $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
                                $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
                                $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
                        }
-                       
+                               // Register RTE windows
+                       $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
+                       $textAreaId = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $PA['itemFormElName']);
+                       $textAreaId = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $textAreaId));
+
                        /* =======================================
                         * LANGUAGES & CHARACTER SETS
                         * =======================================
@@ -271,11 +291,11 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
 
                                // Languages: interface and content
                        $this->language = $LANG->lang;
-                       if ($this->language=='default' || !$this->language)     {
-                               $this->language='en';
+                       if ($this->language == 'default' || !$this->language)   {
+                               $this->language = 'en';
                        }
-                       $this->contentTypo3Language = $this->language;
-                       
+                       $this->contentTypo3Language = ($this->language == 'en') ? 'default' : $this->language;
+                       $this->contentISOLanguage = 'en';
                        $this->contentLanguageUid = ($row['sys_language_uid'] > 0) ? $row['sys_language_uid'] : 0;
                        if (t3lib_extMgm::isLoaded('static_info_tables')) {
                                if ($this->contentLanguageUid) {
@@ -290,131 +310,82 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                        $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
                                        while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
                                                $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']).(trim($languageRow['lg_country_iso_2'])?'_'.trim($languageRow['lg_country_iso_2']):''));
-                                               $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
+                                               $this->contentTypo3Language = trim($languageRow['lg_typo3']) ? strtolower(trim($languageRow['lg_typo3'])) : 'default';
                                        }
                                } else {
-                                       $this->contentISOLanguage = trim($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['defaultDictionary']) ? trim($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['defaultDictionary']) : 'en';
+                                       $this->contentISOLanguage = trim($this->thisConfig['defaultContentLanguage']) ? trim($this->thisConfig['defaultContentLanguage']) : 'en';
                                        $selectFields = 'lg_iso_2, lg_typo3';
                                        $tableAB = 'static_languages';
                                        $whereClause = 'lg_iso_2 = ' . $TYPO3_DB->fullQuoteStr(strtoupper($this->contentISOLanguage), $tableAB);
                                        $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
                                        while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
-                                               $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
+                                               $this->contentTypo3Language = trim($languageRow['lg_typo3']) ? strtolower(trim($languageRow['lg_typo3'])) : 'default';
                                        }
                                }
                        }
-                       
-                               // Character sets: interface and content
-                       $this->charset = $LANG->charSet;
-                       $this->OutputCharset = $this->charset;
-                       
-                       $this->contentCharset = $LANG->csConvObj->charSetArray[$this->contentTypo3Language];
-                       $this->contentCharset = $this->contentCharset ? $this->contentCharset : 'iso-8859-1';
-                       $this->origContentCharSet = $this->contentCharset;
-                       $this->contentCharset = (trim($TYPO3_CONF_VARS['BE']['forceCharset']) ? trim($TYPO3_CONF_VARS['BE']['forceCharset']) : $this->contentCharset);
 
                        /* =======================================
                         * TOOLBAR CONFIGURATION
                         * =======================================
                         */
-                       
-                               // htmlArea plugins list
-                       $this->pluginEnabledArray = t3lib_div::trimExplode(',', $this->pluginList, 1);
-                       $this->enableRegisteredPlugins();
+                       $this->initializeToolbarConfiguration();
 
-                       if ($this->client['BROWSER'] == 'msie') {
-                               $this->thisConfig['keepButtonGroupTogether'] = 0;
-                       }
-                       if ($this->client['BROWSER'] == 'opera') {
-                               $this->thisConfig['keepButtonGroupTogether'] = 0;
-                       }
-                       if ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')  {
-                               $this->thisConfig['keepButtonGroupTogether'] = 0;
-                       }
-
-                               // Toolbar
-                       $this->setToolbar();
-
-                               // Check if some plugins need to be disabled
-                       $this->setPlugins();
-                       
-                               // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
-                       $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
-                       if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])) {
-                               $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray,$this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])));
-                       }
-                       
                        /* =======================================
                         * SET STYLES
                         * =======================================
                         */
-
-                       $RTEWidth = isset($BE_USER->userTS['options.']['RTESmallWidth']) ? $BE_USER->userTS['options.']['RTESmallWidth'] : '530';
-                       $RTEHeight = isset($BE_USER->userTS['options.']['RTESmallHeight']) ? $BE_USER->userTS['options.']['RTESmallHeight'] : '380';
-                       $RTEWidth  = $RTEWidth + ($this->TCEform->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeWidthIncrement']) ? $BE_USER->userTS['options.']['RTELargeWidthIncrement'] : '150') : 0);
-                       $RTEWidth -= ($inline->getStructureDepth() > 0 ? ($inline->getStructureDepth()+1)*$inline->getLevelMargin() : 0);
-                       $RTEHeight = $RTEHeight + ($this->TCEform->docLarge ?  (isset($BE_USER->userTS['options.']['RTELargeHeightIncrement']) ? $BE_USER->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
-                       $RTEHeightOverride = intval($this->thisConfig['RTEHeightOverride']);
-                       $RTEHeight = ($RTEHeightOverride > 0) ? $RTEHeightOverride : $RTEHeight;
-                       $editorWrapWidth = $RTEWidth . 'px';
-                       $editorWrapHeight = $RTEHeight . 'px';
-                       $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:'.$RTEWidth.'px; border: 1px solid black; padding: 2px 0px 2px 2px;';
-                       $this->toolbar_level_size = $RTEWidth;
-
-                       /* =======================================
-                        * LOAD CSS AND JAVASCRIPT
-                        * =======================================
-                        */
-
-                               // Preloading the pageStyle
-                       $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
-                       $this->TCEform->additionalCode_pre['loadCSS'] = '
-               <link rel="alternate stylesheet" type="text/css" href="' . $this->getFullFileName($filename) . '" title="HTMLArea RTE Content CSS" />';
-
-                               // Loading the editor skin
-                       $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
-                       if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3' && substr($skinFilename,0,4) == 'EXT:')  {
-                               $skinFilename = 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
-                       }
-                       if (substr($skinFilename,0,4) == 'EXT:')      {       // extension
-                               list($extKey,$local) = explode('/',substr($skinFilename,4),2);
-                               $skinFilename='';
-                               if (strcmp($extKey,'') &&  t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
-                                       $skinFilename = $this->httpTypo3Path . t3lib_extMgm::siteRelPath($extKey) . $local;
-                                       $skinDir = $this->siteURL . t3lib_extMgm::siteRelPath($extKey) . dirname($local);
-                               }
-                       } elseif (substr($skinFilename,0,1) != '/') {
-                               $skinDir = $this->siteURL.dirname($skinFilename);
-                               $skinFilename = $this->siteURL . $skinFilename;
+                               // Check if wizard_rte called this for fullscreen edtition
+                       if (basename(PATH_thisScript) == 'wizard_rte.php') {
+                               $this->fullScreen = TRUE;
+                               $RTEWidth = '100%';
+                               $RTEHeight = '100%';
+                               $RTEPaddingRight = '0';
+                               $editorWrapWidth = '100%';
                        } else {
-                               $skinDir = substr($this->siteURL,0,-1) . dirname($skinFilename);
-                       }
-                       $this->editorCSS = $skinFilename;
-                       $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
-                       $this->TCEform->additionalCode_pre['loadCSS'] .= '
-               <link rel="alternate stylesheet" type="text/css" href="' . $this->editedContentCSS . '" />';
-                       
-                               // Main skin
-                       $this->TCEform->additionalCode_pre['loadCSS'] .= '
-               <link rel="stylesheet" type="text/css" href="' . $this->editorCSS . '" />';
-                       
-                               // Additional icons from registered plugins
-                       foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
-                               if (is_object($this->registeredPlugins[$pluginId])) {
-                                       $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
-                                       if ($pathToSkin) {
-                                               $this->TCEform->additionalCode_pre['loadCSS'] .= '
-               <link rel="stylesheet" type="text/css" href="' . $this->httpTypo3Path . t3lib_extMgm::siteRelPath($this->registeredPlugins[$pluginId]->getExtensionKey()) . $pathToSkin . '" />';
+                               $RTEWidth = isset($GLOBALS['BE_USER']->userTS['options.']['RTESmallWidth']) ? $GLOBALS['BE_USER']->userTS['options.']['RTESmallWidth'] : '530';
+                               $RTEHeight = isset($GLOBALS['BE_USER']->userTS['options.']['RTESmallHeight']) ? $GLOBALS['BE_USER']->userTS['options.']['RTESmallHeight'] : '380';
+                               $RTEWidth  = $RTEWidth + ($this->TCEform->docLarge ? (isset($GLOBALS['BE_USER']->userTS['options.']['RTELargeWidthIncrement']) ? $GLOBALS['BE_USER']->userTS['options.']['RTELargeWidthIncrement'] : '150') : 0);
+                               $RTEWidth -= ($inline->getStructureDepth() > 0 ? ($inline->getStructureDepth()+1)*$inline->getLevelMargin() : 0);
+                               $RTEWidthOverride = (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteWidth']) && trim($GLOBALS['BE_USER']->uc['rteWidth'])) ? trim($GLOBALS['BE_USER']->uc['rteWidth']) : trim($this->thisConfig['RTEWidthOverride']);
+                               if ($RTEWidthOverride) {
+                                       if (strstr($RTEWidthOverride, '%')) {
+                                               if ($this->client['browser'] != 'msie') {
+                                                       $RTEWidth = (intval($RTEWidthOverride) > 0) ? $RTEWidthOverride : '100%';
+                                               }
+                                       } else {
+                                               $RTEWidth = (intval($RTEWidthOverride) > 0) ? intval($RTEWidthOverride) : $RTEWidth;
                                        }
                                }
+                               $RTEWidth = strstr($RTEWidth, '%') ? $RTEWidth :  $RTEWidth . 'px';
+                               $RTEHeight = $RTEHeight + ($this->TCEform->docLarge ?  (isset($GLOBALS['BE_USER']->userTS['options.']['RTELargeHeightIncrement']) ? $GLOBALS['BE_USER']->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
+                               $RTEHeightOverride = (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && intval($GLOBALS['BE_USER']->uc['rteHeight'])) ? intval($GLOBALS['BE_USER']->uc['rteHeight']) : intval($this->thisConfig['RTEHeightOverride']);
+                               $RTEHeight = ($RTEHeightOverride > 0) ? $RTEHeightOverride : $RTEHeight;
+                               $RTEPaddingRight = '2px';
+                               $editorWrapWidth = '99%';
                        }
-                       
-                               // Loading JavaScript files and code
-                       if ($this->TCEform->RTEcounter == 1) {
-                               $this->TCEform->additionalCode_pre['loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter);
-                               $this->TCEform->additionalJS_pre['loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
-                       }
-
+                       $editorWrapHeight = '100%';
+                       $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:' . $RTEWidth . '; border: 1px solid black; padding: 2px ' . $RTEPaddingRight . ' 2px 2px;';
+                       /* =======================================
+                        * LOAD CSS AND JAVASCRIPT
+                        * =======================================
+                        */
+                       $this->pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
+                               // Preloading the pageStyle and including RTE skin stylesheets
+                       $this->addPageStyle();
+                       $this->addSkin();
+                               // Register RTE in JS
+                       $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
+                               // Set the save option for the RTE
+                       $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId, $PA['itemFormElName']);
+                       $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
+                               // Loading ExtJs inline code
+                       $this->pageRenderer->enableExtJSQuickTips();
+                               // Add TYPO3 notifications JavaScript
+                       $this->pageRenderer->addJsFile('../t3lib/js/extjs/notifications.js');
+                               // Add RTE JavaScript
+                       $this->addRteJsFiles($this->TCEform->RTEcounter);
+                       $this->pageRenderer->addJsFile($this->buildJSMainLangFile($this->TCEform->RTEcounter));
+                       $this->pageRenderer->addJsInlineCode('HTMLArea-init', $this->getRteInitJsCode(), TRUE);
                        /* =======================================
                         * DRAW THE EDITOR
                         * =======================================
@@ -422,57 +393,139 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
 
                                // Transform value:
                        $value = $this->transformContent('rte',$PA['itemFormElValue'],$table,$field,$row,$specConf,$thisConfig,$RTErelPath,$thePidValue);
-                       
+
                                // Further content transformation by registered plugins
                        foreach ($this->registeredPlugins as $pluginId => $plugin) {
                                if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "transformContent")) {
                                        $value = $plugin->transformContent($value);
                                }
                        }
-                               // Register RTE windows
-                       $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
-                       $textAreaId = htmlspecialchars($PA['itemFormElName']);
-
-                               // Check if wizard_rte called this for fullscreen edtition; if so, change the size of the RTE to fullscreen using JS
-                       if (basename(PATH_thisScript) == 'wizard_rte.php') {
-                               $height = 'window.innerHeight';
-                               $width = 'window.innerWidth';
-                               if ($this->client['BROWSER'] == 'msie') {
-                                       $height = 'document.body.offsetHeight';
-                                       $width = 'document.body.offsetWidth';
-                               }
-                               
-                                       // Subtract the docheader height from the calculated window height
-                               $height .= ' - document.getElementById("typo3-docheader").offsetHeight';      
-                               
-                               $editorWrapWidth = '100%';
-                               $editorWrapHeight = '100%';
-                               $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border: 1px solid black; padding: 2px 0px 2px 2px;';
-                               $this->TCEform->additionalJS_post[] = $this->setRTEsizeByJS('RTEarea' . $textAreaId, $height, $width);
-                       }
-
-                               // Register RTE in JS:
-                       $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
-
-                               // Set the save option for the RTE:
-                       $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
-                       $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
-
                                // Draw the textarea
                        $visibility = 'hidden';
-                       $unuqid = uniqid('rte');
                        $item = $this->triggerField($PA['itemFormElName']).'
                                <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $LANG->getLL('Please wait') . '</div>
                                <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:' . $editorWrapHeight . ';">
-                               <textarea id="RTEarea' . $textAreaId . '" name="'.htmlspecialchars($PA['itemFormElName']).'" style="'.t3lib_div::deHSCentities(htmlspecialchars($this->RTEdivStyle)).'">'.t3lib_div::formatForTextarea($value).'</textarea>
-                               </div>' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableDebugMode'] ? '<div id="HTMLAreaLog"></div>' : '') . '
-                               ';
+                               <textarea id="RTEarea' . $textAreaId . '" name="'.htmlspecialchars($PA['itemFormElName']).'" rows="0" cols="0" style="'.t3lib_div::deHSCentities(htmlspecialchars($this->RTEdivStyle)).'">'.t3lib_div::formatForTextarea($value).'</textarea>
+                               </div>' . LF;
                }
 
                        // Return form item:
                return $item;
        }
-       
+
+       /**
+        * Add link to content style sheet to document header
+        *
+        * @return      void
+        */
+       protected function addPageStyle() {
+               $this->addStyleSheet(
+                       'rtehtmlarea-page-style',
+                       $this->getContentCssFileName(),
+                       'htmlArea RTE Content CSS',
+                       'alternate stylesheet'
+               );
+       }
+
+       /**
+        * Get the name of the contentCSS file to use
+        *
+        * @return      the full file name of the content css file to use
+        */
+       protected function getContentCssFileName() {
+                       // Get stylesheet file name from Page TSConfig if any
+               $fileName = trim($this->thisConfig['contentCSS']);
+               if ($fileName) {
+                       $fileName = $this->getFullFileName($fileName);
+               }
+               $absolutePath = $fileName
+                       ? t3lib_div::resolveBackPath(PATH_site . (($this->is_FE() || $this->isFrontendEditActive()) ? '' : TYPO3_mainDir) . $fileName)
+                       : '';
+
+                       // Fallback to default content css file if configured file does not exists or is of zero size
+               if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
+                       $fileName = $this->getFullFileName('EXT:' . $this->ID . '/res/contentcss/default.css');
+               }
+               return $fileName;
+       }
+
+       /**
+        * Add links to skin style sheet(s) to document header
+        *
+        * @return      void
+        */
+       protected function addSkin() {
+                       // Get skin file name from Page TSConfig if any
+               $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
+               $this->editorCSS = $this->getFullFileName($skinFilename);
+               $skinDir = dirname($this->editorCSS);
+                       // Editing area style sheet
+               $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
+               $this->addStyleSheet(
+                       'rtehtmlarea-editing-area-skin',
+                       $this->editedContentCSS
+                       );
+                       // Main skin
+               $this->addStyleSheet(
+                       'rtehtmlarea-skin',
+                       $this->editorCSS
+                       );
+                       // Additional icons from registered plugins
+               foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
+                       if (is_object($this->registeredPlugins[$pluginId])) {
+                               $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
+                               if ($pathToSkin) {
+                                       $key = $this->registeredPlugins[$pluginId]->getExtensionKey();
+                                       $this->addStyleSheet(
+                                               'rtehtmlarea-plugin-' . $pluginId . '-skin',
+                                               ($this->is_FE() ? t3lib_extMgm::siteRelPath($key) : $this->backPath . t3lib_extMgm::extRelPath($key)) . $pathToSkin
+                                               );
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Add style sheet file to document header
+        *
+        * @param       string          $key: some key identifying the style sheet
+        * @param       string          $href: uri to the style sheet file
+        * @param       string          $title: value for the title attribute of the link element
+        * @return      string          $relation: value for the rel attribute of the link element
+        * @return      void
+        */
+       protected function addStyleSheet($key, $href, $title='', $relation='stylesheet') {
+                       // If it was not known that an RTE-enabled would be created when the page was first created, the css would not be added to head
+               if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
+                       $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title. '" />';
+               } else {
+                       $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
+               }
+       }
+
+       /**
+        * Initialize toolbar configuration and enable registered plugins
+        *
+        * @return      void
+        */
+       protected function initializeToolbarConfiguration() {
+
+                       // Enable registred plugins
+               $this->enableRegisteredPlugins();
+
+                       // Configure toolbar
+               $this->setToolbar();
+
+                       // Check if some plugins need to be disabled
+               $this->setPlugins();
+
+                       // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
+               $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
+               if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])) {
+                       $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray,$this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])));
+               }
+       }
+
        /**
         * Add registered plugins to the array of enabled plugins
         *
@@ -482,9 +535,9 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                        // Traverse registered plugins
                if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
                        foreach($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
-                               $plugin = false;
+                               $plugin = FALSE;
                                if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
-                                       $plugin = &t3lib_div::getUserObj($pluginObjectConfiguration['objectReference']);
+                                       $plugin = t3lib_div::getUserObj($pluginObjectConfiguration['objectReference']);
                                }
                                if (is_object($plugin)) {
                                        if ($plugin->main($this)) {
@@ -512,51 +565,31 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                $hidePlugins[] = $pluginId;
                        }
                }
-               $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
+               $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
        }
-       
+
        /**
         * Set the toolbar config (only in this PHP-Object, not in JS):
         *
         */
 
        function setToolbar() {
-               global $BE_USER;
-               
+               if ($this->client['browser'] == 'msie' || $this->client['browser'] == 'opera') {
+                       $this->thisConfig['keepButtonGroupTogether'] = 0;
+               }
+
                $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
                        bar, formattext, bold,  strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
-                       bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote,
+                       bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
                        bar, left, center, right, justifyfull,
-                       bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent,  bar, lefttoright, righttoleft,
+                       bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent,  bar, lefttoright, righttoleft, language, showlanguagemarks,
                        bar, textcolor, bgcolor, textindicator,
-                       bar, emoticon, insertcharacter, line, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
-                       bar, chMode, inserttag, removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak, 
+                       bar, editelement, showmicrodata, emoticon, insertcharacter, insertsofthyphen, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
+                       bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
                        ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
                        columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
                        cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
-               
-                       // Special toolbar for Mozilla Wamcom on Mac OS 9
-               if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')  {
-                       $this->defaultToolbarOrder = $this->TCEform->docLarge ? 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
-                               bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
-                               subscript, superscript, lefttoright, righttoleft, bar, left, center, right, justifyfull, linebreak,
-                               bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
-                               insertcharacter, line, link, unlink, image, table, user, acronym, bar, findreplace, spellcheck, bar, chMode, inserttag,
-                               removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
-                               bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
-                               columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
-                               cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge'
-                               : 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
-                               bar, fontstyle, space, fontsize, space, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, bar, bold, italic, underline, strikethrough,
-                               subscript, superscript, linebreak, bar, lefttoright, righttoleft, bar, left, center, right, justifyfull,
-                               orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, textcolor, bgcolor, textindicator, bar, emoticon,
-                               insertcharacter, line, link, unlink, image, table, user, acronym, linebreak, bar, findreplace, spellcheck, bar, chMode, inserttag,
-                               removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
-                               bar, toggleborders, bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
-                               columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
-                               cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
-               }
-               
+
                        // Additional buttons from registered plugins
                foreach($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId)) {
@@ -591,13 +624,13 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                }
 
                        // Resticting to RTEkeyList for backend user
-               if(is_object($BE_USER)) {
-                       $RTEkeyList = isset($BE_USER->userTS['options.']['RTEkeyList']) ? $BE_USER->userTS['options.']['RTEkeyList'] : '*';
+               if(is_object($GLOBALS['BE_USER'])) {
+                       $RTEkeyList = isset($GLOBALS['BE_USER']->userTS['options.']['RTEkeyList']) ? $GLOBALS['BE_USER']->userTS['options.']['RTEkeyList'] : '*';
                        if ($RTEkeyList != '*') {       // If not all
                                $show = array_intersect($show, t3lib_div::trimExplode(',',$RTEkeyList,1));
                        }
                }
-               
+
                        // Hiding buttons of disabled plugins
                $hideButtons = array('space', 'bar', 'linebreak');
                foreach ($this->pluginButton as $pluginId => $buttonList) {
@@ -608,30 +641,23 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                }
                        }
                }
-               
+
                        // Hiding labels of disabled plugins
                foreach ($this->pluginLabel as $pluginId => $label) {
                        if (!$this->isPluginEnabled($pluginId)) {
                                $hideButtons[] = $label;
                        }
                }
-               
+
                        // Hiding buttons
                $show = array_diff($show, $this->conf_toolbar_hide, t3lib_div::trimExplode(',',$this->thisConfig['hideButtons'],1));
-               
+
                        // Apply toolbar constraints from registered plugins
                foreach ($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "applyToolbarConstraints")) {
                                $show = $plugin->applyToolbarConstraints($show);
                        }
                }
-                       // Adding the always show buttons
-               $show = array_unique(array_merge($show, $this->conf_toolbar_show));
-               $toolbarOrder = array_unique(array_merge($toolbarOrder, $this->conf_toolbar_show));
-               foreach ($this->conf_toolbar_show as $buttonId) {
-                       if (!in_array($buttonId, $this->toolbarOrderArray)) $this->toolbarOrderArray[] = $buttonId;
-               }
-               
                        // Getting rid of the buttons for which we have no position
                $show = array_intersect($show, $toolbarOrder);
                $this->toolbar = $show;
@@ -642,16 +668,16 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         *
         */
        function setPlugins() {
-               
+
                        // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
                $hidePlugins = array();
                foreach ($this->pluginButton as $pluginId => $buttonList) {
                        if ($this->registeredPlugins[$pluginId]->addsButtons()) {
-                               $showPlugin = false;
+                               $showPlugin = FALSE;
                                $buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
                                foreach ($buttonArray as $button) {
                                        if (in_array($button, $this->toolbar)) {
-                                               $showPlugin = true;
+                                               $showPlugin = TRUE;
                                        }
                                }
                                if (!$showPlugin) {
@@ -660,7 +686,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        }
                }
                $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
-               
+
                        // Hiding labels of disabled plugins
                $hideLabels = array();
                foreach ($this->pluginLabel as $pluginId => $label) {
@@ -683,128 +709,76 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                $this->pluginEnabledArray[] = $pluginId;
                        }
                }
+               $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
 
-                       // Completing the toolbar converion array for htmlArea
+                       // Completing the toolbar conversion array for htmlArea
                foreach ($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId)) {
                                $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
                        }
                }
        }
-
        /**
         * Convert the TYPO3 names of buttons into the names for htmlArea RTE
-        * 
+        *
         * @param       string  buttonname (typo3-name)
+        *
         * @return      string  buttonname (htmlarea-name)
         */
-
-        function convertToolbarForHTMLArea($button) {
+       function convertToolbarForHTMLArea($button) {
                return $this->convertToolbarForHtmlAreaArray[$button];
-        }
-
+       }
        /**
-        * Return the JS-function for setting the RTE size.
+        * Add RTE main scripts and plugin scripts
         *
-        * @param       string          DivID-Name
-        * @param       int                     the height for the RTE
-        * @param       int                     the width for the RTE
-        * @return string               Loader function in JS
+        * @param string $RTEcounter:  The index number of the current RTE editing area within the form.
+        *
+        * @return void
         */
-       function setRTEsizeByJS($divId, $height, $width) {
-               return '
-                       setRTEsizeByJS(\''.$divId.'\','.$height.', '.$width.');
-               ';
+       protected function addRteJsFiles($RTEcounter) {
+               $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $this->ID . '/htmlarea/htmlarea.js'));
+               foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
+                       $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
+                       $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', "$1".'-'."$2"."$3", $pluginId)) . '.js'));
+               }
        }
-
        /**
-        * Return the HTML code for loading the Javascript files
+        * Return RTE initialization inline JavaScript code
         *
-        * @param       integer         $RTEcounter: The index number of the current RTE editing area within the form.
-        *
-        * @return      string          the html code for loading the Javascript Files
+        * @return string RTE initialization inline JavaScript code
         */
-       function loadJSfiles($RTEcounter) {
-               global $TYPO3_CONF_VARS;
-               
-               $loadJavascriptCode = '
-               <script type="text/javascript">
-               /*<![CDATA[*/
-                       function rteHtmlAreaGetElementsByClassName(className) {
-                               var allElements = document.getElementsByTagName("*");
-                               var result = new Array();
-
-                               for (var i = 0; i < allElements.length; i++) {
-                                       var c = " " + allElements[i].className + " ";
-                                       if (c.indexOf(" " + className + " ") != -1) {
-                                               result[result.length] = allElements[i];
+       protected function getRteInitJsCode() {
+               return '
+                       if (typeof(RTEarea) == "undefined") {
+                               RTEarea = new Object();
+                               RTEarea[0] = new Object();
+                               RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['version'] . '";
+                               RTEarea[0].editorUrl = "' . $this->extHttpPath . 'htmlarea/";
+                               RTEarea[0].editorCSS = "' . t3lib_div::createVersionNumberedFilename($this->editorCSS) . '";
+                               RTEarea[0].editorSkin = "' . dirname($this->editorCSS) . '/";
+                               RTEarea[0].editedContentCSS = "' . t3lib_div::createVersionNumberedFilename($this->editedContentCSS)  . '";
+                               RTEarea[0].hostUrl = "' . $this->hostURL . '";
+                               RTEarea.init = function() {
+                                       if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
+                                               window.setTimeout("RTEarea.init();", 10);
+                                       } else {
+                                               Ext.QuickTips.init();
+                                               HTMLArea.init();
                                        }
-                               }
-                               return result;
-                       }
-
-                       wait_elements = rteHtmlAreaGetElementsByClassName("pleasewait");
-                       wrap_elements = rteHtmlAreaGetElementsByClassName("editorWrap");
-                       for (i = 0; i < wait_elements.length; i++) {
-                               wait_elements[i].style.display = "block";
-                               wrap_elements[i].style.visibility = "hidden";
+                               };
+                               RTEarea.initEditor = function(editorNumber) {
+                                       if (typeof(HTMLArea) == "undefined" || !HTMLArea.isReady) {
+                                               RTEarea.initEditor.defer(40, null, [editorNumber]);
+                                       } else {
+                                               HTMLArea.initEditor(editorNumber);
+                                       }
+                               };
                        }
-                       RTEarea = new Array();
-                       RTEarea[0] = new Object();
-                       RTEarea[0]["version"] = "' . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . '";'
-                       . (($this->client['BROWSER'] == 'msie') ? ('
-                       RTEarea[0]["htmlarea-ie"] = "' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-ie.js', "htmlarea-ie") . '";')
-                       : ('
-                       RTEarea[0]["htmlarea-gecko"] = "' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-gecko.js', "htmlarea-gecko") . '";')) . '
-                       _editor_url = "' . $this->extHttpPath . 'htmlarea";
-                       _editor_lang = "' . $this->language . '";
-                       _editor_CSS = "' . $this->editorCSS . '";
-                       _editor_skin = "' . dirname($this->editorCSS) . '";
-                       _editor_edited_content_CSS = "' .  $this->editedContentCSS  . '";
-                       _typo3_host_url = "' . $this->hostURL . '";
-                       _editor_debug_mode = ' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableDebugMode'] ? 'true' : 'false') . ';
-                       _editor_compressed_scripts = ' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] ? 'true' : 'false') . ';'
-                       . (($this->client['BROWSER'] == 'gecko') ? ('
-                       _editor_mozAllowClipboard_url = "' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['mozAllowClipboardURL'] ? $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['mozAllowClipboardURL'] : '') . '";')
-                       : '') . '
-               /*]]>*/
-               </script>';
-               $loadJavascriptCode .= '
-               <script type="text/javascript" src="' . $this->buildJSMainLangFile($RTEcounter) . '"></script>
-               <script type="text/javascript" src="' . $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea.js', "htmlarea") . '"></script>
-               ';
-               return $loadJavascriptCode;
-       }
-       
-       /**
-        * Return the inline Javascript code for initializing the RTE
-        *
-        * @param       integer         $RTEcounter: The index number of the current RTE editing area within the form.
-        *
-        * @return      string          the inline Javascript code for initializing the RTE
-        */
-        
-       function loadJScode($RTEcounter) {
-               global $TYPO3_CONF_VARS;
-               
-               $loadPluginCode = '';
-               foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
-                       $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
-                       $loadPluginCode .= '
-                       HTMLArea.loadPlugin("' . $pluginId . '", "' . $this->writeTemporaryFile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', "$1".'-'."$2"."$3", $pluginId)) . '.js', $pluginId) . '", '. ($this->registeredPlugins[$pluginId]->requiresSynchronousLoad()?'false':'true'). ');';
-               }
-               return (!$this->is_FE() ? '' : '
-               ' . '/*<![CDATA[*/') . ($this->is_FE() ? '' : '
-                       RTEarea[0]["RTEtsConfigParams"] = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";')
-                       . $loadPluginCode .  '
-                       HTMLArea.init();' . (!$this->is_FE() ? '' : '
-               /*]]>*/
-               ');
+                       RTEarea.init();';
        }
-       
        /**
         * Return the Javascript code for configuring the RTE
-        * 
+        *
         * @param       integer         $RTEcounter: The index number of the current RTE editing area within the form.
         * @param       string          $table: The table that includes this RTE (optional, necessary for IRRE).
         * @param       string          $uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
@@ -813,39 +787,57 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         * @return      string          the Javascript code for configuring the RTE
         */
        function registerRTEinJS($RTEcounter, $table='', $uid='', $field='', $textAreaId = '') {
-               global $TYPO3_CONF_VARS;
-               
-               $configureRTEInJavascriptString = (!$this->is_FE() ? '' : '
-                       ' . '/*<![CDATA[*/') . '
-                       editornumber = RTEarea.length;
-                       document.getElementById("pleasewait' . $textAreaId . '").id = "pleasewait" + editornumber;
-                       document.getElementById("editorWrap' . $textAreaId . '").id = "editorWrap" + editornumber;
-                       document.getElementById("RTEarea' . $textAreaId . '").id = "RTEarea" + editornumber;
+               $configureRTEInJavascriptString = '
+                       if (typeof(configureEditorInstance) == "undefined") {
+                               configureEditorInstance = new Object();
+                       }
+                       configureEditorInstance["' . $textAreaId . '"] = function() {
+                               if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
+                                       window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
+                               } else {
+                       editornumber = "' . $textAreaId . '";
                        RTEarea[editornumber] = new Object();
                        RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
                        RTEarea[editornumber].number = editornumber;
                        RTEarea[editornumber].deleted = false;
                        RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
                        RTEarea[editornumber].id = "RTEarea" + editornumber;
+                       RTEarea[editornumber].RTEWidthOverride = "' . ((is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteWidth']) && trim($GLOBALS['BE_USER']->uc['rteWidth'])) ? trim($GLOBALS['BE_USER']->uc['rteWidth']) : trim($this->thisConfig['RTEWidthOverride'])) . '";
+                       RTEarea[editornumber].RTEHeightOverride = "' . ((is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && intval($GLOBALS['BE_USER']->uc['rteHeight'])) ? intval($GLOBALS['BE_USER']->uc['rteHeight']) : intval($this->thisConfig['RTEHeightOverride'])) . '";
+                       RTEarea[editornumber].resizable = ' . ((is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteResize']) && $GLOBALS['BE_USER']->uc['rteResize']) ? 'true' : (trim($this->thisConfig['rteResize']) ? 'true' : 'false')) . ';
+                       RTEarea[editornumber].maxHeight = "' . ((is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteMaxHeight']) && intval($GLOBALS['BE_USER']->uc['rteMaxHeight'])) ? trim($GLOBALS['BE_USER']->uc['rteMaxHeight']) : (intval($this->thisConfig['rteMaxHeight']) ? intval($this->thisConfig['rteMaxHeight']) : '2000')) . '";
+                       RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
+                       RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar'])?'true':'false') . ';
                        RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean'])?'true':'false') . ';
-                       RTEarea[editornumber]["htmlRemoveComments"] = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . ';
+                       RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . ';
                        RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . ';
                        RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing'])?'true':'false') . ';
-                       RTEarea[editornumber]["removeTrailingBR"] = ' . (trim($this->thisConfig['removeTrailingBR'])?'true':'false') . ';
-                       RTEarea[editornumber]["useCSS"] = ' . (trim($this->thisConfig['useCSS'])?'true':'false') . ';
-                       RTEarea[editornumber]["keepButtonGroupTogether"] = ' . (trim($this->thisConfig['keepButtonGroupTogether'])?'true':'false') . ';
-                       RTEarea[editornumber]["disablePCexamples"] = ' . (trim($this->thisConfig['disablePCexamples'])?'true':'false') . ';
-                       RTEarea[editornumber]["statusBar"] = ' . (trim($this->thisConfig['showStatusBar'])?'true':'false') . ';
-                       RTEarea[editornumber]["showTagFreeClasses"] = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
-                       RTEarea[editornumber]["useHTTPS"] = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
-                       RTEarea[editornumber]["enableMozillaExtension"] = ' . (($this->client['BROWSER'] == 'gecko' && $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableMozillaExtension'])?'true':'false') . ';
-                       RTEarea[editornumber]["tceformsNested"] = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(true) : '[]') . ';
-                       RTEarea[editornumber].dialogueWindows = new Object();
-                       RTEarea[editornumber].dialogueWindows.defaultPositionFromTop = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) : '100') . ';
-                       RTEarea[editornumber].dialogueWindows.defaultPositionFromLeft = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) : '100') . ';
-                       RTEarea[editornumber].dialogueWindows.doNotResize = ' . (trim($this->thisConfig['dialogueWindows.']['doNotResize'])?'true':'false') . ';
-                       RTEarea[editornumber].dialogueWindows.doNotCenter = ' . (trim($this->thisConfig['dialogueWindows.']['doNotCenter'])?'true':'false') . ';';
-
+                       RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR'])?'true':'false') . ';
+                       RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS'])?'true':'false') . ';
+                       RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether'])?'true':'false') . ';
+                       RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples'])?'true':'false') . ';
+                       RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
+                       RTEarea[editornumber].useHTTPS = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
+                       RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(TRUE) : '[]') . ';
+                       RTEarea[editornumber].dialogueWindows = new Object();';
+                       // The following property is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8
+               if (isset($this->thisConfig['showTagFreeClasses'])) {
+                       $this->logDeprecatedProperty('showTagFreeClasses', 'buttons.blockstyle.showTagFreeClasses', '4.8');
+                       $this->logDeprecatedProperty('showTagFreeClasses', 'buttons.textstyle.showTagFreeClasses', '4.8');
+               }
+                       // The following property is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8
+               if (isset($this->thisConfig['disablePCexamples'])) {
+                       $this->logDeprecatedProperty('disablePCexamples', 'buttons.blockstyle.disableStyleOnOptionLabel', '4.8');
+                       $this->logDeprecatedProperty('disablePCexamples', 'buttons.textstyle.disableStyleOnOptionLabel', '4.8');
+               }
+               if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])) {
+                       $configureRTEInJavascriptString .= '
+                       RTEarea[editornumber].dialogueWindows.positionFromTop = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) . ';';
+               }
+               if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])) {
+                       $configureRTEInJavascriptString .= '
+                       RTEarea[editornumber].dialogueWindows.positionFromLeft = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) . ';';
+               }
                        // The following properties apply only to the backend
                if (!$this->is_FE()) {
                        $configureRTEInJavascriptString .= '
@@ -854,7 +846,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                        RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
                        RTEarea[editornumber].userUid = "' . $this->userUid . '";';
                }
-               
+
                        // Setting the plugin flags
                $configureRTEInJavascriptString .= '
                        RTEarea[editornumber].plugin = new Object();
@@ -870,43 +862,49 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                }
                        }
                }
-               
+
                        // Setting the buttons configuration
                $configureRTEInJavascriptString .= '
                        RTEarea[editornumber].buttons = new Object();';
                if (is_array($this->thisConfig['buttons.'])) {
                        foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
                                $button = substr($buttonIndex, 0, -1);
-                               if (in_array($button,$this->toolbar)) {
+                               if (is_array($conf)) {
                                        $configureRTEInJavascriptString .= '
                        RTEarea[editornumber].buttons.'.$button.' = ' . $this->buildNestedJSArray($conf) . ';';
                                }
                        }
                }
-               
+
                        // Setting the list of tags to be removed if specified in the RTE config
                if (trim($this->thisConfig['removeTags']))  {
                        $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber]["htmlRemoveTags"] = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
+                       RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
                }
-               
+
                        // Setting the list of tags to be removed with their contents if specified in the RTE config
-               if (trim($this->thisConfig['removeTagsAndContents']))  {
+               if (trim($this->thisConfig['removeTagsAndContents'])) {
                        $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber]["htmlRemoveTagsAndContents"] = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
+                       RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
+               }
+                       // Setting array of custom tags if specified in the RTE config
+               if (!empty($this->thisConfig['customTags'])) {
+                       $customTags = t3lib_div::trimExplode(',', $this->thisConfig['customTags'], 1);
+                       if (!empty($customTags)) {
+                               $configureRTEInJavascriptString .= '
+                               RTEarea[editornumber].customTags= ' . json_encode($customTags) . ';';
+                       }
                }
-               
                        // Process default style configuration
+                       // This default configuration is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8.
+                       // Use contentCSS instead.
                $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber].defaultPageStyle = "' . $this->hostURL . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
-                       
+                       RTEarea[editornumber].defaultPageStyle = "' . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
                        // Setting the pageStyle
-               $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
                $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber].pageStyle = "' . $this->getFullFileName($filename) .'";';
-               
+                       RTEarea[editornumber].pageStyle = "' . t3lib_div::createVersionNumberedFilename($this->getContentCssFileName()) .'";';
                        // Process classes configuration
-               $classesConfigurationRequired = false;
+               $classesConfigurationRequired = FALSE;
                foreach ($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId)) {
                                $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
@@ -915,44 +913,59 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                if ($classesConfigurationRequired) {
                        $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
                }
-               
                        // Add Javascript configuration for registered plugins
                foreach ($this->registeredPlugins as $pluginId => $plugin) {
                        if ($this->isPluginEnabled($pluginId)) {
                                $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
                        }
                }
-               
+                       // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
                $configureRTEInJavascriptString .= '
                        RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
-                       RTEarea[editornumber].convertButtonId = ' . t3lib_div::array2json(array_flip($this->convertToolbarForHtmlAreaArray)) .';
-                       HTMLArea.initEditor(editornumber);' . (!$this->is_FE() ? '' : '
-                       /*]]>*/');
+                       RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
+                       RTEarea.initEditor(editornumber);
+                               }
+                       };
+                       configureEditorInstance["' . $textAreaId . '"]();';
                return $configureRTEInJavascriptString;
        }
 
        /**
-        * Return true, if the plugin can be loaded
+        * Return TRUE, if the plugin can be loaded
         *
         * @param       string          $pluginId: The identification string of the plugin
         *
-        * @return      boolean         true if the plugin can be loaded
+        * @return      boolean         TRUE if the plugin can be loaded
         */
-       
-       function isPluginEnabled($pluginId) { 
+
+       function isPluginEnabled($pluginId) {
                return in_array($pluginId, $this->pluginEnabledArray);
        }
-       
+
        /**
         * Build the default content style sheet
         *
         * @return string               Style sheet
+        * @deprecated since TYPO3 4.8, will be removed in TYPO3 4.10
         */
        function buildStyleSheet() {
-               
+                       // This function will be DEPRECATED as of TYPO3 4.8 and will be removed in TYPO3 4.10
+               //t3lib_div::logDeprecatedFunction();
+                       // These PageTSConfig properties are DEPRECATED as of TYPO3 4.6 and will be removed in TYPO3 4.8
+               $properties = array('mainStyle_font', 'mainStyle_size', 'mainStyle_color', 'mainStyle_bgcolor', 'mainStyleOverride');
+               foreach ($properties as $property) {
+                       if (isset($this->thisConfig[$property])) {
+                               $this->logDeprecatedProperty($property, 'contentCSS', '4.8');
+                       }
+               }
+               if (is_array($this->thisConfig['mainStyleOverride_add.'])) {
+                       $this->logDeprecatedProperty('mainStyleOverride_add', 'contentCSS', '4.8');
+               }
+               if (is_array($this->thisConfig['inlineStyle.']))        {
+                       $this->logDeprecatedProperty('inlineStyle', 'contentCSS', '4.8');
+               }
                if (!trim($this->thisConfig['ignoreMainStyleOverride'])) {
                        $mainStyle_font = $this->thisConfig['mainStyle_font'] ? $this->thisConfig['mainStyle_font']: 'Verdana,sans-serif';
-                       
                        $mainElements = array();
                        $mainElements['P'] = $this->thisConfig['mainStyleOverride_add.']['P'];
                        $elList = explode(',','H1,H2,H3,H4,H5,H6,PRE');
@@ -961,35 +974,35 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                        $mainElements[$elListName] = $this->thisConfig['mainStyleOverride_add.'][$elListName];
                                }
                        }
-                       
+
                        $addElementCode = '';
                        foreach ($mainElements as $elListName => $elValue) {
-                               $addElementCode .= strToLower($elListName) . ' {' . $elValue . '}' . chr(10);
+                               $addElementCode .= strToLower($elListName) . ' {' . $elValue . '}' . LF;
                        }
-                       
-                       $stylesheet = $this->thisConfig['mainStyleOverride'] ? $this->thisConfig['mainStyleOverride'] : chr(10) .
+
+                       $stylesheet = $this->thisConfig['mainStyleOverride'] ? $this->thisConfig['mainStyleOverride'] : LF .
                                'body.htmlarea-content-body { font-family: ' . $mainStyle_font .
                                        '; font-size: '.($this->thisConfig['mainStyle_size'] ? $this->thisConfig['mainStyle_size'] : '12px') .
                                        '; color: '.($this->thisConfig['mainStyle_color']?$this->thisConfig['mainStyle_color'] : 'black') .
                                        '; background-color: '.($this->thisConfig['mainStyle_bgcolor'] ? $this->thisConfig['mainStyle_bgcolor'] : 'white') .
-                                       ';'.$this->thisConfig['mainStyleOverride_add.']['BODY'].'}' . chr(10) .
-                               'td { ' . $this->thisConfig['mainStyleOverride_add.']['TD'].'}' . chr(10) .
-                               'div { ' . $this->thisConfig['mainStyleOverride_add.']['DIV'].'}' . chr(10) .
-                               'pre { ' . $this->thisConfig['mainStyleOverride_add.']['PRE'].'}' . chr(10) .
-                               'ol { ' . $this->thisConfig['mainStyleOverride_add.']['OL'].'}' . chr(10) .
-                               'ul { ' . $this->thisConfig['mainStyleOverride_add.']['UL'].'}' . chr(10) .
-                               'blockquote { ' . $this->thisConfig['mainStyleOverride_add.']['BLOCKQUOTE'].'}' . chr(10) .
+                                       ';'.$this->thisConfig['mainStyleOverride_add.']['BODY'].'}' . LF .
+                               'td { ' . $this->thisConfig['mainStyleOverride_add.']['TD'].'}' . LF .
+                               'div { ' . $this->thisConfig['mainStyleOverride_add.']['DIV'].'}' . LF .
+                               'pre { ' . $this->thisConfig['mainStyleOverride_add.']['PRE'].'}' . LF .
+                               'ol { ' . $this->thisConfig['mainStyleOverride_add.']['OL'].'}' . LF .
+                               'ul { ' . $this->thisConfig['mainStyleOverride_add.']['UL'].'}' . LF .
+                               'blockquote { ' . $this->thisConfig['mainStyleOverride_add.']['BLOCKQUOTE'].'}' . LF .
                                $addElementCode;
-       
+
                        if (is_array($this->thisConfig['inlineStyle.']))        {
-                               $stylesheet .= chr(10) . implode(chr(10), $this->thisConfig['inlineStyle.']) . chr(10);
+                               $stylesheet .= LF . implode(LF, $this->thisConfig['inlineStyle.']) . LF;
                        }
                } else {
                        $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
                }
                return $stylesheet;
        }
-       
+
        /**
         * Return Javascript configuration of classes
         *
@@ -999,200 +1012,109 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         */
        function buildJSClassesConfig($RTEcounter) {
                        // Build JS array of lists of classes
+                       // These PageTSConfig properties are DEPRECATED as of TYPO3 4.6 and will be removed in TYPO3 4.8
                $classesTagList = 'classesCharacter, classesParagraph, classesImage, classesTable, classesLinks, classesTD';
-               $classesTagConvert = array( 'classesCharacter' => 'span', 'classesParagraph' => 'div', 'classesImage' => 'img', 'classesTable' => 'table', 'classesLinks' => 'a', 'classesTD' => 'td');
+               $classesTagConvert = array('classesCharacter' => 'span', 'classesParagraph' => 'div', 'classesImage' => 'img', 'classesTable' => 'table', 'classesLinks' => 'a', 'classesTD' => 'td');
+               $classesUseInstead = array('classesCharacter' => 'buttons.textstyle.tags.span.allowedClasses', 'classesParagraph' => 'buttons.blockstyle.tags.div.allowedClasses', 'classesImage' => 'buttons.image.properties.class.allowedClasses', 'classesTable' => 'buttons.blockstyle.tags.table.allowedClasses', 'classesLinks' => 'buttons.link.properties.class.allowedClasses', 'classesTD' => 'buttons.blockstyle.tags.td.allowedClasses');
                $classesTagArray = t3lib_div::trimExplode(',' , $classesTagList);
                $configureRTEInJavascriptString = '
-                       RTEarea[editornumber]["classesTag"] = new Object();';
+                       RTEarea[editornumber].classesTag = new Object();';
                foreach ($classesTagArray as $classesTagName) {
-                       $HTMLAreaJSClasses = ($this->thisConfig[$classesTagName])?('"' . $this->cleanList($this->thisConfig[$classesTagName]) . '";'):'null;';
+                       $HTMLAreaJSClasses = $this->thisConfig[$classesTagName] ? ('"' . $this->cleanList($this->thisConfig[$classesTagName]) . '";') : 'null;';
                        $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber]["classesTag"]["'. $classesTagConvert[$classesTagName] .'"] = '. $HTMLAreaJSClasses;
+                       RTEarea[editornumber].classesTag.'. $classesTagConvert[$classesTagName] .' = '. $HTMLAreaJSClasses;
+                       if (isset($this->thisConfig[$classesTagName])) {
+                               $this->logDeprecatedProperty($classesTagName, $classesUseInstead[$classesTagName], '4.8');
+                       }
                }
-               
                        // Include JS arrays of configured classes
                $configureRTEInJavascriptString .= '
-                       RTEarea[editornumber]["classesUrl"] = "' . $this->hostURL . $this->writeTemporaryFile('', 'classes_'.$LANG->lang, 'js', $this->buildJSClassesArray()) . '";';
-               
+                       RTEarea[editornumber].classesUrl = "' . (($this->is_FE() && $GLOBALS['TSFE']->absRefPrefix) ? $GLOBALS['TSFE']->absRefPrefix : '') . $this->writeTemporaryFile('', 'classes_' . $this->language, 'js', $this->buildJSClassesArray(), TRUE) . '";';
                return $configureRTEInJavascriptString;
        }
-       
+
        /**
-        * Return JS arrays of classes labels and noShow flags
+        * Return JS arrays of classes configuration
         *
-        * @return string               JS classes arrays
+        * @return string       JS classes arrays
         */
        function buildJSClassesArray() {
-               global $TSFE, $LANG, $TYPO3_CONF_VARS;
-               
                if ($this->is_FE()) {
                        $RTEProperties = $this->RTEsetup;
                } else {
                        $RTEProperties = $this->RTEsetup['properties'];
                }
-               
-               $linebreak = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : chr(10);
-               $index = 0;
-               $indexNoShow = 0;
-               $indexAlternating = 0;
-               $indexCounting = 0;
-               $JSClassesLabelsArray = 'HTMLArea.classesLabels = { ' . $linebreak;
-               $JSClassesValuesArray = 'HTMLArea.classesValues = { ' . $linebreak;
-               $JSClassesNoShowArray = 'HTMLArea.classesNoShow = { ' . $linebreak;
-               $JSClassesAlternatingArray = 'HTMLArea.classesAlternating = { ' . $linebreak;
-               $JSClassesCountingArray = 'HTMLArea.classesCounting = { ' . $linebreak;
-               $JSClassesXORArray = 'HTMLArea.classesXOR = { ' . $linebreak;
-               
+               $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
+               $JSClassesArray = '';
                        // Scanning the list of classes if specified in the RTE config
-               if (is_array($RTEProperties['classes.']))  {
+               if (is_array($RTEProperties['classes.'])) {
                        foreach ($RTEProperties['classes.'] as $className => $conf) {
-                               $className = substr($className,0,-1);
-                               $classLabel = $this->getPageConfigLabel($conf['name']);
-                               $JSClassesLabelsArray .= ($index?',':'') . '"' . $className . '": ' . $classLabel . $linebreak;
-                               $JSClassesValuesArray .= ($index?',':'') . '"' . $className . '":"' . str_replace('"', '\"', str_replace('\\\'', '\'', $conf['value'])) . '"' . $linebreak;
-                               if ($conf['noShow']) {
-                                       $JSClassesNoShowArray .= ($indexNoShow?',':'') . '"' . $className . '":' . ($conf['noShow']?'true':'false') . $linebreak;
-                                       $indexNoShow++;
+                               $className = rtrim($className, '.');
+                               $classesArray['labels'][$className] = $this->getPageConfigLabel($conf['name'], FALSE);
+                               $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
+                               if (isset($conf['noShow'])) {
+                                       $classesArray['noShow'][$className] = $conf['noShow'];
                                }
                                if (is_array($conf['alternating.'])) {
-                                       $JSClassesAlternatingArray .= ($indexAlternating?',':'') . '"' . $className . '":' . (is_array($conf['alternating.']) ? $this->buildNestedJSArray($conf['alternating.']) : ' "false"') . $linebreak;
-                                       $indexAlternating++;
+                                       $classesArray['alternating'][$className] = $conf['alternating.'];
                                }
                                if (is_array($conf['counting.'])) {
-                                       $JSClassesCountingArray .= ($indexCounting?',':'') . '"' . $className . '":' . (is_array($conf['counting.']) ? $this->buildNestedJSArray($conf['counting.']) : ' "false"') . $linebreak;
-                                       $indexCounting++;
+                                       $classesArray['counting'][$className] = $conf['counting.'];
                                }
-                               $index++;
                        }
                }
                        // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
-               $index = 0;
-               if (is_array($RTEProperties['mutuallyExclusiveClasses.']))  {
+               if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
                        foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
-                               $classArray = t3lib_div::trimExplode(',', $conf, 1);
-                               $classList = implode(',', $classArray);
-                               foreach ($classArray as $className) {
-                                       $JSClassesXORArray .= ($index?',':'') . '"' . $className . '": /^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $classList), 1)) . ')$/i' . $linebreak;
-                                       $index++;
+                               $classSet = t3lib_div::trimExplode(',', $conf, 1);
+                               $classList = implode(',', $classSet);
+                               foreach ($classSet as $className) {
+                                       $classesArray['XOR'][$className] = '/^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $classList), 1)) . ')$/';
                                }
                        }
                }
-               $JSClassesLabelsArray .= '};' . $linebreak;
-               $JSClassesValuesArray .= '};' . $linebreak;
-               $JSClassesNoShowArray .= '};' . $linebreak;
-               $JSClassesAlternatingArray .= '};' . $linebreak;
-               $JSClassesCountingArray .= '};' . $linebreak;
-               $JSClassesXORArray .= '};' . $linebreak;
-               
-               return $JSClassesLabelsArray . $JSClassesValuesArray . $JSClassesNoShowArray . $JSClassesAlternatingArray . $JSClassesCountingArray . $JSClassesXORArray;
+               foreach ($classesArray as $key => $subArray) {
+                       $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
+               }
+               return $JSClassesArray;
        }
-       
+
        /**
         * Translate Page TS Config array in JS nested array definition
+        * Replace 0 values with false
+        * Unquote regular expression values
+        * Replace empty arrays with empty objects
         *
         * @param       array           $conf: Page TSConfig configuration array
         *
         * @return      string          nested JS array definition
         */
        function buildNestedJSArray($conf) {
-               $configureRTEInJavascriptString = '{';
-               $index = 0;
-               if (is_array($conf)) {
-                       foreach ($conf as $propertyName => $conf1) {
-                               $property = $propertyName;
-                               if ($index) {
-                                       $configureRTEInJavascriptString .= ', ';
-                               }
-                               if (is_array($conf1)) {
-                                       $property = substr($property, 0, -1);
-                                       $indexProperty = 0;
-                                       $configureRTEInJavascriptString .= '"'.$property.'" : {';
-                                       foreach ($conf1 as $property1Name => $conf2) {
-                                               $property1 = $property1Name;
-                                               if ($indexProperty) {
-                                                       $configureRTEInJavascriptString .= ', ';
-                                               }
-                                               if (is_array($conf2)) {
-                                                       $property1 = substr($property1, 0, -1);
-                                                       $indexProperty1 = 0;
-                                                       $configureRTEInJavascriptString .= '"'.$property1.'" : {';
-                                                       foreach ($conf2 as $property2Name => $conf3) {
-                                                               $property2 = $property2Name;
-                                                               if ($indexProperty1) {
-                                                                       $configureRTEInJavascriptString .= ', ';
-                                                               }
-                                                               if (is_array($conf3)) {
-                                                                       $property2 = substr($property2, 0, -1);
-                                                                       $indexProperty2 = 0;
-                                                                       $configureRTEInJavascriptString .= '"'.$property2.'" : {';
-                                                                       foreach($conf3 as $property3Name => $conf4) {
-                                                                               $property3 = $property3Name;
-                                                                               if ($indexProperty2) {
-                                                                                       $configureRTEInJavascriptString .= ', ';
-                                                                               }
-                                                                               if (!is_array($conf4)) {
-                                                                                       $configureRTEInJavascriptString .= '"'.$property3.'" : '.($conf4?'"'.$conf4.'"':'false');
-                                                                               }
-                                                                               $indexProperty2++;
-                                                                       }
-                                                                       $configureRTEInJavascriptString .= '}';
-                                                               } else {
-                                                                       $configureRTEInJavascriptString .= '"'.$property2.'" : '.($conf3?'"'.$conf3.'"':'false');                                                                                               
-                                                               }
-                                                               $indexProperty1++;
-                                                       }
-                                                       $configureRTEInJavascriptString .= '}';
-                                               } else {
-                                                       $configureRTEInJavascriptString .= '"'.$property1.'" : '.($conf2?'"'.$conf2.'"':'false');
-                                               }
-                                               $indexProperty++;
-                                       }
-                                       $configureRTEInJavascriptString .= '}';
-                               } else {
-                                       $configureRTEInJavascriptString .= '"'.$property.'" : '.($conf1?'"'.$conf1.'"':'false');
-                               }
-                               $index++;
-                       }
-               }
-               $configureRTEInJavascriptString .= '}';
-               return $configureRTEInJavascriptString;
+               $convertedConf = t3lib_div::removeDotsFromTS($conf);
+               return str_replace(array(':"0"', ':"\/^(', ')$\/i"', ':"\/^(', ')$\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode($convertedConf));
        }
-       
+
        /**
         * Return a Javascript localization array for htmlArea RTE
         *
         * @return      string          Javascript localization array
         */
        function buildJSMainLangArray() {
-               global $TSFE, $LANG, $TYPO3_CONF_VARS;
-               
-               $linebreak = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : chr(10);
-               $JSLanguageArray .= 'var HTMLArea_langArray = new Object();' . $linebreak;
-               $JSLanguageArray .= 'HTMLArea_langArray = { ' . $linebreak;
-               $subArrays = array( 'tooltips', 'msg' , 'dialogs');
-               $subArraysIndex = 0;
-               foreach ($subArrays as $labels) {
-                       $JSLanguageArray .= (($subArraysIndex++)?',':'') . $labels . ': {' . $linebreak;
-                       if ($this->is_FE()) {
-                               $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, $this->OutputCharset);
-                       } else {
-                               $LOCAL_LANG = $LANG->readLLfile(t3lib_extMgm::extPath($this->ID).'htmlarea/locallang_' . $labels . '.xml');
-                       }
+               $JSLanguageArray = 'HTMLArea.I18N = new Object();' . LF;
+               $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
+               foreach ($labelsArray as $labels => $subArray) {
+                       $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, 'utf-8');
                        if (!empty($LOCAL_LANG[$this->language])) {
-                               $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language]);
+                               $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language], FALSE, FALSE);
                        } else {
                                $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
                        }
-                       $index = 0;
-                       foreach ($LOCAL_LANG[$this->language] as $labelKey => $labelValue ) {
-                               $JSLanguageArray .=  (($index++)?',':'') . '"' . $labelKey . '":"' . str_replace('"', '\"', $labelValue) . '"' . $linebreak;
-                       }
-                       $JSLanguageArray .= ' }' . chr(10);
+                       $labelsArray[$labels] = $LOCAL_LANG[$this->language];
                }
-               $JSLanguageArray .= ' };' . chr(10);
+               $JSLanguageArray .= 'HTMLArea.I18N = ' . json_encode($labelsArray) . ';' . LF;
                return $JSLanguageArray;
        }
-       
+
        /**
         * Writes contents in a file in typo3temp/rtehtmlarea directory and returns the file name
         *
@@ -1203,9 +1125,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         *
         * @return      string          The name of the file writtten to typo3temp/rtehtmlarea
         */
-       public function writeTemporaryFile($sourceFileName='', $label, $fileExtension='js', $contents='') {
-               global $TYPO3_CONF_VARS;
-               
+       public function writeTemporaryFile($sourceFileName='', $label, $fileExtension='js', $contents='', $concatenate = FALSE) {
                if ($sourceFileName) {
                        $output = '';
                        $source = t3lib_div::getFileAbsFileName($sourceFileName);
@@ -1213,22 +1133,25 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                } else {
                        $output = $contents;
                }
-               $compress = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] && ($fileExtension == 'js') && ($output != '');
-               $relativeFilename = 'typo3temp/' . $this->ID . '/' . str_replace('-','_',$label) . '_' . t3lib_div::shortMD5(($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName?$sourceFileName:$output)), 20) . ($compress ? '_compressed' : '') . '.' . $fileExtension;
+               $relativeFilename = 'typo3temp/' . $this->ID . '_' . str_replace('-','_',$label) . '_' . t3lib_div::shortMD5((TYPO3_version . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName ? $sourceFileName : $output)), 20) . '.' . $fileExtension;
                $destination = PATH_site . $relativeFilename;
-               if(!file_exists($destination)) {
-                       $compressedJavaScript = '';
-                       if ($compress) {
-                               $compressedJavaScript = t3lib_div::minifyJavaScript($output);
+               if (!file_exists($destination)) {
+                       $minifiedJavaScript = '';
+                       if ($fileExtension == 'js' && $output != '') {
+                               $minifiedJavaScript = t3lib_div::minifyJavaScript($output);
                        }
-                       $failure = t3lib_div::writeFileToTypo3tempDir($destination, $compressedJavaScript?$compressedJavaScript:$output);
+                       $failure = t3lib_div::writeFileToTypo3tempDir($destination, $minifiedJavaScript ? $minifiedJavaScript : $output);
                        if ($failure)  {
-                               die($failure);
+                               throw new RuntimeException($failure, 1294585668);
                        }
                }
-               return ($this->thisConfig['forceHTTPS']?$this->siteURL:$this->httpTypo3Path) . $relativeFilename;
+               if ($this->is_FE()) {
+                       $filename = $relativeFilename;
+               } else {
+                       $filename = ($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename;
+               }
+               return t3lib_div::resolveBackPath($filename);
        }
-       
        /**
         * Return a file name containing the main JS language array for HTMLArea
         *
@@ -1236,13 +1159,12 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         *
         * @return      string          filename
         */
-        
-       function buildJSMainLangFile($RTEcounter) { 
-               $contents = $this->buildJSMainLangArray() . chr(10);
+       function buildJSMainLangFile($RTEcounter) {
+               $contents = $this->buildJSMainLangArray() . LF;
                foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
-                       $contents .= $this->buildJSLangArray($pluginId) . chr(10);
+                       $contents .= $this->buildJSLangArray($pluginId) . LF;
                }
-               return $this->writeTemporaryFile('', $this->language.'_'.$this->OutputCharset, 'js', $contents);
+               return $this->writeTemporaryFile('', $this->language.'_'.$this->OutputCharset, 'js', $contents, TRUE);
        }
 
        /**
@@ -1252,117 +1174,104 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         *
         * @return      string          Javascript localization array
         */
-        
        function buildJSLangArray($plugin) {
-               global $LANG, $TYPO3_CONF_VARS;
-
+               $LOCAL_LANG = FALSE;
                $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
-
-               $linebreak = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : chr(10);
-               if($this->is_FE()) {
-                       $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml', $this->language, $this->OutputCharset);
-               } else {
-                       $LOCAL_LANG = $LANG->readLLfile(t3lib_extMgm::extPath($extensionKey).'htmlarea/plugins/' . $plugin . '/locallang.xml');
-               }
-
-               if (!empty($LOCAL_LANG[$this->language])) {
-                       $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'],$LOCAL_LANG[$this->language]);
-               } else {
-                       $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
-               }
-       
-               $JSLanguageArray .= 'var ' . $plugin . '_langArray = new Object();' . $linebreak;
-               $JSLanguageArray .= $plugin . '_langArray = {' . $linebreak;
-               $index = 0;
-               foreach ($LOCAL_LANG[$this->language] as $labelKey => $labelValue ) {
-                       $JSLanguageArray .=  (($index++)?',':'') . '"' . $labelKey . '":"' . str_replace('"', '\"', $labelValue) . '"' . $linebreak;
+               $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml', $this->language, 'utf-8', 1);
+               $JSLanguageArray = 'HTMLArea.I18N["' . $plugin . '"] = new Object();' . LF;
+               if (is_array($LOCAL_LANG)) {
+                       if (!empty($LOCAL_LANG[$this->language])) {
+                               $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language], FALSE, FALSE);
+                       } else {
+                               $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
+                       }
+                       $JSLanguageArray .= 'HTMLArea.I18N["' . $plugin . '"] = ' . json_encode($LOCAL_LANG[$this->language]) . ';'. LF;
                }
-               $JSLanguageArray .= ' };' . chr(10);
-               
                return $JSLanguageArray;
        }
 
        /**
-        * Return the JS-Code for the Toolbar-Config-Array for HTML-Area
+        * Return the JS code of the toolbar configuration for the HTMLArea editor
         *
-        * @return string               the JS-Code as an JS-Array
+        * @return string       the JS code as nested JS arrays
         */
-
-       function getJSToolbarArray() {
-               $toolbar = '';                  // The JS-Code for the toolbar
-               $group = '';                    // The TS-Code for the group in the moment, each group are between "bar"s
-               $group_has_button = false;      // True if the group has any enabled buttons
-               $group_needs_starting_bar = false;
-               $previous_is_space = false;
-
-                       // process each button in the order list
-               foreach ($this->toolbarOrderArray as $button) {
-                       // check if a new group starts
-                       if (($button == 'bar' || $button == 'linebreak') && $group_has_button) {
-                                       // New line
-                               if ($button == 'linebreak') {
-                                       $convertButton = '"' . $this->convertToolbarForHTMLArea('linebreak') . '"';
-                                       $group = ($group!='') ? ($group . ', ' . $convertButton) : $convertButton;
-                               }
-                                       // New group
-                               $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group);
-                               $group = '';
-                               $previous_is_space = false;
-                               $group_has_button = false;
-                               $group_needs_starting_bar = true;
-                       } elseif ($toolbar && $button == 'linebreak' && !$group_has_button) {
-                                       // Insert linebreak if no group is opened
-                               $group = '';
-                               $previous_is_space = false;
-                               $group_needs_starting_bar = false;
-                               $toolbar .= ', "' . $this->convertToolbarForHTMLArea($button) . '"';
-                       } elseif ($button == 'bar' && !$group_has_button) {
-                               $group_needs_starting_bar = true;
-                       } elseif ($button == 'space' && $group_has_button && !$previous_is_space) {
-                               $convertButton = $this->convertToolbarForHTMLArea($button);
-                               $convertButton = '"' . $convertButton . '"';
-                               $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton);
-                               $group_needs_starting_bar = false;
-                               $previous_is_space = true;
-                       } elseif (in_array($button, $this->toolbar)) {
-                                       // Add the button to the group
-                               $convertButton = $this->convertToolbarForHTMLArea($button);
-                               if ($convertButton) {
-                                       $convertButton = '"' . $convertButton . '"';
-                                       $group .= $group ? (', ' . $convertButton) : ($group_needs_starting_bar ? ('"' . $this->convertToolbarForHTMLArea('bar') . '", ' . $convertButton) : $convertButton);
-                                       $group_has_button = true;
-                                       $group_needs_starting_bar = false;
-                                       $previous_is_space = false;
-                               }
+       protected function getJSToolbarArray() {
+                       // The toolbar array
+               $toolbar = array();
+                       // The current row;  a "linebreak" ends the current row
+               $row = array();
+                       // The current group; each group is between "bar"s; a "linebreak" ends the current group
+               $group = array();
+                       // Process each toolbar item in the toolbar order list
+               foreach ($this->toolbarOrderArray as $item) {
+                       switch ($item) {
+                               case 'linebreak':
+                                               // Add row to toolbar if not empty
+                                       if (!empty($group)) {
+                                               $row[] = $group;
+                                               $group = array();
+                                       }
+                                       if (!empty($row)) {
+                                               $toolbar[] = $row;
+                                               $row = array();
+                                       }
+                                       break;
+                               case 'bar':
+                                               // Add group to row if not empty
+                                       if (!empty($group)) {
+                                               $row[] = $group;
+                                               $group = array();
+                                       }
+                                       break;
+                               case 'space':
+                                       if (end($group) != $this->convertToolbarForHTMLArea($item)) {
+                                               $group[] = $this->convertToolbarForHTMLArea($item);
+                                       }
+                                       break;
+                               default:
+                                       if (in_array($item, $this->toolbar)) {
+                                                       // Add the item to the group
+                                               $convertedItem = $this->convertToolbarForHTMLArea($item);
+                                               if ($convertedItem) {
+                                                       $group[] = $convertedItem;
+                                               }
+                                       }
+                                       break;
                        }
-                       // else ignore
                }
-                       // add the last group
-               if($group_has_button) $toolbar .= $toolbar ? (', ' . $group) : ('[[' . $group);
-               $toolbar = $toolbar . ']]';
-               return $toolbar;
+                       // Add the last group and last line, if not empty
+               if (!empty($group)) {
+                       $row[] = $group;
+               }
+               if (!empty($row)) {
+                       $toolbar[] = $row;
+               }
+               return json_encode($toolbar);
        }
-       
+
+       /**
+        * Localize a string using the language of the content element rather than the language of the BE interface
+        *
+        * @param       string          string: the label to be localized
+        * @return      string          Localized string.
+        */
        public function getLLContent($string) {
-               global $LANG;
-               
-               $BE_lang = $LANG->lang;
-               $BE_charSet = $LANG->charSet;
-               $LANG->lang = $this->contentTypo3Language;
-               $LANG->charSet = $this->contentCharset;
-               $LLString = $LANG->JScharCode($LANG->sL($string));
-               $LANG->lang = $BE_lang;
-               $LANG->charSet = $BE_charSet;
+               $BE_lang = $GLOBALS['LANG']->lang;
+
+               $GLOBALS['LANG']->lang = $this->contentTypo3Language;
+               $LLString = $GLOBALS['LANG']->JScharCode($GLOBALS['LANG']->sL($string));
+
+               $GLOBALS['LANG']->lang = $BE_lang;
                return $LLString;
        }
-       
+
        public function getPageConfigLabel($string,$JScharCode=1) {
                global $LANG, $TSFE, $TYPO3_CONF_VARS;
-               
+
                if ($this->is_FE()) {
-                       if (strcmp(substr($string,0,4),'LLL:') && $TYPO3_CONF_VARS['BE']['forceCharset'])       {
-                                       // A pure string coming from Page TSConfig must be in forceCharset, otherwise we just don't know..
-                               $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $TYPO3_CONF_VARS['BE']['forceCharset'], $this->OutputCharset);
+                       if (strcmp(substr($string,0,4),'LLL:')) {
+                                       // A pure string coming from Page TSConfig must be in utf-8
+                               $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), 'utf-8', $this->OutputCharset);
                        } else {
                                $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
                        }
@@ -1379,29 +1288,30 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                }
                return $label;
        }
-       
+
        function feJScharCode($str) {
-               global $TSFE;
                        // Convert string to UTF-8:
-               if ($this->OutputCharset != 'utf-8') $str = $TSFE->csConvObj->utf8_encode($str,$this->OutputCharset);
+               if ($this->OutputCharset != 'utf-8') {
+                       $str = $GLOBALS['TSFE']->csConvObj->utf8_encode($str, $this->OutputCharset);
+               }
                        // Convert the UTF-8 string into a array of char numbers:
-               $nArr = $TSFE->csConvObj->utf8_to_numberarray($str);
-               return 'String.fromCharCode('.implode(',',$nArr).')';
+               $nArr = $GLOBALS['TSFE']->csConvObj->utf8_to_numberarray($str);
+               return 'String.fromCharCode('.implode(',', $nArr).')';
        }
-       
+
        public function getFullFileName($filename) {
                if (substr($filename,0,4)=='EXT:')      {       // extension
                        list($extKey,$local) = explode('/',substr($filename,4),2);
                        $newFilename = '';
                        if (strcmp($extKey,'') &&  t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
-                               $newFilename = $this->siteURL . t3lib_extMgm::siteRelPath($extKey) . $local;
+                               $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? t3lib_extMgm::siteRelPath($extKey) : $this->backPath . t3lib_extMgm::extRelPath($extKey)) . $local;
                        }
                } elseif (substr($filename,0,1) != '/') {
-                       $newFilename = $this->siteURL . $filename;
+                       $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . $filename;
                } else {
-                       $newFilename = $this->siteURL . substr($filename,1);
+                       $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . substr($filename, 1);
                }
-               return $newFilename;
+               return  t3lib_div::resolveBackPath($newFilename);
        }
 
        /**
@@ -1411,27 +1321,14 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         * @param       integer         $RTEcounter: The index number of the current RTE editing area within the form.
         * @param       string          $formName: the name of the form
         * @param       string          $textareaId: the id of the textarea
+        * @param       string          $textareaName: the name of the textarea
         *
         * @return      string          Javascript code
         */
-       function setSaveRTE($RTEcounter, $formName, $textareaId) {
-               return '
-               rteFound = false;
-               for (editornumber = 1; editornumber < RTEarea.length; editornumber++) {
-                       if (RTEarea[editornumber].textAreaId == "' . $textareaId . '") {
-                               if (!RTEarea[editornumber].deleted) {
-                       document.'.$formName.'["'.$textareaId.'"].value = RTEarea[editornumber]["editor"].getHTML();
-               }
-                               rteFound = true;
-                               break;
-                       }
-               }
-               if (!rteFound) {
-                       OK = 0;
-               }
-               ';
+       function setSaveRTE($RTEcounter, $formName, $textareaId, $textareaName) {
+               return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaName . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };';
        }
-       
+
        /**
         * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
         * This is for submit function of the form.
@@ -1443,104 +1340,72 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         * @return      string          Javascript code
         */
        function setDeleteRTE($RTEcounter, $formName, $textareaId) {
-               return '
-               for (editornumber = 1; editornumber < RTEarea.length; editornumber++) {
-                       if (RTEarea[editornumber].textAreaId == "' . $textareaId . '") {
-                               if (RTEarea[editornumber]) {
-                                       RTEarea[editornumber].deleted = true;
-                               }
-                       }
-                       break;
-               }
-               ';
+               return 'if (RTEarea["' . $textareaId . '"]) { RTEarea["' . $textareaId . '"].deleted = true;}';
        }
 
        /**
-        * Return true if we are in the FE, but not in the FE editing feature of BE.
+        * Return TRUE if we are in the FE, but not in the FE editing feature of BE.
         *
         * @return boolean
         */
-        
+
        function is_FE() {
-               global $TSFE;
-               return is_object($TSFE) && is_array($this->LOCAL_LANG) && !strstr($this->elementId,'TSFE_EDIT');
+               return is_object($GLOBALS['TSFE']) && !$this->isFrontendEditActive() && TYPO3_MODE=='FE';
        }
-       
+
        /**
-        * Client Browser Information
+        * Checks whether frontend editing is active.
         *
-        * Usage: 4
+        * @return              boolean
+        */
+       public function isFrontendEditActive() {
+               return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit);
+       }
+       /**
+        * Client Browser Information
         *
-        * @param       string          Alternative User Agent string (if empty, t3lib_div::getIndpEnv('HTTP_USER_AGENT') is used)
-        * @return      array           Parsed information about the HTTP_USER_AGENT in categories BROWSER, VERSION, SYSTEM and FORMSTYLE
+        * @param       string          $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
+        * @return      array           Contains keys "useragent", "browser", "version", "system"
+        *                                      where "browser" is limited to the engines
+        *                                      and where "version" is a floating number
         */
-
-       function clientInfo($useragent='')      {
-               global $TYPO3_CONF_VARS;
-               
-               if (!$useragent) $useragent=t3lib_div::getIndpEnv('HTTP_USER_AGENT');
-               
-               $bInfo=array();
-                       // Which browser?
-               if (strstr($useragent,'Konqueror'))     {
-                       $bInfo['BROWSER']= 'konqu';
-               } elseif (strstr($useragent,'Opera'))   {
-                       $bInfo['BROWSER']= 'opera';
-               } elseif (strstr($useragent,'MSIE'))    {
-                       $bInfo['BROWSER']= 'msie';
-               } elseif (strstr($useragent,'Gecko/'))  {
-                       $bInfo['BROWSER']='gecko';
-               } elseif (strstr($useragent,'Safari/')) {
-                       $bInfo['BROWSER']='safari';
-               } elseif (strstr($useragent,'Mozilla/4')) {
-                       $bInfo['BROWSER']='net';
+       function clientInfo ($userAgent='') {
+               if (!$userAgent) {
+                       $userAgent = t3lib_div::getIndpEnv('HTTP_USER_AGENT');
                }
-
-               if ($bInfo['BROWSER'])  {
-                               // Browser version
-                       switch($bInfo['BROWSER'])       {
-                               case 'net':
-                                       $bInfo['VERSION']= doubleval(substr($useragent,8));
-                                       if (strstr($useragent,'Netscape6/')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape6/'),10));}
-                                       if (strstr($useragent,'Netscape/7')) {$bInfo['VERSION']=doubleval(substr(strstr($useragent,'Netscape/7'),9));}
-                               break;
-                               case 'gecko':
-                                       $tmp = strstr($useragent,'rv:');
-                                       $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,3)));
-                               break;
-                               case 'msie':
-                                       $tmp = strstr($useragent,'MSIE');
-                                       $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,4)));
-                               break;
-                               case 'safari':
-                                       $tmp = strstr($useragent,'Safari/');
-                                       $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,3)));
-                               break;
-                               case 'opera':
-                                       $tmp = strstr($useragent,'Opera');
-                                       $bInfo['VERSION'] = doubleval(ereg_replace('^[^0-9]*','',substr($tmp,5)));
-                               break;
-                               case 'konqu':
-                                       $tmp = strstr($useragent,'Konqueror/');
-                                       $bInfo['VERSION'] = doubleval(substr($tmp,10));
-                               break;
+               $browserInfo = t3lib_utility_Client::getBrowserInfo($userAgent);
+                       // Known engines: order is not irrelevant!
+               $knownEngines = array('opera', 'msie', 'gecko', 'webkit');
+               if (is_array($browserInfo['all'])) {
+                       foreach ($knownEngines as $engine) {
+                               if ($browserInfo['all'][$engine]) {
+                                       $browserInfo['browser'] = $engine;
+                                       $browserInfo['version'] = t3lib_utility_Client::getVersion($browserInfo['all'][$engine]);
+                                       break;
+                               }
                        }
-
-                               // Client system
-                       if (strstr($useragent,'Win'))   {
-                               $bInfo['SYSTEM'] = 'win';
-                       } elseif (strstr($useragent,'Mac'))     {
-                               $bInfo['SYSTEM'] = 'mac';
-                       } elseif (strstr($useragent,'Linux') || strstr($useragent,'X11') || strstr($useragent,'SGI') || strstr($useragent,' SunOS ') || strstr($useragent,' HP-UX '))   {
-                               $bInfo['SYSTEM'] = 'unix';
+               }
+               return $browserInfo;
+       }
+       /**
+        * Log usage of deprecated Page TS Config Property
+        *
+        * @param string $deprecatedProperty: Name of deprecated property
+        * @param string $useProperty: Name of property to use instead
+        * @param string $version: Version of TYPO3 in which the property will be removed
+        *
+        * @return void
+        */
+       public function logDeprecatedProperty ($deprecatedProperty, $useProperty, $version) {
+               if (!$this->thisConfig['logDeprecatedProperties.']['disabled']) {
+                       $message = sprintf('RTE Page TSConfig property "%1$s" used on page id #%4$s is DEPRECATED and will be removed in TYPO3 %3$s. Use "%2$s" instead.', $deprecatedProperty, $useProperty, $version, $this->thePid);
+                       t3lib_div::deprecationLog($message);
+                       if (is_object($GLOBALS['BE_USER']) && $this->thisConfig['logDeprecatedProperties.']['logAlsoToBELog']) {
+                               $message = sprintf($GLOBALS['LANG']->getLL('deprecatedPropertyMessage'), $deprecatedProperty, $useProperty, $version, $this->thePid);
+                               $GLOBALS['BE_USER']->simplelog($message, $this->ID);
                        }
                }
-
-                       // Is true if the browser supports css to format forms, especially the width
-               $bInfo['FORMSTYLE']=($bInfo['BROWSER']=='msie' || ($bInfo['BROWSER']=='net'&&$bInfo['VERSION']>=5) || $bInfo['BROWSER']=='opera' || $bInfo['BROWSER']=='konqu');
-               return $bInfo;
        }
-
        /***************************
         *
         * OTHER FUNCTIONS:     (from Classic RTE)
@@ -1548,7 +1413,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
         ***************************/
        /**
         * @return      [type]          ...
-        * @desc 
+        * @desc
         */
 
        function RTEtsConfigParams()    {
@@ -1568,7 +1433,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                }
                return $str;
        }
-       
+
        function filterStyleEl($elValue,$matchList)     {
                $matchParts = t3lib_div::trimExplode(',',$matchList,1);
                $styleParts = explode(';',$elValue);
@@ -1588,7 +1453,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                }
                return implode('; ',$nStyle);
        }
-       
+
                // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
        function loremIpsumInsert($params) {
                return "
@@ -1596,9 +1461,7 @@ class tx_rtehtmlarea_base extends t3lib_rteapi {
                                ";
        }
 }
-
-if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php'])  {
-       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
+if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php'])) {
+       include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
 }
-
-?>
+?>
\ No newline at end of file