Index: typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php
===================================================================
--- typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/class.tx_rtehtmlarea_base.php	(copie de travail)
@@ -4,7 +4,7 @@
 *
 *  (c) 2004-2009 Kasper Skaarhoj (kasper@typo3.com)
 *  (c) 2004-2009 Philipp Borgmann <philipp.borgmann@gmx.de>
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -36,18 +36,17 @@
  */
 
 class tx_rtehtmlarea_base extends t3lib_rteapi {
-
 		// Configuration of supported browsers
 	var $conf_supported_browser = array (
 			'msie' => array (
 				1 => array (
-					'version' => 5.5,
+					'version' => 6.0,
 					'system' => 'win'
 				)
 			),
 			'gecko' => array (
 				1 => array (
-					'version' => 1.3
+					'version' => 1.8
 				)
 			),
 			'safari' => array (
@@ -72,9 +71,7 @@
 
 		// Conversion array: TYPO3 button names to htmlArea button names
 	var $convertToolbarForHtmlAreaArray = array (
-		'line'			=> 'InsertHorizontalRule',
 		'showhelp'		=> 'ShowHelp',
-		'textindicator'		=> 'TextIndicator',
 		'space'			=> 'space',
 		'bar'			=> 'separator',
 		'linebreak'		=> 'linebreak',
@@ -120,11 +117,11 @@
 	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;
 
 	/**
 	 * Returns true if the RTE is available. Here you check if the browser requirements are met.
@@ -338,13 +335,16 @@
 				// Preloading the pageStyle and including RTE skin stylesheets
 			$this->addPageStyle();
 			$this->addSkin();
-
 				// Loading JavaScript files and code
 			if ($this->TCEform->RTEcounter == 1) {
 				$this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
 			}
 			$this->TCEform->additionalCode_pre['rtehtmlarea-loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter);
-
+			$pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
+			$pageRenderer->enableExtJSQuickTips();
+			if (!$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts']) {
+				$pageRenderer->enableExtJsDebug();
+			}
 			/* =======================================
 			 * DRAW THE EDITOR
 			 * =======================================
@@ -365,20 +365,10 @@
 
 				// 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';
-
+				$this->fullScreen = true;
 				$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:
@@ -426,9 +416,6 @@
 	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';
-		if($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3' && substr($skinFilename,0,4) == 'EXT:')  {
-			$skinFilename = 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
-		}
 			// Skin provided by some extension
 		if (substr($skinFilename,0,4) == 'EXT:') {
 			list($extKey,$local) = explode('/',substr($skinFilename,4),2);
@@ -561,44 +548,22 @@
 	function setToolbar() {
 		global $BE_USER;
 
-		if ($this->client['BROWSER'] == 'msie' || $this->client['BROWSER'] == 'opera' || ($this->client['BROWSER'] == 'gecko' && $this->client['VERSION'] == '1.3')) {
+		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, 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, emoticon, insertcharacter, 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,
 			' . ($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, language, showlanguagemarks, 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, language, showlanguagemarks, 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)) {
@@ -738,22 +703,7 @@
 	 function convertToolbarForHTMLArea($button) {
  		return $this->convertToolbarForHtmlAreaArray[$button];
 	 }
-
 	/**
-	 * Return the JS-function for setting the RTE size.
-	 *
-	 * @param	string		DivID-Name
-	 * @param	int			the height for the RTE
-	 * @param	int			the width for the RTE
-	 * @return string		Loader function in JS
-	 */
-	function setRTEsizeByJS($divId, $height, $width) {
-		return '
-			setRTEsizeByJS(\''.$divId.'\','.$height.', '.$width.');
-		';
-	}
-
-	/**
 	 * Return the HTML code for loading the Javascript files
 	 *
 	 * @param	integer		$RTEcounter: The index number of the current RTE editing area within the form.
@@ -777,7 +727,7 @@
 			if (typeof(RTEarea) == "undefined") {
 				RTEarea = new Object();
 				RTEarea.init = function() {
-					if (typeof(HTMLArea) == "undefined") {
+					if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
 						window.setTimeout("RTEarea.init();", 40);
 					} else {'
 						. $loadPluginCode . '
@@ -859,6 +809,10 @@
 			RTEarea[editornumber].deleted = false;
 			RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
 			RTEarea[editornumber].id = "RTEarea" + editornumber;
+			RTEarea[editornumber].RTEWidthOverride = "' . trim($this->thisConfig['RTEWidthOverride']) . '";
+			RTEarea[editornumber].RTEHeightOverride = "' . trim($this->thisConfig['RTEHeightOverride']) . '";
+			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].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . ';
@@ -1215,64 +1169,62 @@
 	}
 
 	/**
-	 * 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 = ($button == 'bar');
-			} 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);
 	}
 
 	public function getLLContent($string) {
@@ -1347,7 +1299,7 @@
 	 * @return	string		Javascript code
 	 */
 	function setSaveRTE($RTEcounter, $formName, $textareaId) {
-		return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getPluginInstance("EditorMode").getHTML(); } else { OK = 0; };';
+		return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };';
 	}
 
 	/**
Index: typo3/sysext/rtehtmlarea/ext_emconf.php
===================================================================
--- typo3/sysext/rtehtmlarea/ext_emconf.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/ext_emconf.php	(copie de travail)
@@ -19,7 +19,7 @@
 	'conflicts' => 'rte_conf',
 	'priority' => '',
 	'loadOrder' => '',
-	'module' => 'mod2,mod3,mod4,mod5,mod6',
+	'module' => 'mod3,mod4,mod5,mod6',
 	'state' => 'stable',
 	'internal' => 0,
 	'uploadfolder' => 1,
@@ -32,7 +32,7 @@
 	'author_company' => 'SJBR',
 	'CGLcompliance' => '',
 	'CGLcompliance_note' => '',
-	'version' => '1.9.0',
+	'version' => '1.9.1',
 	'_md5_values_when_last_written' => 'a:434:{s:9:"ChangeLog";s:4:"e5f3";s:29:"class.tx_rtehtmlarea_base.php";s:4:"8a14";s:27:"class.tx_rtehtmlareaapi.php";s:4:"69b4";s:21:"ext_conf_template.txt";s:4:"afd8";s:12:"ext_icon.gif";s:4:"2f41";s:17:"ext_localconf.php";s:4:"340c";s:14:"ext_tables.php";s:4:"ea2e";s:14:"ext_tables.sql";s:4:"bba8";s:13:"locallang.xml";s:4:"3cca";s:16:"locallang_db.xml";s:4:"c2ed";s:7:"tca.php";s:4:"6b5a";s:14:"doc/manual.sxw";s:4:"e68c";s:59:"extensions/AboutEditor/class.tx_rtehtmlarea_abouteditor.php";s:4:"d8ac";s:40:"extensions/AboutEditor/skin/htmlarea.css";s:4:"eb62";s:44:"extensions/AboutEditor/skin/images/about.gif";s:4:"1690";s:51:"extensions/Acronym/class.tx_rtehtmlarea_acronym.php";s:4:"ee28";s:36:"extensions/Acronym/skin/htmlarea.css";s:4:"c107";s:42:"extensions/Acronym/skin/images/acronym.gif";s:4:"1eaa";s:63:"extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php";s:4:"aeef";s:38:"extensions/BlockElements/locallang.xml";s:4:"479e";s:42:"extensions/BlockElements/skin/htmlarea.css";s:4:"83ce";s:51:"extensions/BlockElements/skin/images/blockquote.gif";s:4:"34dc";s:47:"extensions/BlockElements/skin/images/indent.gif";s:4:"57df";s:58:"extensions/BlockElements/skin/images/insertOrderedList.gif";s:4:"eb1c";s:61:"extensions/BlockElements/skin/images/insertParagraphAfter.gif";s:4:"e335";s:62:"extensions/BlockElements/skin/images/insertParagraphBefore.gif";s:4:"9c42";s:60:"extensions/BlockElements/skin/images/insertUnorderedList.gif";s:4:"5620";s:54:"extensions/BlockElements/skin/images/justifyCenter.gif";s:4:"420d";s:52:"extensions/BlockElements/skin/images/justifyFull.gif";s:4:"b129";s:52:"extensions/BlockElements/skin/images/justifyLeft.gif";s:4:"3799";s:53:"extensions/BlockElements/skin/images/justifyRight.gif";s:4:"0662";s:48:"extensions/BlockElements/skin/images/outdent.gif";s:4:"4786";s:57:"extensions/BlockStyle/class.tx_rtehtmlarea_blockstyle.php";s:4:"3ba0";s:35:"extensions/BlockStyle/locallang.xml";s:4:"26b8";s:61:"extensions/CharacterMap/class.tx_rtehtmlarea_charactermap.php";s:4:"a537";s:41:"extensions/CharacterMap/skin/htmlarea.css";s:4:"06c8";s:55:"extensions/CharacterMap/skin/images/insertCharacter.gif";s:4:"af19";s:59:"extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php";s:4:"e4b5";s:55:"extensions/CopyPaste/class.tx_rtehtmlarea_copypaste.php";s:4:"09ad";s:38:"extensions/CopyPaste/skin/htmlarea.css";s:4:"9391";s:41:"extensions/CopyPaste/skin/images/copy.gif";s:4:"98d2";s:40:"extensions/CopyPaste/skin/images/cut.gif";s:4:"1323";s:42:"extensions/CopyPaste/skin/images/paste.gif";s:4:"7df5";s:61:"extensions/DefaultClean/class.tx_rtehtmlarea_defaultclean.php";s:4:"142b";s:61:"extensions/DefaultColor/class.tx_rtehtmlarea_defaultcolor.php";s:4:"fa59";s:37:"extensions/DefaultColor/locallang.xml";s:4:"3fb4";s:41:"extensions/DefaultColor/skin/htmlarea.css";s:4:"6076";s:49:"extensions/DefaultColor/skin/images/forecolor.gif";s:4:"dbc8";s:51:"extensions/DefaultColor/skin/images/hilitecolor.gif";s:4:"d97c";s:59:"extensions/DefaultFont/class.tx_rtehtmlarea_defaultfont.php";s:4:"2172";s:36:"extensions/DefaultFont/locallang.xml";s:4:"8c90";s:61:"extensions/DefaultImage/class.tx_rtehtmlarea_defaultimage.php";s:4:"12cf";s:41:"extensions/DefaultImage/skin/htmlarea.css";s:4:"6cfe";s:45:"extensions/DefaultImage/skin/images/image.gif";s:4:"c0f0";s:63:"extensions/DefaultInline/class.tx_rtehtmlarea_defaultinline.php";s:4:"4e85";s:38:"extensions/DefaultInline/locallang.xml";s:4:"318f";s:42:"extensions/DefaultInline/skin/htmlarea.css";s:4:"6009";s:45:"extensions/DefaultInline/skin/images/bold.gif";s:4:"94f2";s:47:"extensions/DefaultInline/skin/images/italic.gif";s:4:"f60c";s:54:"extensions/DefaultInline/skin/images/strikethrough.gif";s:4:"3fd0";s:50:"extensions/DefaultInline/skin/images/subscript.gif";s:4:"cedd";s:52:"extensions/DefaultInline/skin/images/superscript.gif";s:4:"8aea";s:50:"extensions/DefaultInline/skin/images/underline.gif";s:4:"81e6";s:59:"extensions/DefaultLink/class.tx_rtehtmlarea_defaultlink.php";s:4:"2219";s:40:"extensions/DefaultLink/skin/htmlarea.css";s:4:"680b";s:43:"extensions/DefaultLink/skin/images/link.gif";s:4:"db9a";s:45:"extensions/DefaultLink/skin/images/unlink.gif";s:4:"86c4";s:65:"extensions/DefinitionList/class.tx_rtehtmlarea_definitionlist.php";s:4:"483d";s:43:"extensions/DefinitionList/skin/htmlarea.css";s:4:"a254";s:56:"extensions/DefinitionList/skin/images/definitionItem.gif";s:4:"33ae";s:56:"extensions/DefinitionList/skin/images/definitionList.gif";s:4:"d5d1";s:57:"extensions/EditorMode/class.tx_rtehtmlarea_editormode.php";s:4:"1453";s:39:"extensions/EditorMode/skin/htmlarea.css";s:4:"0793";s:45:"extensions/EditorMode/skin/images/ed_html.gif";s:4:"fa6e";s:59:"extensions/FindReplace/class.tx_rtehtmlarea_findreplace.php";s:4:"a968";s:40:"extensions/FindReplace/skin/htmlarea.css";s:4:"43cc";s:43:"extensions/FindReplace/skin/images/find.gif";s:4:"827f";s:65:"extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php";s:4:"452a";s:39:"extensions/InlineElements/locallang.xml";s:4:"07c6";s:46:"extensions/InlineElements/res/pageTSConfig.txt";s:4:"088c";s:43:"extensions/InlineElements/skin/htmlarea.css";s:4:"978b";s:54:"extensions/InlineElements/skin/images/bidioverride.gif";s:4:"f38b";s:45:"extensions/InlineElements/skin/images/big.gif";s:4:"779b";s:46:"extensions/InlineElements/skin/images/bold.gif";s:4:"06ac";s:50:"extensions/InlineElements/skin/images/citation.gif";s:4:"b6eb";s:46:"extensions/InlineElements/skin/images/code.gif";s:4:"6057";s:52:"extensions/InlineElements/skin/images/definition.gif";s:4:"692d";s:53:"extensions/InlineElements/skin/images/deletedtext.gif";s:4:"4eec";s:50:"extensions/InlineElements/skin/images/emphasis.gif";s:4:"04c9";s:54:"extensions/InlineElements/skin/images/insertedtext.gif";s:4:"a624";s:48:"extensions/InlineElements/skin/images/italic.gif";s:4:"be83";s:50:"extensions/InlineElements/skin/images/keyboard.gif";s:4:"53ac";s:52:"extensions/InlineElements/skin/images/monospaced.gif";s:4:"78c0";s:51:"extensions/InlineElements/skin/images/quotation.gif";s:4:"7c62";s:48:"extensions/InlineElements/skin/images/sample.gif";s:4:"667c";s:47:"extensions/InlineElements/skin/images/small.gif";s:4:"e013";s:46:"extensions/InlineElements/skin/images/span.gif";s:4:"0dfa";s:55:"extensions/InlineElements/skin/images/strikethrough.gif";s:4:"73b1";s:48:"extensions/InlineElements/skin/images/strong.gif";s:4:"7f50";s:51:"extensions/InlineElements/skin/images/subscript.gif";s:4:"36c0";s:53:"extensions/InlineElements/skin/images/superscript.gif";s:4:"40c4";s:51:"extensions/InlineElements/skin/images/underline.gif";s:4:"dfac";s:50:"extensions/InlineElements/skin/images/variable.gif";s:4:"da61";s:61:"extensions/InsertSmiley/class.tx_rtehtmlarea_insertsmiley.php";s:4:"4d97";s:41:"extensions/InsertSmiley/skin/htmlarea.css";s:4:"fb52";s:46:"extensions/InsertSmiley/skin/images/smiley.gif";s:4:"c331";s:53:"extensions/Language/class.tx_rtehtmlarea_language.php";s:4:"4f0b";s:33:"extensions/Language/locallang.xml";s:4:"ff62";s:37:"extensions/Language/skin/htmlarea.css";s:4:"7034";s:49:"extensions/Language/skin/images/left_to_right.gif";s:4:"1a1f";s:49:"extensions/Language/skin/images/right_to_left.gif";s:4:"2a38";s:55:"extensions/Language/skin/images/show-language-marks.gif";s:4:"0bbb";s:53:"extensions/QuickTag/class.tx_rtehtmlarea_quicktag.php";s:4:"c925";s:37:"extensions/QuickTag/skin/htmlarea.css";s:4:"b006";s:45:"extensions/QuickTag/skin/images/inserttag.gif";s:4:"a463";s:61:"extensions/RemoveFormat/class.tx_rtehtmlarea_removeformat.php";s:4:"f7a1";s:41:"extensions/RemoveFormat/skin/htmlarea.css";s:4:"be33";s:45:"extensions/RemoveFormat/skin/images/clean.gif";s:4:"2a0f";s:57:"extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php";s:4:"281e";s:35:"extensions/SelectFont/locallang.xml";s:4:"cb6e";s:61:"extensions/SpellChecker/class.tx_rtehtmlarea_spellchecker.php";s:4:"9c27";s:41:"extensions/SpellChecker/skin/htmlarea.css";s:4:"cedf";s:51:"extensions/SpellChecker/skin/images/spell-check.gif";s:4:"6e0a";s:55:"extensions/StatusBar/class.tx_rtehtmlarea_statusbar.php";s:4:"7db4";s:57:"extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php";s:4:"daad";s:35:"extensions/TYPO3Color/locallang.xml";s:4:"377f";s:39:"extensions/TYPO3Color/skin/htmlarea.css";s:4:"fad4";s:47:"extensions/TYPO3Color/skin/images/forecolor.gif";s:4:"dbc8";s:49:"extensions/TYPO3Color/skin/images/hilitecolor.gif";s:4:"d97c";s:67:"extensions/TYPO3HtmlParser/class.tx_rtehtmlarea_typo3htmlparser.php";s:4:"b885";s:57:"extensions/TYPO3Image/class.tx_rtehtmlarea_typo3image.php";s:4:"55d0";s:39:"extensions/TYPO3Image/skin/htmlarea.css";s:4:"f593";s:43:"extensions/TYPO3Image/skin/images/image.gif";s:4:"c0f0";s:55:"extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php";s:4:"50b8";s:38:"extensions/TYPO3Link/skin/htmlarea.css";s:4:"73f9";s:41:"extensions/TYPO3Link/skin/images/link.gif";s:4:"db9a";s:43:"extensions/TYPO3Link/skin/images/unlink.gif";s:4:"86c4";s:67:"extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php";s:4:"56ba";s:44:"extensions/TableOperations/skin/htmlarea.css";s:4:"b57e";s:54:"extensions/TableOperations/skin/images/cell-delete.gif";s:4:"f371";s:60:"extensions/TableOperations/skin/images/cell-insert-after.gif";s:4:"2dd2";s:61:"extensions/TableOperations/skin/images/cell-insert-before.gif";s:4:"5d13";s:53:"extensions/TableOperations/skin/images/cell-merge.gif";s:4:"cb52";s:52:"extensions/TableOperations/skin/images/cell-prop.gif";s:4:"ca41";s:53:"extensions/TableOperations/skin/images/cell-split.gif";s:4:"0095";s:53:"extensions/TableOperations/skin/images/col-delete.gif";s:4:"da78";s:59:"extensions/TableOperations/skin/images/col-insert-after.gif";s:4:"80d8";s:60:"extensions/TableOperations/skin/images/col-insert-before.gif";s:4:"d47d";s:51:"extensions/TableOperations/skin/images/col-prop.gif";s:4:"b178";s:52:"extensions/TableOperations/skin/images/col-split.gif";s:4:"c168";s:55:"extensions/TableOperations/skin/images/insert_table.gif";s:4:"c01b";s:53:"extensions/TableOperations/skin/images/row-delete.gif";s:4:"a289";s:59:"extensions/TableOperations/skin/images/row-insert-above.gif";s:4:"1ef1";s:59:"extensions/TableOperations/skin/images/row-insert-under.gif";s:4:"9ad6";s:51:"extensions/TableOperations/skin/images/row-prop.gif";s:4:"5344";s:52:"extensions/TableOperations/skin/images/row-split.gif";s:4:"ebfd";s:53:"extensions/TableOperations/skin/images/table-prop.gif";s:4:"0a5c";s:56:"extensions/TableOperations/skin/images/table-restyle.gif";s:4:"9284";s:57:"extensions/TableOperations/skin/images/toggle-borders.gif";s:4:"50cb";s:55:"extensions/TextStyle/class.tx_rtehtmlarea_textstyle.php";s:4:"ed42";s:34:"extensions/TextStyle/locallang.xml";s:4:"23dd";s:53:"extensions/UndoRedo/class.tx_rtehtmlarea_undoredo.php";s:4:"d297";s:37:"extensions/UndoRedo/skin/htmlarea.css";s:4:"de26";s:40:"extensions/UndoRedo/skin/images/redo.gif";s:4:"5fdf";s:40:"extensions/UndoRedo/skin/images/undo.gif";s:4:"8d53";s:61:"extensions/UserElements/class.tx_rtehtmlarea_userelements.php";s:4:"984d";s:41:"extensions/UserElements/skin/htmlarea.css";s:4:"f66d";s:44:"extensions/UserElements/skin/images/user.gif";s:4:"bbb4";s:59:"hooks/clearrtecache/class.tx_rtehtmlarea_clearcachemenu.php";s:4:"b8fe";s:58:"hooks/clearrtecache/class.tx_rtehtmlarea_clearrtecache.php";s:4:"a33e";s:37:"hooks/clearrtecache/clearrtecache.png";s:4:"e03a";s:37:"hooks/clearrtecache/ext_localconf.php";s:4:"3cbb";s:33:"hooks/clearrtecache/locallang.xml";s:4:"3902";s:29:"htmlarea/HTMLAREA_LICENSE.txt";s:4:"a10f";s:26:"htmlarea/htmlarea-gecko.js";s:4:"786d";s:23:"htmlarea/htmlarea-ie.js";s:4:"601e";s:20:"htmlarea/htmlarea.js";s:4:"6dde";s:30:"htmlarea/locallang_dialogs.xml";s:4:"a7aa";s:26:"htmlarea/locallang_msg.xml";s:4:"7b6f";s:31:"htmlarea/locallang_tooltips.xml";s:4:"0152";s:44:"htmlarea/plugins/AboutEditor/about-editor.js";s:4:"8241";s:46:"htmlarea/plugins/AboutEditor/popups/about.html";s:4:"d677";s:35:"htmlarea/plugins/Acronym/acronym.js";s:4:"f9af";s:38:"htmlarea/plugins/Acronym/locallang.xml";s:4:"aea2";s:48:"htmlarea/plugins/BlockElements/block-elements.js";s:4:"4c56";s:44:"htmlarea/plugins/BlockElements/locallang.xml";s:4:"ee21";s:42:"htmlarea/plugins/BlockStyle/block-style.js";s:4:"d9e7";s:41:"htmlarea/plugins/BlockStyle/locallang.xml";s:4:"32ed";s:46:"htmlarea/plugins/CharacterMap/character-map.js";s:4:"3b2b";s:43:"htmlarea/plugins/CharacterMap/locallang.xml";s:4:"7211";s:58:"htmlarea/plugins/CharacterMap/popups/select_character.html";s:4:"c48a";s:44:"htmlarea/plugins/ContextMenu/context-menu.js";s:4:"d88e";s:42:"htmlarea/plugins/ContextMenu/locallang.xml";s:4:"3ead";s:40:"htmlarea/plugins/CopyPaste/copy-paste.js";s:4:"427b";s:40:"htmlarea/plugins/CopyPaste/locallang.xml";s:4:"6703";s:46:"htmlarea/plugins/DefaultClean/default-clean.js";s:4:"409f";s:43:"htmlarea/plugins/DefaultClean/locallang.xml";s:4:"9e62";s:46:"htmlarea/plugins/DefaultColor/default-color.js";s:4:"3c23";s:43:"htmlarea/plugins/DefaultColor/locallang.xml";s:4:"c8d1";s:54:"htmlarea/plugins/DefaultColor/popups/select_color.html";s:4:"8af8";s:44:"htmlarea/plugins/DefaultFont/default-font.js";s:4:"8d1c";s:42:"htmlarea/plugins/DefaultFont/locallang.xml";s:4:"a7f8";s:46:"htmlarea/plugins/DefaultImage/default-image.js";s:4:"9ca0";s:43:"htmlarea/plugins/DefaultImage/locallang.xml";s:4:"1fdd";s:54:"htmlarea/plugins/DefaultImage/popups/insert_image.html";s:4:"6773";s:48:"htmlarea/plugins/DefaultInline/default-inline.js";s:4:"c303";s:44:"htmlarea/plugins/DefaultInline/locallang.xml";s:4:"2b55";s:44:"htmlarea/plugins/DefaultLink/default-link.js";s:4:"3139";s:42:"htmlarea/plugins/DefaultLink/locallang.xml";s:4:"e233";s:45:"htmlarea/plugins/DefaultLink/popups/link.html";s:4:"6157";s:50:"htmlarea/plugins/DefinitionList/definition-list.js";s:4:"581b";s:45:"htmlarea/plugins/DefinitionList/locallang.xml";s:4:"5c85";s:42:"htmlarea/plugins/DynamicCSS/dynamiccss.css";s:4:"85b7";s:41:"htmlarea/plugins/DynamicCSS/locallang.xml";s:4:"b6bf";s:52:"htmlarea/plugins/DynamicCSS/img/red_arrow_bullet.gif";s:4:"82d6";s:42:"htmlarea/plugins/EditorMode/editor-mode.js";s:4:"eaab";s:41:"htmlarea/plugins/EditorMode/locallang.xml";s:4:"5b14";s:44:"htmlarea/plugins/FindReplace/find-replace.js";s:4:"5caf";s:41:"htmlarea/plugins/FindReplace/fr_engine.js";s:4:"4ce4";s:42:"htmlarea/plugins/FindReplace/locallang.xml";s:4:"f836";s:53:"htmlarea/plugins/FindReplace/popups/find_replace.html";s:4:"4ee2";s:40:"htmlarea/plugins/InlineCSS/locallang.xml";s:4:"7840";s:50:"htmlarea/plugins/InlineElements/inline-elements.js";s:4:"d31a";s:45:"htmlarea/plugins/InlineElements/locallang.xml";s:4:"6f8c";s:46:"htmlarea/plugins/InsertSmiley/insert-smiley.js";s:4:"23a1";s:43:"htmlarea/plugins/InsertSmiley/locallang.xml";s:4:"ed64";s:54:"htmlarea/plugins/InsertSmiley/popups/insertsmiley.html";s:4:"6ece";s:46:"htmlarea/plugins/InsertSmiley/smileys/0001.gif";s:4:"4aff";s:46:"htmlarea/plugins/InsertSmiley/smileys/0002.gif";s:4:"02c4";s:46:"htmlarea/plugins/InsertSmiley/smileys/0003.gif";s:4:"834f";s:46:"htmlarea/plugins/InsertSmiley/smileys/0004.gif";s:4:"fb6a";s:46:"htmlarea/plugins/InsertSmiley/smileys/0005.gif";s:4:"2a48";s:46:"htmlarea/plugins/InsertSmiley/smileys/0006.gif";s:4:"f970";s:46:"htmlarea/plugins/InsertSmiley/smileys/0007.gif";s:4:"97ee";s:46:"htmlarea/plugins/InsertSmiley/smileys/0008.gif";s:4:"10a6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0009.gif";s:4:"1907";s:46:"htmlarea/plugins/InsertSmiley/smileys/0010.gif";s:4:"9ee6";s:46:"htmlarea/plugins/InsertSmiley/smileys/0011.gif";s:4:"ae73";s:46:"htmlarea/plugins/InsertSmiley/smileys/0012.gif";s:4:"f058";s:46:"htmlarea/plugins/InsertSmiley/smileys/0013.gif";s:4:"3ed8";s:46:"htmlarea/plugins/InsertSmiley/smileys/0014.gif";s:4:"a948";s:46:"htmlarea/plugins/InsertSmiley/smileys/0015.gif";s:4:"218d";s:46:"htmlarea/plugins/InsertSmiley/smileys/0016.gif";s:4:"3539";s:46:"htmlarea/plugins/InsertSmiley/smileys/0017.gif";s:4:"ee2e";s:46:"htmlarea/plugins/InsertSmiley/smileys/0018.gif";s:4:"8c66";s:46:"htmlarea/plugins/InsertSmiley/smileys/0019.gif";s:4:"ac36";s:46:"htmlarea/plugins/InsertSmiley/smileys/0020.gif";s:4:"71ef";s:37:"htmlarea/plugins/Language/language.js";s:4:"f923";s:39:"htmlarea/plugins/Language/locallang.xml";s:4:"d16c";s:39:"htmlarea/plugins/QuickTag/locallang.xml";s:4:"2f53";s:38:"htmlarea/plugins/QuickTag/quick-tag.js";s:4:"3efd";s:36:"htmlarea/plugins/QuickTag/tag-lib.js";s:4:"ba71";s:46:"htmlarea/plugins/QuickTag/popups/quicktag.html";s:4:"9f4b";s:43:"htmlarea/plugins/RemoveFormat/locallang.xml";s:4:"aa85";s:46:"htmlarea/plugins/RemoveFormat/remove-format.js";s:4:"cbbb";s:54:"htmlarea/plugins/RemoveFormat/popups/removeformat.html";s:4:"061e";s:42:"htmlarea/plugins/SelectColor/locallang.xml";s:4:"9f9e";s:42:"htmlarea/plugins/SelectFont/select-font.js";s:4:"af22";s:43:"htmlarea/plugins/SpellChecker/locallang.xml";s:4:"20d8";s:51:"htmlarea/plugins/SpellChecker/spell-check-style.css";s:4:"82bd";s:47:"htmlarea/plugins/SpellChecker/spell-check-ui.js";s:4:"7831";s:46:"htmlarea/plugins/SpellChecker/spell-checker.js";s:4:"c8a9";s:67:"htmlarea/plugins/SpellChecker/popups/spell-check-ui-iso-8859-1.html";s:4:"8a95";s:56:"htmlarea/plugins/SpellChecker/popups/spell-check-ui.html";s:4:"61dc";s:40:"htmlarea/plugins/StatusBar/status-bar.js";s:4:"c578";s:44:"htmlarea/plugins/TYPO3Browsers/locallang.xml";s:4:"89b8";s:47:"htmlarea/plugins/TYPO3Browsers/img/download.gif";s:4:"f6d9";s:52:"htmlarea/plugins/TYPO3Browsers/img/external_link.gif";s:4:"9e48";s:63:"htmlarea/plugins/TYPO3Browsers/img/external_link_new_window.gif";s:4:"6e8d";s:52:"htmlarea/plugins/TYPO3Browsers/img/internal_link.gif";s:4:"12b9";s:63:"htmlarea/plugins/TYPO3Browsers/img/internal_link_new_window.gif";s:4:"402a";s:43:"htmlarea/plugins/TYPO3Browsers/img/mail.gif";s:4:"d5a2";s:41:"htmlarea/plugins/TYPO3Color/locallang.xml";s:4:"3d3c";s:41:"htmlarea/plugins/TYPO3Color/typo3color.js";s:4:"5afa";s:46:"htmlarea/plugins/TYPO3HtmlParser/locallang.xml";s:4:"8010";s:52:"htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js";s:4:"99ea";s:41:"htmlarea/plugins/TYPO3Image/locallang.xml";s:4:"ab27";s:41:"htmlarea/plugins/TYPO3Image/typo3image.js";s:4:"ccc3";s:39:"htmlarea/plugins/TYPO3Link/typo3link.js";s:4:"677d";s:46:"htmlarea/plugins/TableOperations/locallang.xml";s:4:"e7ed";s:52:"htmlarea/plugins/TableOperations/table-operations.js";s:4:"1bbc";s:40:"htmlarea/plugins/TextStyle/locallang.xml";s:4:"ff67";s:40:"htmlarea/plugins/TextStyle/text-style.js";s:4:"7356";s:38:"htmlarea/plugins/UndoRedo/undo-redo.js";s:4:"762b";s:43:"htmlarea/plugins/UserElements/locallang.xml";s:4:"33f9";s:46:"htmlarea/plugins/UserElements/user-elements.js";s:4:"52c7";s:26:"htmlarea/popups/blank.html";s:4:"8d8d";s:32:"htmlarea/popups/editor_help.html";s:4:"398a";s:50:"htmlarea/skins/default/htmlarea-edited-content.css";s:4:"6626";s:35:"htmlarea/skins/default/htmlarea.css";s:4:"5112";s:48:"htmlarea/skins/default/images/definitionItem.gif";s:4:"33ae";s:48:"htmlarea/skins/default/images/definitionList.gif";s:4:"d5d1";s:42:"htmlarea/skins/default/images/ed_about.gif";s:4:"2763";s:42:"htmlarea/skins/default/images/ed_blank.gif";s:4:"0208";s:45:"htmlarea/skins/default/images/ed_color_bg.gif";s:4:"c6e2";s:45:"htmlarea/skins/default/images/ed_color_fg.gif";s:4:"5d7f";s:41:"htmlarea/skins/default/images/ed_copy.gif";s:4:"4f55";s:43:"htmlarea/skins/default/images/ed_custom.gif";s:4:"e7b2";s:40:"htmlarea/skins/default/images/ed_cut.gif";s:4:"1b00";s:43:"htmlarea/skins/default/images/ed_delete.gif";s:4:"926b";s:41:"htmlarea/skins/default/images/ed_help.gif";s:4:"e7fc";s:39:"htmlarea/skins/default/images/ed_hr.gif";s:4:"f384";s:41:"htmlarea/skins/default/images/ed_html.gif";s:4:"fa6e";s:42:"htmlarea/skins/default/images/ed_image.gif";s:4:"c0f0";s:50:"htmlarea/skins/default/images/ed_left_to_right.gif";s:4:"1a1f";s:41:"htmlarea/skins/default/images/ed_link.gif";s:4:"db9a";s:48:"htmlarea/skins/default/images/ed_list_bullet.gif";s:4:"5620";s:45:"htmlarea/skins/default/images/ed_list_num.gif";s:4:"eb1c";s:42:"htmlarea/skins/default/images/ed_paste.gif";s:4:"fbd2";s:41:"htmlarea/skins/default/images/ed_redo.gif";s:4:"e9e8";s:50:"htmlarea/skins/default/images/ed_right_to_left.gif";s:4:"2a38";s:41:"htmlarea/skins/default/images/ed_save.gif";s:4:"07ad";s:47:"htmlarea/skins/default/images/ed_splitblock.gif";s:4:"503e";s:45:"htmlarea/skins/default/images/ed_splitcel.gif";s:4:"2c04";s:41:"htmlarea/skins/default/images/ed_undo.gif";s:4:"b9ba";s:43:"htmlarea/skins/default/images/ed_unlink.gif";s:4:"86c4";s:53:"htmlarea/skins/default/images/fullscreen_maximize.gif";s:4:"2118";s:53:"htmlarea/skins/default/images/fullscreen_minimize.gif";s:4:"91d6";s:46:"htmlarea/skins/default/images/insert_table.gif";s:4:"c01b";s:49:"htmlarea/skins/default/images/language-marker.gif";s:4:"7b48";s:53:"htmlarea/skins/default/images/show-language-marks.gif";s:4:"0bbb";s:52:"htmlarea/skins/default/images/Acronym/ed_acronym.gif";s:4:"1eaa";s:58:"htmlarea/skins/default/images/BlockElements/blockquote.gif";s:4:"34dc";s:54:"htmlarea/skins/default/images/BlockElements/indent.gif";s:4:"57df";s:68:"htmlarea/skins/default/images/BlockElements/insertParagraphAfter.gif";s:4:"e335";s:69:"htmlarea/skins/default/images/BlockElements/insertParagraphBefore.gif";s:4:"9c42";s:61:"htmlarea/skins/default/images/BlockElements/justifyCenter.gif";s:4:"420d";s:59:"htmlarea/skins/default/images/BlockElements/justifyFull.gif";s:4:"b129";s:59:"htmlarea/skins/default/images/BlockElements/justifyLeft.gif";s:4:"3799";s:60:"htmlarea/skins/default/images/BlockElements/justifyRight.gif";s:4:"0662";s:55:"htmlarea/skins/default/images/BlockElements/outdent.gif";s:4:"4786";s:57:"htmlarea/skins/default/images/CharacterMap/ed_charmap.gif";s:4:"af19";s:53:"htmlarea/skins/default/images/FindReplace/ed_find.gif";s:4:"827f";s:61:"htmlarea/skins/default/images/InlineElements/bidioverride.gif";s:4:"f38b";s:52:"htmlarea/skins/default/images/InlineElements/big.gif";s:4:"779b";s:53:"htmlarea/skins/default/images/InlineElements/bold.gif";s:4:"06ac";s:57:"htmlarea/skins/default/images/InlineElements/citation.gif";s:4:"b6eb";s:53:"htmlarea/skins/default/images/InlineElements/code.gif";s:4:"6057";s:59:"htmlarea/skins/default/images/InlineElements/definition.gif";s:4:"692d";s:60:"htmlarea/skins/default/images/InlineElements/deletedtext.gif";s:4:"4eec";s:57:"htmlarea/skins/default/images/InlineElements/emphasis.gif";s:4:"04c9";s:61:"htmlarea/skins/default/images/InlineElements/insertedtext.gif";s:4:"a624";s:55:"htmlarea/skins/default/images/InlineElements/italic.gif";s:4:"be83";s:57:"htmlarea/skins/default/images/InlineElements/keyboard.gif";s:4:"53ac";s:59:"htmlarea/skins/default/images/InlineElements/monospaced.gif";s:4:"78c0";s:58:"htmlarea/skins/default/images/InlineElements/quotation.gif";s:4:"7c62";s:55:"htmlarea/skins/default/images/InlineElements/sample.gif";s:4:"667c";s:54:"htmlarea/skins/default/images/InlineElements/small.gif";s:4:"e013";s:53:"htmlarea/skins/default/images/InlineElements/span.gif";s:4:"0dfa";s:62:"htmlarea/skins/default/images/InlineElements/strikethrough.gif";s:4:"73b1";s:55:"htmlarea/skins/default/images/InlineElements/strong.gif";s:4:"7f50";s:58:"htmlarea/skins/default/images/InlineElements/subscript.gif";s:4:"36c0";s:60:"htmlarea/skins/default/images/InlineElements/superscript.gif";s:4:"40c4";s:58:"htmlarea/skins/default/images/InlineElements/underline.gif";s:4:"dfac";s:57:"htmlarea/skins/default/images/InlineElements/variable.gif";s:4:"da61";s:56:"htmlarea/skins/default/images/InsertSmiley/ed_smiley.gif";s:4:"c331";s:54:"htmlarea/skins/default/images/QuickTag/ed_quicktag.gif";s:4:"a463";s:55:"htmlarea/skins/default/images/RemoveFormat/ed_clean.gif";s:4:"2a0f";s:58:"htmlarea/skins/default/images/SpellChecker/spell-check.gif";s:4:"6e0a";s:59:"htmlarea/skins/default/images/TYPO3ViewHelp/module_help.gif";s:4:"a500";s:61:"htmlarea/skins/default/images/TableOperations/cell-delete.gif";s:4:"f371";s:67:"htmlarea/skins/default/images/TableOperations/cell-insert-after.gif";s:4:"2dd2";s:68:"htmlarea/skins/default/images/TableOperations/cell-insert-before.gif";s:4:"5d13";s:60:"htmlarea/skins/default/images/TableOperations/cell-merge.gif";s:4:"a2d2";s:59:"htmlarea/skins/default/images/TableOperations/cell-prop.gif";s:4:"ca41";s:60:"htmlarea/skins/default/images/TableOperations/cell-split.gif";s:4:"d87c";s:60:"htmlarea/skins/default/images/TableOperations/col-delete.gif";s:4:"da78";s:66:"htmlarea/skins/default/images/TableOperations/col-insert-after.gif";s:4:"80d8";s:67:"htmlarea/skins/default/images/TableOperations/col-insert-before.gif";s:4:"d47d";s:58:"htmlarea/skins/default/images/TableOperations/col-prop.gif";s:4:"b178";s:59:"htmlarea/skins/default/images/TableOperations/col-split.gif";s:4:"eacc";s:62:"htmlarea/skins/default/images/TableOperations/insert_table.gif";s:4:"c1db";s:60:"htmlarea/skins/default/images/TableOperations/row-delete.gif";s:4:"a289";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-above.gif";s:4:"1ef1";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-after.gif";s:4:"5e98";s:66:"htmlarea/skins/default/images/TableOperations/row-insert-under.gif";s:4:"9ad6";s:58:"htmlarea/skins/default/images/TableOperations/row-prop.gif";s:4:"5344";s:59:"htmlarea/skins/default/images/TableOperations/row-split.gif";s:4:"a712";s:60:"htmlarea/skins/default/images/TableOperations/table-prop.gif";s:4:"0a5c";s:63:"htmlarea/skins/default/images/TableOperations/table-restyle.gif";s:4:"9284";s:64:"htmlarea/skins/default/images/TableOperations/toggle-borders.gif";s:4:"50cb";s:54:"htmlarea/skins/default/images/UserElements/ed_user.gif";s:4:"bbb4";s:16:"mod2/acronym.php";s:4:"6dce";s:41:"mod2/class.tx_rtehtmlarea_acronym_mod.php";s:4:"9dce";s:14:"mod2/clear.gif";s:4:"cc11";s:13:"mod2/conf.php";s:4:"1ec2";s:18:"mod2/locallang.xml";s:4:"0cd8";s:21:"mod3/browse_links.php";s:4:"8d69";s:42:"mod3/class.tx_rtehtmlarea_browse_links.php";s:4:"f98e";s:46:"mod3/class.tx_rtehtmlarea_dam_browse_links.php";s:4:"e306";s:14:"mod3/clear.gif";s:4:"cc11";s:13:"mod3/conf.php";s:4:"b2fb";s:18:"mod3/locallang.xml";s:4:"2d51";s:46:"mod4/class.tx_rtehtmlarea_dam_browse_media.php";s:4:"a1e8";s:42:"mod4/class.tx_rtehtmlarea_select_image.php";s:4:"a55f";s:14:"mod4/clear.gif";s:4:"cc11";s:13:"mod4/conf.php";s:4:"8598";s:18:"mod4/locallang.xml";s:4:"8995";s:21:"mod4/select_image.php";s:4:"c6b9";s:34:"mod5/class.tx_rtehtmlarea_user.php";s:4:"f5fc";s:14:"mod5/clear.gif";s:4:"cc11";s:13:"mod5/conf.php";s:4:"7149";s:18:"mod5/locallang.xml";s:4:"7a78";s:13:"mod5/user.php";s:4:"f5b5";s:40:"mod6/class.tx_rtehtmlarea_parse_html.php";s:4:"33c4";s:13:"mod6/conf.php";s:4:"0cab";s:19:"mod6/parse_html.php";s:4:"e04e";s:32:"pi1/class.tx_rtehtmlarea_pi1.php";s:4:"54b2";s:17:"pi1/locallang.xml";s:4:"2e58";s:32:"pi2/class.tx_rtehtmlarea_pi2.php";s:4:"91ea";s:17:"pi2/locallang.xml";s:4:"a0a7";s:32:"pi3/class.tx_rtehtmlarea_pi3.php";s:4:"b2b7";s:36:"res/accessibilityicons/locallang.xml";s:4:"8211";s:39:"res/accessibilityicons/pageTSConfig.txt";s:4:"7e1a";s:39:"res/accessibilityicons/img/download.gif";s:4:"f6d9";s:44:"res/accessibilityicons/img/external_link.gif";s:4:"9e48";s:55:"res/accessibilityicons/img/external_link_new_window.gif";s:4:"6e8d";s:44:"res/accessibilityicons/img/internal_link.gif";s:4:"12b9";s:55:"res/accessibilityicons/img/internal_link_new_window.gif";s:4:"402a";s:35:"res/accessibilityicons/img/mail.gif";s:4:"d5a2";s:29:"res/advanced/pageTSConfig.txt";s:4:"414e";s:29:"res/advanced/userTSConfig.txt";s:4:"8e7a";s:26:"res/contentcss/default.css";s:4:"429f";s:28:"res/contentcss/locallang.xml";s:4:"ec0e";s:39:"res/contentcss/img/red_arrow_bullet.gif";s:4:"82d6";s:25:"res/demo/pageTSConfig.txt";s:4:"146c";s:25:"res/demo/userTSConfig.txt";s:4:"9b82";s:26:"res/image/pageTSConfig.txt";s:4:"9b6f";s:32:"res/indentalign/pageTSConfig.txt";s:4:"14d5";s:25:"res/proc/pageTSConfig.txt";s:4:"d4f8";s:26:"res/style/pageTSConfig.txt";s:4:"e8e7";s:28:"res/typical/pageTSConfig.txt";s:4:"d33d";s:28:"res/typical/userTSConfig.txt";s:4:"9fa6";s:29:"static/clickenlarge/setup.txt";s:4:"5681";}',
 	'constraints' => array(
 		'depends' => array(
Index: typo3/sysext/rtehtmlarea/ext_localconf.php
===================================================================
--- typo3/sysext/rtehtmlarea/ext_localconf.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/ext_localconf.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -68,6 +68,7 @@
 	// Troubleshooting and experimentation
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableDebugMode'] = $_EXTCONF['enableDebugMode'] ? $_EXTCONF['enableDebugMode'] : 0;
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] = $_EXTCONF['enableCompressedScripts'] ? $_EXTCONF['enableCompressedScripts'] : 0;
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] = $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableCompressedScripts'] && !$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['enableDebugMode'];
 
 	// Integrating with DAM
 	// DAM browser may be enabled here only for DAM version lower than 1.1
@@ -95,9 +96,6 @@
 
 	// Initialize plugin registration array
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins'] = array();
-	// Status Bar configuration
-$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['StatusBar'] = array();
-$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['StatusBar']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/StatusBar/class.tx_rtehtmlarea_statusbar.php:&tx_rtehtmlarea_statusbar';
 	// Editor Mode configuration
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['EditorMode'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['EditorMode']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/EditorMode/class.tx_rtehtmlarea_editormode.php:&tx_rtehtmlarea_editormode';
@@ -186,10 +184,6 @@
 	// Register features that use the style attribute
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['allowStyleAttribute'] = $_EXTCONF['allowStyleAttribute'] ? $_EXTCONF['allowStyleAttribute'] : 0;
 if ($TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['allowStyleAttribute']) {
-	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor'] = array();
-	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/DefaultColor/class.tx_rtehtmlarea_defaultcolor.php:&tx_rtehtmlarea_defaultcolor';
-	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['addIconsToSkin'] = 0;
-	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['DefaultColor']['disableInFE'] = 0;
 	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color'] = array();
 	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php:&tx_rtehtmlarea_typo3color';
 	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TYPO3Color']['addIconsToSkin'] = 0;
@@ -200,6 +194,10 @@
 	$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['SelectFont']['disableInFE'] = 0;
 	t3lib_extMgm::addPageTSConfig('<INCLUDE_TYPOSCRIPT: source="FILE:EXT:' . $_EXTKEY . '/res/style/pageTSConfig.txt">');
 }
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator'] = array();
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php:&tx_rtehtmlarea_textindicator';
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['addIconsToSkin'] = 0;
+$TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['TextIndicator']['disableInFE'] = 0;
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley'] = array();
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley']['objectReference'] = 'EXT:'.$_EXTKEY.'/extensions/InsertSmiley/class.tx_rtehtmlarea_insertsmiley.php:&tx_rtehtmlarea_insertsmiley';
 $TYPO3_CONF_VARS['EXTCONF'][$_EXTKEY]['plugins']['InsertSmiley']['addIconsToSkin'] = 0;
Index: typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/Acronym/class.tx_rtehtmlarea_acronym.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -118,22 +118,18 @@
 
 		$charset = $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : 'iso-8859-1';
 		$button = 'acronym';
+		$acronymArray = array();
+		$abbrArray = array();
 
-		$linebreak = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->htmlAreaRTE->ID]['enableCompressedScripts'] ? '' : chr(10);
-		$JSAcronymArray .= 'acronyms = { ' . $linebreak;
-		$JSAcronymLanguageArray .= 'acronymLanguage = { ' . $linebreak;
-		$JSAbbreviationArray .= 'abbreviations = { ' . $linebreak;
-		$JSAbbreviationLanguageArray .= 'abbreviationLanguage = { ' . $linebreak;
-
 		$tableA = 'tx_rtehtmlarea_acronym';
 		$tableB = 'static_languages';
-		$fields = $tableA.'.type,' . $tableA . '.term,' . $tableA . '.acronym,' . $tableB . '.lg_iso_2';
+		$fields = $tableA.'.type,' . $tableA . '.term,' . $tableA . '.acronym,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2';
 		$tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
 		$whereClause = '1=1';
 			// Get all acronyms on pages to which the user has access
 		$lockBeUserToDBmounts = isset($this->thisConfig['buttons.'][$button.'.']['lockBeUserToDBmounts']) ? $this->thisConfig['buttons.'][$button.'.']['lockBeUserToDBmounts'] : $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'];
 		if (!$GLOBALS['BE_USER']->isAdmin() && $GLOBALS['TYPO3_CONF_VARS']['BE']['lockBeUserToDBmounts'] && $lockBeUserToDBmounts) {
-                // Temporarily setting alternative web browsing mounts
+				// Temporarily setting alternative web browsing mounts
 			$altMountPoints = trim($GLOBALS['BE_USER']->getTSConfigVal('options.pageTree.altElementBrowserMountPoints'));
 			if ($altMountPoints) {
 				$savedGroupDataWebmounts = $GLOBALS['BE_USER']->groupData['webmounts'];
@@ -182,21 +178,16 @@
 		$whereClause .= t3lib_BEfunc::deleteClause($tableB);
 		$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $tableAB, $whereClause);
 		while ($acronymRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
-			if( $acronymRow['type'] == 1) {
-				$JSAcronymArray .= (($this->acronymIndex++)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset) . '"' . $linebreak;
-				$JSAcronymLanguageArray .= (($this->acronymIndex-1)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . '"' . $linebreak;
+			$item = array($GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset), $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset), $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . ($acronymRow['lg_country_iso_2'] ? ('-' . $acronymRow['lg_country_iso_2']) : ''));
+			if ($acronymRow['type'] == 1) {
+				$acronymArray[] = $item;
+			} else if ($acronymRow['type'] == 2) {
+				$abbrArray[] = $item;
 			}
-			if ($acronymRow['type'] == 2) {
-				$JSAbbreviationArray .= (($this->abbreviationIndex++)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['acronym'], $charset) . '"' . $linebreak;
-				$JSAbbreviationLanguageArray .= (($this->abbreviationIndex-1)?',':'') . '"' . $GLOBALS['LANG']->csConvObj->utf8_encode($acronymRow['term'], $charset) . '":"' . $GLOBALS['LANG']->csConvObj->utf8_encode(strtolower($acronymRow['lg_iso_2']), $charset) . '"' . $linebreak;
-			}
 		}
-		$JSAcronymArray .= '};' . $linebreak;
-		$JSAcronymLanguageArray .= '};' . $linebreak;
-		$JSAbbreviationArray .= '};' . $linebreak;
-		$JSAbbreviationLanguageArray .= '};' . $linebreak;
-
-		return $JSAcronymArray . $JSAcronymLanguageArray . $JSAbbreviationArray . $JSAbbreviationLanguageArray;
+		$this->acronymIndex = count($acronymArray);
+		$this->abbreviationIndex = count($abbrArray);
+		return 'var acronyms = ' . json_encode($acronymArray) . ';' . 'var abbreviations = ' . json_encode($abbrArray) . ';';
 	}
 }
 
Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/BlockElements/class.tx_rtehtmlarea_blockelements.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2208 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -43,7 +43,7 @@
 	protected $toolbar;					// Reference to RTE toolbar array
 	protected $LOCAL_LANG; 					// Frontend language array
 
-	protected $pluginButtons = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull, orderedlist, unorderedlist';
+	protected $pluginButtons = 'formatblock, indent, outdent, blockquote, insertparagraphbefore, insertparagraphafter, left, center, right, justifyfull, orderedlist, unorderedlist, line';
 	protected $convertToolbarForHtmlAreaArray = array (
 		'formatblock'		=> 'FormatBlock',
 		'indent'		=> 'Indent',
@@ -57,6 +57,7 @@
 		'justifyfull'		=> 'JustifyFull',
 		'orderedlist'		=> 'InsertOrderedList',
 		'unorderedlist'		=> 'InsertUnorderedList',
+		'line'			=> 'InsertHorizontalRule',
 		);
 
 	protected $defaultBlockElements = array(
@@ -171,16 +172,13 @@
 				}
 			}
 				// Generating the javascript options
-			$JSBlockElements = '{
-			"'. $first.'" : "none"';
+			$JSBlockElements = array();
+			$JSBlockElements[] = array($first, 'none');
 			foreach ($blockElementsOptions as $item => $label) {
-				$JSBlockElements .= ',
-			"' . $label . '" : "' . $item . '"';
+				$JSBlockElements[] = array($label, $item);
 			}
-			$JSBlockElements .= '};';
-
 			$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.formatblock.dropDownOptions = '. $JSBlockElements;
+			RTEarea['.$RTEcounter.'].buttons.formatblock.data = ' . json_encode($JSBlockElements) . ';';
 		}
 		return $registerRTEinJavascriptString;
 	}
Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/htmlarea.css	(copie de travail)
@@ -11,3 +11,4 @@
 .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/justifyFull.gif");}
 .htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/insertOrderedList.gif");}
 .htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/insertUnorderedList.gif");}
+.htmlarea .toolbar .InsertHorinzontalRule, .htmlarea-context-menu .InsertHorinzontalRule {background-image:url("images/insertHorizontalRule.gif");}
Index: typo3/sysext/rtehtmlarea/extensions/BlockElements/skin/images/insertHorizontalRule.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\rtehtmlarea\extensions\BlockElements\skin\images\insertHorizontalRule.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -22,7 +22,7 @@
 *  This copyright notice MUST APPEAR in all copies of the script!
 ***************************************************************/
 /**
- * About Editor plugin for htmlArea RTE
+ * Context Menu plugin for htmlArea RTE
  *
  * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
  *
@@ -49,7 +49,6 @@
 	public function main($parentObject) {
 		return parent::main($parentObject) && !($this->htmlAreaRTE->client['BROWSER'] == 'opera' || $this->thisConfig['disableContextMenu'] || $this->thisConfig['disableRightClick']);
 	}
-
 	/**
 	 * Return JS configuration of the htmlArea plugins registered by the extension
 	 *
@@ -59,17 +58,26 @@
 	 *
 	 * The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
 	 * Each of the instructions should be of the form:
-	 * 	RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
+	 * 	RTEarea['.$editorId.']["buttons"]["button-id"]["property"] = "value";
 	 */
-	public function buildJavascriptConfiguration($RTEcounter) {
+	public function buildJavascriptConfiguration($editorId) {
 		$registerRTEinJavascriptString = '';
+		if (is_array( $this->thisConfig['contextMenu.'])) {
+			$registerRTEinJavascriptString .= '
+	RTEarea['.$editorId.'].contextMenu = new Object();';
+			if ($this->thisConfig['contextMenu.']['showButtons']) {
+				$registerRTEinJavascriptString .= '
+	RTEarea['.$editorId.'].contextMenu.showButtons = ' . json_encode(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList(t3lib_div::strtolower($this->thisConfig['contextMenu.']['showButtons'])), 1)) . ';';
+			}
+			if ($this->thisConfig['contextMenu.']['hideButtons']) {
+				$registerRTEinJavascriptString .= '
+	RTEarea['.$editorId.'].contextMenu.hideButtons = ' . json_encode(t3lib_div::trimExplode(',', $this->htmlAreaRTE->cleanList(t3lib_div::strtolower($this->thisConfig['contextMenu.']['hideButtons'])), 1)) . ';';
+			}
+		}
 		return $registerRTEinJavascriptString;
 	}
-
-} // end of class
-
+}
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']) {
 	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/ContextMenu/class.tx_rtehtmlarea_contextmenu.php']);
 }
-
 ?>
\ No newline at end of file
Index: typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/InlineElements/class.tx_rtehtmlarea_inlineelements.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2009 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -24,7 +24,7 @@
 /**
  * InlineElements plugin for htmlArea RTE
  *
- * @author Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+ * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
  *
  * TYPO3 SVN ID: $Id$
  *
@@ -200,16 +200,13 @@
 				}
 			}
 				// Generating the javascript options
-			$JSInlineElements = '{
-			"'. $first.'" : "none"';
+			$JSInlineElements = array();
+			$JSInlineElements[] = array($first, 'none');
 			foreach ($inlineElementsOptions as $item => $label) {
-				$JSInlineElements .= ',
-			"' . $label . '" : "' . $item . '"';
+				$JSInlineElements[] = array($label, $item);
 			}
-			$JSInlineElements .= '};';
-
 			$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.formattext.dropDownOptions = '. $JSInlineElements;
+			RTEarea['.$RTEcounter.'].buttons.formattext.data = ' . json_encode($JSInlineElements) . ';';
 		}
 		return $registerRTEinJavascriptString;
 	 }
Index: typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/Language/class.tx_rtehtmlarea_language.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -85,10 +85,14 @@
 				$first = $GLOBALS['LANG']->getLL('No language mark');
 			}
 			$languages = array('none' => $first);
-			$languages = array_merge($languages, $this->getLanguages());
-			$languagesJSArray = 'HTMLArea.languageOptions = ' . json_encode(array_flip($languages));
+			$languages = array_flip(array_merge($languages, $this->getLanguages()));
+			$languagesJSArray = array();
+			foreach ($languages as $key => $value) {
+				$languagesJSArray[] = array($key, $value);
+			}
+			$languagesJSArray = 'var options = ' . json_encode($languagesJSArray) . ';';
 			$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'. $button .'.languagesUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', 'languages_'.$this->htmlAreaRTE->contentLanguageUid, 'js', $languagesJSArray) . '";';
+			RTEarea['.$RTEcounter.'].buttons.'. $button .'.dataUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', $button . '_' . $this->htmlAreaRTE->contentLanguageUid, 'js', $languagesJSArray) . '";';
 		}
 		return $registerRTEinJavascriptString;
 	}
Index: typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/SelectFont/class.tx_rtehtmlarea_selectfont.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -133,13 +133,11 @@
 			// Initializing the items array
 		$items = array();
 		if ($this->htmlAreaRTE->is_FE()) {
-			$items['none'] = '
-			"' . $GLOBALS['TSFE']->getLLL((($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $this->LOCAL_LANG) . '" : ""';
+			$items['none'] = array($GLOBALS['TSFE']->getLLL((($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $this->LOCAL_LANG), 'none');
 		} else {
-			$items['none'] = '
-			"' . ($this->htmlAreaRTE->TCEform->inline->isAjaxCall
+			$items['none'] = array(($this->htmlAreaRTE->TCEform->inline->isAjaxCall
 					? $GLOBALS['LANG']->csConvObj->utf8_encode($GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size'), $GLOBALS['LANG']->charSet)
-					: $GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size')) . '" : ""';
+					: $GLOBALS['LANG']->getLL(($buttonId == 'fontstyle') ? 'Default font' : 'Default size')), 'none');
 		}
 			// Inserting and localizing default items
 		if ($hideItems != '*') {
@@ -155,8 +153,7 @@
 						}
 						$label = $this->htmlAreaRTE->TCEform->inline->isAjaxCall ? $GLOBALS['LANG']->csConvObj->utf8_encode($label, $GLOBALS['LANG']->charSet) : $label;
 					}
-					$items[$name] = '
-				"' . $label . '" : "' . $this->htmlAreaRTE->cleanList($value) . '"';
+					$items[$name] = array($label, $this->htmlAreaRTE->cleanList($value));
 				}
 				$index++;
 			}
@@ -168,35 +165,29 @@
 				if (in_array($name, $addItems)) {
 					$label = $this->htmlAreaRTE->getPageConfigLabel($conf['name'],0);
 					$label = (!$this->htmlAreaRTE->is_FE() && $this->htmlAreaRTE->TCEform->inline->isAjaxCall) ? $GLOBALS['LANG']->csConvObj->utf8_encode($label, $GLOBALS['LANG']->charSet) : $label;
-					$items[$name] = '
-				"' . $label . '" : "' . $this->htmlAreaRTE->cleanList($conf['value']) . '"';
+					$items[$name] = array($label, $this->htmlAreaRTE->cleanList($conf['value']));
 				}
 			}
 		}
 			// Seting default item
 		if ($this->thisConfig['buttons.'][$buttonId . '.']['defaultItem'] && $items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']]) {
-			$items['none'] = $items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']];
+			$items['none'] = array($items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']][0], 'none');
 			unset($items[$this->thisConfig['buttons.'][$buttonId . '.']['defaultItem']]);
 		}
 			// Setting the JS list of options
-		$JSOptions = '';
-		$index = 0;
+		$itemsJSArray = array();
 		foreach ($items as $option) {
-			$JSOptions .= ($index ? ',' : '') . $option;
-			$index++;
+			$itemsJSArray[] = $option;
 		}
-		$JSOptions = '{'
-			. $JSOptions . '
-		};';
-
+		$itemsJSArray = 'var options = ' . json_encode($itemsJSArray) . ';';
+		
 			// Adding to button JS configuration
 		if (!is_array( $this->thisConfig['buttons.']) || !is_array($this->thisConfig['buttons.'][$buttonId . '.'])) {
 			$configureRTEInJavascriptString .= '
 			RTEarea['.$RTEcounter.'].buttons.'. $buttonId .' = new Object();';
 		}
 		$configureRTEInJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'. $buttonId .'.options = '. $JSOptions;
-
+			RTEarea['.$RTEcounter.'].buttons.'. $buttonId . '.dataUrl = \'' . $this->htmlAreaRTE->writeTemporaryFile('', $buttonId . '_'. $this->htmlAreaRTE->contentLanguageUid, 'js', $itemsJSArray) . '\';';
 		return $configureRTEInJavascriptString;
 	}
 } // end of class
Index: typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/TableOperations/class.tx_rtehtmlarea_tableoperations.php	(copie de travail)
@@ -111,18 +111,20 @@
 			$disabledFieldsets = strtolower(implode(',', $disabledFieldsets));
 
 				// Dialogue fieldsets removal configuration
-			$dialogues = array('table', 'tableproperties', 'rowproperties', 'columnproperties', 'cellproperties');
-			foreach ($dialogues as $dialogue) {
-				if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.'][$dialogue.'.'])) {
-					$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'.$dialogue.' = new Object();
-			RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = "' . $disabledFieldsets . '";';
-				} else if ($this->thisConfig['buttons.'][$dialogue.'.']['removeFieldsets']) {
-					$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets += ",' . $disabledFieldsets . '";';
-				} else {
-					$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = ",' . $disabledFieldsets . '";';
+			if ($disabledFieldsets) {
+				$dialogues = array('table', 'tableproperties', 'rowproperties', 'columnproperties', 'cellproperties');
+				foreach ($dialogues as $dialogue) {
+					if (!is_array( $this->thisConfig['buttons.']) || !is_array( $this->thisConfig['buttons.'][$dialogue.'.'])) {
+						$registerRTEinJavascriptString .= '
+				RTEarea['.$RTEcounter.'].buttons.'.$dialogue.' = new Object();
+				RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = "' . $disabledFieldsets . '";';
+					} else if ($this->thisConfig['buttons.'][$dialogue.'.']['removeFieldsets']) {
+						$registerRTEinJavascriptString .= '
+				RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets += ",' . $disabledFieldsets . '";';
+					} else {
+						$registerRTEinJavascriptString .= '
+				RTEarea['.$RTEcounter.'].buttons.'.$dialogue.'.removeFieldsets = ",' . $disabledFieldsets . '";';
+					}
 				}
 			}
 
Index: typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php	(révision 0)
+++ typo3/sysext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php	(révision 0)
@@ -0,0 +1,66 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  All rights reserved
+*
+*  This script is part of the Typo3 project. The Typo3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Text Indicator plugin for htmlArea RTE
+ *
+ * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
+ *
+ * TYPO3 SVN ID: $Id: class.tx_rtehtmlarea_textindicator.php 5489 2009-05-23 15:26:20Z ohader $
+ *
+ */
+require_once(t3lib_extMgm::extPath('rtehtmlarea').'class.tx_rtehtmlareaapi.php');
+
+class tx_rtehtmlarea_textindicator extends tx_rtehtmlareaapi {
+	protected $extensionKey = 'rtehtmlarea';	// The key of the extension that is extending htmlArea RTE
+	protected $pluginName = 'TextIndicator';	// The name of the plugin registered by the extension
+	protected $relativePathToLocallangFile = '';	// Path to this main locallang file of the extension relative to the extension dir.
+	protected $relativePathToSkin = 'extensions/TextIndicator/skin/htmlarea.css';		// Path to the skin (css) file relative to the extension dir.
+	protected $htmlAreaRTE;				// Reference to the invoking object
+	protected $thisConfig;				// Reference to RTE PageTSConfig
+	protected $toolbar;				// Reference to RTE toolbar array
+	protected $LOCAL_LANG; 				// Frontend language array
+	protected $pluginButtons = 'textindicator';
+	protected $convertToolbarForHtmlAreaArray = array (
+		'textindicator'	=> 'TextIndicator',
+		);
+	/**
+	 * Return JS configuration of the htmlArea plugins registered by the extension
+	 *
+	 * @param	integer		Relative id of the RTE editing area in the form
+	 *
+	 * @return string		JS configuration for registered plugins
+	 *
+	 * The returned string will be a set of JS instructions defining the configuration that will be provided to the plugin(s)
+	 * Each of the instructions should be of the form:
+	 * 	RTEarea['.$RTEcounter.']["buttons"]["button-id"]["property"] = "value";
+	 */
+	public function buildJavascriptConfiguration($RTEcounter) {
+		$registerRTEinJavascriptString = '';
+		return $registerRTEinJavascriptString;
+	}
+}
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php']) {
+	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TextIndicator/class.tx_rtehtmlarea_textindicator.php']);
+}
+?>
\ No newline at end of file
Index: typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css	(révision 0)
+++ typo3/sysext/rtehtmlarea/extensions/TextIndicator/skin/htmlarea.css	(révision 0)
@@ -0,0 +1,9 @@
+/* Selectors for the TextIndicator plugin of htmlArea RTE */
+/* TYPO3 SVN ID: $Id $ */
+.htmlarea .toolbar .indicator {
+	background-color:white;cursor:default;
+	width:20px;overflow:hidden;
+	text-align:center;
+	border:1px solid ButtonShadow;margin:4px 1px 0px 1px;padding:0px 3px;
+	float:left;
+}
Index: typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the Typo3 project. The Typo3 project is
@@ -50,7 +50,7 @@
 		);
 
 	public function main($parentObject) {
-		return parent::main($parentObject) && $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['allowStyleAttribute'] && !$this->thisConfig['disableSelectColor'];
+		return parent::main($parentObject) && $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['allowStyleAttribute'];
 	}
 
 	/**
@@ -80,53 +80,40 @@
 	 * @return	string		Javascript configuration of colors
 	 */
 	function buildJSColorsConfig($RTEcounter) {
-
 		if ($this->htmlAreaRTE->is_FE()) {
 			$RTEProperties = $this->htmlAreaRTE->RTEsetup;
 		} else {
 			$RTEProperties = $this->htmlAreaRTE->RTEsetup['properties'];
 		}
-
 		$configureRTEInJavascriptString = '';
-
 		$configureRTEInJavascriptString .= '
 			RTEarea['.$RTEcounter.'].disableColorPicker = ' . (trim($this->thisConfig['disableColorPicker']) ? 'true' : 'false') . ';';
-
-			// Building JS array of configured colors
+			// Building the array of configured colors
 		if (is_array($RTEProperties['colors.']) )  {
 			$HTMLAreaColorname = array();
 			foreach ($RTEProperties['colors.'] as $colorName => $conf) {
-				$colorName=substr($colorName,0,-1);
-				$colorLabel = $this->htmlAreaRTE->getPageConfigLabel($conf['name']);
-				$HTMLAreaColorname[$colorName] = '
-				[' . $colorLabel . ' , "' . $conf['value'] . '"]';
+				$colorName = substr($colorName, 0, -1);
+				$colorLabel = $this->htmlAreaRTE->getPageConfigLabel($conf['name'], 0);
+				$colorLabel = (!$this->htmlAreaRTE->is_FE() && $this->htmlAreaRTE->TCEform->inline->isAjaxCall) ? $GLOBALS['LANG']->csConvObj->utf8_encode($colorLabel, $GLOBALS['LANG']->charSet) : $colorLabel;
+				$HTMLAreaColorname[$colorName] = array($colorLabel, strtoupper(substr($conf['value'], 1, 6)));
 			}
 		}
-
 			// Setting the list of colors if specified in the RTE config
-		if ($this->thisConfig['colors'] ) {
-			$HTMLAreaJSColors = '[';
+		if ($this->thisConfig['colors']) {
 			$HTMLAreaColors = t3lib_div::trimExplode(',' , $this->htmlAreaRTE->cleanList($this->thisConfig['colors']));
-			$HTMLAreaColorsIndex = 0;
+			$HTMLAreaJSColors = array();
 			foreach ($HTMLAreaColors as $colorName) {
-				if($HTMLAreaColorsIndex && $HTMLAreaColorname[$colorName]) {
-					$HTMLAreaJSColors .= ',';
+				if ($HTMLAreaColorname[$colorName]) {
+					$HTMLAreaJSColors[] = $HTMLAreaColorname[$colorName];
 				}
-				$HTMLAreaJSColors .= $HTMLAreaColorname[$colorName];
-				$HTMLAreaColorsIndex++;
 			}
-			$HTMLAreaJSColors .= '];';
 			$configureRTEInJavascriptString .= '
-			RTEarea['.$RTEcounter.'].colors = '. $HTMLAreaJSColors;
+			RTEarea['.$RTEcounter.'].colors = ' . json_encode($HTMLAreaJSColors) . ';';
 		}
-
 		return $configureRTEInJavascriptString;
 	}
-
-} // end of class
-
+}
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php']) {
 	include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/extensions/TYPO3Color/class.tx_rtehtmlarea_typo3color.php']);
 }
-
 ?>
\ No newline at end of file
Index: typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php
===================================================================
--- typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/extensions/TYPO3Link/class.tx_rtehtmlarea_typo3link.php	(copie de travail)
@@ -87,10 +87,8 @@
 				$registerRTEinJavascriptString .= '
 			RTEarea['.$RTEcounter.'].buttons.'. $button .'.classesAnchorUrl = "' . $this->htmlAreaRTE->writeTemporaryFile('', 'classesAnchor_'.$this->htmlAreaRTE->contentLanguageUid, 'js', $this->buildJSClassesAnchorArray()) . '";';
 			}
-			if ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes']) {
-				$registerRTEinJavascriptString .= '
-			RTEarea['.$RTEcounter.'].buttons.'. $button .'.additionalAttributes = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] .'";';
-			}
+			$registerRTEinJavascriptString .= '
+			RTEarea['.$RTEcounter.'].buttons.'. $button .'.additionalAttributes = "external' . ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes'] ? (',' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->extensionKey]['plugins'][$this->pluginName]['additionalAttributes']) : '') . '";';
 		}
 		return $registerRTEinJavascriptString;
 	}
Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js	(copie de travail)
@@ -3,7 +3,7 @@
 *
 *  (c) 2002-2004 interactivetools.com, inc.
 *  (c) 2003-2004 dynarch.com
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -35,71 +35,24 @@
 /***************************************************
  *  GECKO-SPECIFIC FUNCTIONS
  ***************************************************/
-HTMLArea.prototype.isEditable = function() {
+HTMLArea.Editor.prototype.isEditable = function() {
 	return (this._doc.designMode === "on");
 };
-
 /***************************************************
- *  MOZILLA/FIREFOX EDIT MODE INITILIZATION
- ***************************************************/
-
-HTMLArea.prototype._initEditMode = function () {
-		// We can't set designMode when we are in a hidden TYPO3 tab
-		// Then we will set it when the tab comes in the front.
-	var isNested = false;
-	var allDisplayed = true;
-
-	if (this.nested.sorted && this.nested.sorted.length) {
-		isNested = true;
-		allDisplayed = HTMLArea.allElementsAreDisplayed(this.nested.sorted);
-	}
-	if (!isNested || allDisplayed) {
-		try {
-			this._iframe.style.display = "block";
-			this._doc.designMode = "on";
-			if (this._doc.queryCommandEnabled("insertbronreturn")) this._doc.execCommand("insertbronreturn", false, this.config.disableEnterParagraphs);
-			if (this._doc.queryCommandEnabled("enableObjectResizing")) this._doc.execCommand("enableObjectResizing", false, !this.config.disableObjectResizing);
-			if (this._doc.queryCommandEnabled("enableInlineTableEditing")) this._doc.execCommand("enableInlineTableEditing", false, (this.config.buttons.table && this.config.buttons.table.enableHandles) ? true : false);
-			if (this._doc.queryCommandEnabled("styleWithCSS")) this._doc.execCommand("styleWithCSS", false, this.config.useCSS);
-				else if (this._doc.queryCommandEnabled("useCSS")) this._doc.execCommand("useCSS", false, !this.config.useCSS);
-		} catch(e) {
-			if (HTMLArea.is_wamcom) {
-				this._doc.open();
-				this._doc.close();
-				this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(\'" + this._editorNumber + "\');", 500);
-				return false;
-			}
-		}
-	}
-		// When the TYPO3 TCA feature div2tab is used, the editor iframe may become hidden with style.display = "none"
-		// This breaks the editor in Mozilla/Firefox browsers: the designMode attribute needs to be resetted after the style.display of the containing div is resetted to "block"
-		// Here we rely on TYPO3 naming conventions for the div id and class name
-	if (this.nested.sorted && this.nested.sorted.length) {
-		var nestedObj, listenerFunction;
-		for (var i=0, length=this.nested.sorted.length; i < length; i++) {
-			nestedObj = document.getElementById(this.nested.sorted[i]);
-			listenerFunction = HTMLArea.NestedListener(this, nestedObj, false);
-			HTMLArea._addEvent(nestedObj, 'DOMAttrModified', listenerFunction);
-		}
-	}
-	return true;
-};
-
-/***************************************************
  *  SELECTIONS AND RANGES
  ***************************************************/
 
 /*
  * Get the current selection object
  */
-HTMLArea.prototype._getSelection = function() {
+HTMLArea.Editor.prototype._getSelection = function() {
 	return this._iframe.contentWindow.getSelection();
 };
 
 /*
  * Empty the selection object
  */
-HTMLArea.prototype.emptySelection = function(selection) {
+HTMLArea.Editor.prototype.emptySelection = function(selection) {
 	if (HTMLArea.is_safari) {
 		selection.empty();
 	} else {
@@ -113,7 +66,7 @@
 /*
  * Add a range to the selection
  */
-HTMLArea.prototype.addRangeToSelection = function(selection, range) {
+HTMLArea.Editor.prototype.addRangeToSelection = function(selection, range) {
 	if (HTMLArea.is_safari) {
 		selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset);
 	} else {
@@ -124,7 +77,7 @@
 /*
  * Create a range for the current selection
  */
-HTMLArea.prototype._createRange = function(sel) {
+HTMLArea.Editor.prototype._createRange = function(sel) {
 	if (HTMLArea.is_safari) {
 		var range = this._doc.createRange();
 		if (typeof(sel) == "undefined") {
@@ -143,7 +96,9 @@
 			return range;
 		}
 	}
-	if (typeof(sel) == "undefined") return this._doc.createRange();
+	if (Ext.isEmpty(sel)) {
+		return this._doc.createRange();
+	}
 	try {
 		return sel.getRangeAt(0);
 	} catch(e) {
@@ -154,7 +109,7 @@
 /*
  * Select a node AND the contents inside the node
  */
-HTMLArea.prototype.selectNode = function(node, endPoint) {
+HTMLArea.Editor.prototype.selectNode = function(node, endPoint) {
 	this.focusEditor();
 	var selection = this._getSelection();
 	var range = this._doc.createRange();
@@ -173,7 +128,7 @@
 /*
  * Select ONLY the contents inside the given node
  */
-HTMLArea.prototype.selectNodeContents = function(node, endPoint) {
+HTMLArea.Editor.prototype.selectNodeContents = function(node, endPoint) {
 	this.focusEditor();
 	var selection = this._getSelection();
 	var range = this._doc.createRange();
@@ -185,7 +140,7 @@
 	this.addRangeToSelection(selection, range);
 };
 
-HTMLArea.prototype.rangeIntersectsNode = function(range, node) {
+HTMLArea.Editor.prototype.rangeIntersectsNode = function(range, node) {
 	var nodeRange = this._doc.createRange();
 	try {
 		nodeRange.selectNode(node);
@@ -200,7 +155,7 @@
 /*
  * Get the selection type
  */
-HTMLArea.prototype.getSelectionType = function(selection) {
+HTMLArea.Editor.prototype.getSelectionType = function(selection) {
 		// By default set the type to "Text".
 	var type = "Text";
 	if (!selection) {
@@ -222,7 +177,7 @@
 /*
  * Retrieves the selected element (if any), just in the case that a single element (object like and image or a table) is selected.
  */
-HTMLArea.prototype.getSelectedElement = function(selection) {
+HTMLArea.Editor.prototype.getSelectedElement = function(selection) {
 	var selectedElement = null;
 	if (!selection) {
 		var selection = this._getSelection();
@@ -244,7 +199,7 @@
 /*
  * Retrieve the HTML contents of selected block
  */
-HTMLArea.prototype.getSelectedHTML = function() {
+HTMLArea.Editor.prototype.getSelectedHTML = function() {
 	var range = this._createRange(this._getSelection());
 	if (range.collapsed) return "";
 	var cloneContents = range.cloneContents();
@@ -257,14 +212,14 @@
 /*
  * Retrieve simply HTML contents of the selected block, IE ignoring control ranges
  */
-HTMLArea.prototype.getSelectedHTMLContents = function() {
+HTMLArea.Editor.prototype.getSelectedHTMLContents = function() {
 	return this.getSelectedHTML();
 };
 
 /*
  * Get the deepest node that contains both endpoints of the current selection.
  */
-HTMLArea.prototype.getParentElement = function(selection, range) {
+HTMLArea.Editor.prototype.getParentElement = function(selection, range) {
 	if (!selection) {
 		var selection = this._getSelection();
 	}
@@ -290,7 +245,7 @@
  * @returns null | element
  * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
  */
-HTMLArea.prototype._activeElement = function(selection) {
+HTMLArea.Editor.prototype._activeElement = function(selection) {
 	if (this._selectionEmpty(selection)) {
 		return null;
 	}
@@ -305,7 +260,7 @@
 /*
  * Determine if the current selection is empty or not.
  */
-HTMLArea.prototype._selectionEmpty = function(sel) {
+HTMLArea.Editor.prototype._selectionEmpty = function(sel) {
 	if (!sel) return true;
 	return sel.isCollapsed;
 };
@@ -317,7 +272,7 @@
  * in the range boundaries. The advantage of it is that it is possible to
  * handle DOM mutations when moving back to the bookmark.
  */
-HTMLArea.prototype.getBookmark = function (range) {
+HTMLArea.Editor.prototype.getBookmark = function (range) {
 		// Create the bookmark info (random IDs).
 	var bookmark = {
 		startId : (new Date()).valueOf() + Math.floor(Math.random()*1000) + 'S',
@@ -364,7 +319,7 @@
  * Get the end point of the bookmark
  * Adapted from FCKeditor
  */
-HTMLArea.prototype.getBookmarkNode = function(bookmark, endPoint) {
+HTMLArea.Editor.prototype.getBookmarkNode = function(bookmark, endPoint) {
 	if (endPoint) {
 		return this._doc.getElementById(bookmark.startId);
 	} else {
@@ -376,7 +331,7 @@
  * Move the range to the bookmark
  * Adapted from FCKeditor
  */
-HTMLArea.prototype.moveToBookmark = function (bookmark) {
+HTMLArea.Editor.prototype.moveToBookmark = function (bookmark) {
 	var startSpan  = this.getBookmarkNode(bookmark, true);
 	var endSpan    = this.getBookmarkNode(bookmark, false);
 
@@ -406,7 +361,7 @@
 /*
  * Select range
  */
-HTMLArea.prototype.selectRange = function (range) {
+HTMLArea.Editor.prototype.selectRange = function (range) {
 	var selection = this._getSelection();
 	this.emptySelection(selection);
 	this.addRangeToSelection(selection, range);
@@ -421,7 +376,7 @@
  * Delete the current selection, if any.
  * Split the text node, if needed.
  */
-HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+HTMLArea.Editor.prototype.insertNodeAtSelection = function(toBeInserted) {
 	this.focusEditor();
 	var range = this._createRange(this._getSelection());
 	range.deleteContents();
@@ -434,7 +389,7 @@
  * Insert HTML source code at the current position.
  * Delete the current selection, if any.
  */
-HTMLArea.prototype.insertHTML = function(html) {
+HTMLArea.Editor.prototype.insertHTML = function(html) {
 	this.focusEditor();
 	var fragment = this._doc.createDocumentFragment();
 	var div = this._doc.createElement("div");
@@ -454,7 +409,7 @@
  *
  * @return	void
  */
-HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) {
+HTMLArea.Editor.prototype.wrapWithInlineElement = function(element, selection, range) {
 		// Sometimes Opera raises a bad boundary points error
 	if (HTMLArea.is_opera) {
 		try {
@@ -486,7 +441,7 @@
  *
  * @return	void
  */
-HTMLArea.prototype.cleanAppleStyleSpans = function(node) {
+HTMLArea.Editor.prototype.cleanAppleStyleSpans = function(node) {
 	if (HTMLArea.is_safari) {
 		if (node.getElementsByClassName) {
 			var spans = node.getElementsByClassName("Apple-style-span");
@@ -513,62 +468,10 @@
 /***************************************************
  *  EVENTS HANDLERS
  ***************************************************/
-
 /*
- * TYPO3 hidden tab and inline event listener (gets event calls)
- */
-HTMLArea.NestedListener = function (editor,nestedObj,noOpenCloseAction) {
-	return (function(ev) {
-		if(!ev) var ev = window.event;
-		HTMLArea.NestedHandler(ev,editor,nestedObj,noOpenCloseAction);
-	});
-};
-
-/*
- * TYPO3 hidden tab and inline event handler (performs actions on event calls)
- */
-HTMLArea.NestedHandler = function(ev,editor,nestedObj,noOpenCloseAction) {
-	window.setTimeout(function() {
-		var target = (ev.target) ? ev.target : ev.srcElement, styleEvent = true;
-			// In older versions of Mozilla ev.attrName is not yet set and refering to it causes a non-catchable crash
-			// We are assuming that this was fixed in Firefox 2.0.0.11
-		if (navigator.productSub > 20071127) {
-			styleEvent = (ev.attrName == "style");
-		}
-		if (target == nestedObj && editor.getMode() == "wysiwyg" && styleEvent && (target.style.display == "" || target.style.display == "block")) {
-				// Check if all affected nested elements are displayed (style.display!='none'):
-			if (HTMLArea.allElementsAreDisplayed(editor.nested.sorted)) {
-				window.setTimeout(function() {
-					try {
-						editor._doc.designMode = "on";
-						if (editor.config.sizeIncludesToolbar && editor._initialToolbarOffsetHeight != editor._toolbar.offsetHeight) {
-							editor.sizeIframe(2);
-						}
-						if (editor._doc.queryCommandEnabled("insertbronreturn")) editor._doc.execCommand("insertbronreturn", false, editor.config.disableEnterParagraphs);
-						if (editor._doc.queryCommandEnabled("enableObjectResizing")) editor._doc.execCommand("enableObjectResizing", false, !editor.config.disableObjectResizing);
-						if (editor._doc.queryCommandEnabled("enableInlineTableEditing")) editor._doc.execCommand("enableInlineTableEditing", false, (editor.config.buttons.table && editor.config.buttons.table.enableHandles) ? true : false);
-						if (editor._doc.queryCommandEnabled("styleWithCSS")) editor._doc.execCommand("styleWithCSS", false, editor.config.useCSS);
-							else if (editor._doc.queryCommandEnabled("useCSS")) editor._doc.execCommand("useCSS", false, !editor.config.useCSS);
-					} catch(e) {
-							// If an event of a parent tab ("nested tabs") is triggered, the following lines should not be
-							// processed, because this causes some trouble on all event handlers...
-						if (!noOpenCloseAction) {
-							editor._doc.open();
-							editor._doc.close();
-						}
-						editor.initIframe();
-					}
-				}, 50);
-			}
-			HTMLArea._stopEvent(ev);
-		}
-	}, 50);
-};
-
-/*
  * Backspace event handler
  */
-HTMLArea.prototype._checkBackspace = function() {
+HTMLArea.Editor.prototype._checkBackspace = function() {
 	if (!HTMLArea.is_safari && !HTMLArea.is_opera) {
 		var self = this;
 		window.setTimeout(function() {
@@ -609,7 +512,7 @@
 /*
  * Enter event handler
  */
-HTMLArea.prototype._checkInsertP = function() {
+HTMLArea.Editor.prototype._checkInsertP = function() {
 	var editor = this;
 	this.focusEditor();
 	var i, left, right, rangeClone,
@@ -742,7 +645,8 @@
  * Detect emails and urls as they are typed in Mozilla
  * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
  */
-HTMLArea.prototype._detectURL = function(ev) {
+HTMLArea.Editor.prototype._detectURL = function(event) {
+	var ev = event.browserEvent;
 	var editor = this;
 	var s = this._getSelection();
 	if (this.getParentElement(s).nodeName.toLowerCase() != 'a') {
@@ -754,7 +658,7 @@
 			a.appendChild(textNode);
 			rightText.data += " ";
 			s.collapse(rightText, rightText.data.length);
-			HTMLArea._stopEvent(ev);
+			event.stopEvent();
 	
 			editor._unLink = function() {
 				var t = a.firstChild;
@@ -809,7 +713,7 @@
 				if(ev.keyCode == 27 || (editor._unlinkOnUndo && ev.ctrlKey && ev.which == 122) ) {
 					if(this._unLink) {
 						this._unLink();
-						HTMLArea._stopEvent(ev);
+						event.stopEvent();
 					}
 					break;
 				} else if(ev.which || ev.keyCode == 8 || ev.keyCode == 46) {
Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-ie.js	(copie de travail)
@@ -3,7 +3,7 @@
 *
 *  (c) 2002-2004 interactivetools.com, inc.
 *  (c) 2003-2004 dynarch.com
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -35,7 +35,7 @@
 /***************************************************
  *  IE-SPECIFIC FUNCTIONS
  ***************************************************/
-HTMLArea.prototype.isEditable = function() {
+HTMLArea.Editor.prototype.isEditable = function() {
 	return this._doc.body.contentEditable;
 };
 
@@ -45,14 +45,14 @@
 /*
  * Get the current selection object
  */
-HTMLArea.prototype._getSelection = function() {
+HTMLArea.Editor.prototype._getSelection = function() {
 	return this._doc.selection;
 };
 
 /*
  * Create a range for the current selection
  */
-HTMLArea.prototype._createRange = function(sel) {
+HTMLArea.Editor.prototype._createRange = function(sel) {
 	if (typeof(sel) == "undefined") {
 		var sel = this._getSelection();
 	}
@@ -65,7 +65,7 @@
 /*
  * Select a node AND the contents inside the node
  */
-HTMLArea.prototype.selectNode = function(node) {
+HTMLArea.Editor.prototype.selectNode = function(node) {
 	this.focusEditor();
 	this.forceRedraw();
 	var range = this._doc.body.createTextRange();
@@ -76,7 +76,7 @@
 /*
  * Select ONLY the contents inside the given node
  */
-HTMLArea.prototype.selectNodeContents = function(node, endPoint) {
+HTMLArea.Editor.prototype.selectNodeContents = function(node, endPoint) {
 	this.focusEditor();
 	this.forceRedraw();
 	var range = this._doc.body.createTextRange();
@@ -90,7 +90,7 @@
 /*
  * Determine whether the node intersects the range
  */
-HTMLArea.prototype.rangeIntersectsNode = function(range, node) {
+HTMLArea.Editor.prototype.rangeIntersectsNode = function(range, node) {
 	this.focusEditor();
 	var nodeRange = this._doc.body.createTextRange();
 	nodeRange.moveToElementText(node);
@@ -101,7 +101,7 @@
 /*
  * Retrieve the HTML contents of selected block
  */
-HTMLArea.prototype.getSelectedHTML = function() {
+HTMLArea.Editor.prototype.getSelectedHTML = function() {
 	var sel = this._getSelection();
 	var range = this._createRange(sel);
 	if (sel.type.toLowerCase() == "control") {
@@ -116,7 +116,7 @@
 /*
  * Retrieve simply HTML contents of the selected block, IE ignoring control ranges
  */
-HTMLArea.prototype.getSelectedHTMLContents = function() {
+HTMLArea.Editor.prototype.getSelectedHTMLContents = function() {
 	var sel = this._getSelection();
 	var range = this._createRange(sel);
 	return range.htmlText;
@@ -125,7 +125,7 @@
 /*
  * Get the deepest node that contains both endpoints of the current selection.
  */
-HTMLArea.prototype.getParentElement = function(selection, range) {
+HTMLArea.Editor.prototype.getParentElement = function(selection, range) {
 	if (!selection) {
 		var selection = this._getSelection();
 	}
@@ -150,7 +150,7 @@
  * @returns null | element
  * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
  */
-HTMLArea.prototype._activeElement = function(sel) {
+HTMLArea.Editor.prototype._activeElement = function(sel) {
 	if (sel == null) {
 		return null;
 	}
@@ -172,7 +172,7 @@
 /*
  * Determine if the current selection is empty or not.
  */
-HTMLArea.prototype._selectionEmpty = function(selection) {
+HTMLArea.Editor.prototype._selectionEmpty = function(selection) {
 	if (!selection || selection.type.toLowerCase() === "none") return true;
 	if (selection.type.toLowerCase() === "text") {
 		return !this._createRange(selection).text;
@@ -183,14 +183,14 @@
 /*
  * Get a bookmark
  */
-HTMLArea.prototype.getBookmark = function (range) {
+HTMLArea.Editor.prototype.getBookmark = function (range) {
 	return range.getBookmark();
 };
 
 /*
  * Move the range to the bookmark
  */
-HTMLArea.prototype.moveToBookmark = function (bookmark) {
+HTMLArea.Editor.prototype.moveToBookmark = function (bookmark) {
 	var range = this._createRange();
 	range.moveToBookmark(bookmark);
 	return range;
@@ -199,7 +199,7 @@
 /*
  * Select range
  */
-HTMLArea.prototype.selectRange = function (range) {
+HTMLArea.Editor.prototype.selectRange = function (range) {
 	range.select();
 };
 /***************************************************
@@ -211,7 +211,7 @@
  * Delete the current selection, if any.
  * Split the text node, if needed.
  */
-HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+HTMLArea.Editor.prototype.insertNodeAtSelection = function(toBeInserted) {
 	this.insertHTML(toBeInserted.outerHTML);
 };
 
@@ -219,7 +219,7 @@
  * Insert HTML source code at the current position.
  * Delete the current selection, if any.
  */
-HTMLArea.prototype.insertHTML = function(html) {
+HTMLArea.Editor.prototype.insertHTML = function(html) {
 	var sel = this._getSelection();
 	if (sel.type.toLowerCase() == "control") {
 		sel.clear();
@@ -238,7 +238,7 @@
  *
  * @return	void
  */
-HTMLArea.prototype.wrapWithInlineElement = function(element, selection, range) {
+HTMLArea.Editor.prototype.wrapWithInlineElement = function(element, selection, range) {
 	var nodeName = element.nodeName;
 	var parent = this.getParentElement(selection, range);
 	var bookmark = this.getBookmark(range);
@@ -312,7 +312,7 @@
 /*
  * Handle the backspace event in IE browsers
  */
-HTMLArea.prototype._checkBackspace = function() {
+HTMLArea.Editor.prototype._checkBackspace = function() {
 	var selection = this._getSelection();
 	var range = this._createRange(selection);
 	if (selection.type == "Control"){ // Deleting or backspacing on a control selection : delete the element
Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js	(copie de travail)
@@ -3,7 +3,7 @@
 *
 *  (c) 2002-2004 interactivetools.com, inc.
 *  (c) 2003-2004 dynarch.com
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -33,46 +33,22 @@
  *
  * TYPO3 SVN ID: $Id$
  */
-
+	// Avoid re-starting on Ajax request
+if (typeof(HTMLArea) == 'undefined') {
+	// Establish HTMLArea name space
+Ext.namespace('HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar');
 /***************************************************
- *  EDITOR INITIALIZATION AND CONFIGURATION
+ *  BROWSER IDENTIFICATION
  ***************************************************/
-	// Avoid re-starting on Ajax request
-if (typeof(HTMLArea) != "function") {
-
-/*
- * HTMLArea object constructor.
- */
-HTMLArea = function(textarea, config) {
-	if (HTMLArea.checkSupportedBrowser()) {
-		if (typeof(config) == "undefined") this.config = new HTMLArea.Config();
-			else this.config = config;
-		this._htmlArea = null;
-		this._textArea = textarea;
-		if (typeof(this._textArea) == "string") {
-			this._textArea = HTMLArea.getElementById("textarea", this._textArea);
-		}
-		this.plugins = {};
-		this._timerToolbar = null;
-		this.doctype = '';
-		this.eventHandlers = {};
-	}
-};
-
-/*
- * Browser identification
- */
 HTMLArea.agt = navigator.userAgent.toLowerCase();
-HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
+HTMLArea.is_opera  = Ext.isOpera;
 // Some operations require bug fixes provided by Opera 10 (Presto 2.2)
-HTMLArea.is_opera9 = HTMLArea.is_opera && HTMLArea.agt.indexOf("Presto/2.1") != -1;
-HTMLArea.is_ie = (HTMLArea.agt.indexOf("msie") != -1) && !HTMLArea.is_opera;
-HTMLArea.is_safari = (HTMLArea.agt.indexOf("webkit") != -1);
-HTMLArea.is_gecko  = (navigator.product == "Gecko") || HTMLArea.is_opera;
-HTMLArea.is_ff2 = (HTMLArea.agt.indexOf("firefox/2") != -1);
-HTMLArea.is_chrome = HTMLArea.is_safari && (HTMLArea.agt.indexOf("chrome") != -1);
-// Check on MacOS Wamcom version 1.3, if Mozilla will check earliest supported build in checkSupportedBrowser()
-HTMLArea.is_wamcom = (HTMLArea.agt.indexOf("wamcom") != -1) || (HTMLArea.is_gecko && HTMLArea.agt.indexOf("rv:1.3") != -1);
+HTMLArea.is_opera9 = Ext.isOpera && HTMLArea.agt.indexOf("Presto/2.1") != -1;
+HTMLArea.is_ie = Ext.isIE;
+HTMLArea.is_safari = Ext.isWebKit;
+HTMLArea.is_gecko  = Ext.isGecko || Ext.isOpera || Ext.isWebKit;
+HTMLArea.is_ff2 = Ext.isGecko2;
+HTMLArea.is_chrome = Ext.isChrome;
 
 /*
  * A log for troubleshooting
@@ -86,7 +62,9 @@
 		}
 	}
 };
-
+/***************************************************
+ *  SCRIPTS LOADING PROCESS
+ ***************************************************/
 /*
  * Build stack of scripts to be loaded
  */
@@ -97,7 +75,7 @@
 	if (typeof(asynchronous) == "undefined") {
 		var asynchronous = true;
 	}
-	if (HTMLArea.is_opera) url = _typo3_host_url + url;
+	if (Ext.isOpera) url = _typo3_host_url + url;
 	if (HTMLArea._compressedScripts && url.indexOf("compressed") == -1) url = url.replace(/\.js$/gi, "_compressed.js");
 	var scriptInfo = {
 		pluginName	: pluginName,
@@ -202,8 +180,6 @@
 		if (typeof(_editor_edited_content_CSS) != "string") _editor_edited_content_CSS = _editor_skin + "htmlarea-edited-content.css";
 		if (typeof(_editor_lang) == "string") _editor_lang = _editor_lang ? _editor_lang.toLowerCase() : "en";
 		HTMLArea.editorCSS = _editor_CSS;
-			// Initialize event cache
-		HTMLArea._eventCache = HTMLArea._eventCacheConstructor();
 			// Initialize pending request flag
 		HTMLArea.pendingSynchronousXMLHttpRequest = false;
 			// Set troubleshooting mode
@@ -220,8 +196,8 @@
 		HTMLArea._scripts = [];
 		HTMLArea._scriptLoaded = [];
 		HTMLArea._request = [];
-		if (HTMLArea.is_gecko) HTMLArea.loadScript(RTEarea[0]["htmlarea-gecko"] ? RTEarea[0]["htmlarea-gecko"] : _editor_url + "htmlarea-gecko.js");
-		if (HTMLArea.is_ie) HTMLArea.loadScript(RTEarea[0]["htmlarea-ie"] ? RTEarea[0]["htmlarea-ie"] : _editor_url + "htmlarea-ie.js");
+		if (!Ext.isIE) HTMLArea.loadScript(RTEarea[0]["htmlarea-gecko"] ? RTEarea[0]["htmlarea-gecko"] : _editor_url + "htmlarea-gecko.js");
+		if (Ext.isIE) HTMLArea.loadScript(RTEarea[0]["htmlarea-ie"] ? RTEarea[0]["htmlarea-ie"] : _editor_url + "htmlarea-ie.js");
 		for (var i = 0, n = HTMLArea_plugins.length; i < n; i++) {
 			HTMLArea.loadScript(HTMLArea_plugins[i].url, "", HTMLArea_plugins[i].asynchronous);
 		}
@@ -247,10 +223,10 @@
 			if (success) {
 				HTMLArea.checkInitialLoad();
 			} else {
-				if (HTMLArea.is_ie) window.setTimeout('alert(HTMLArea.I18N.msg["ActiveX-required"]);', 200);
+				if (Ext.isIE) window.setTimeout('alert(HTMLArea.I18N.msg["ActiveX-required"]);', 200);
 			}
 		} else {
-			if (HTMLArea.is_ie) alert(HTMLArea.I18N.msg["ActiveX-required"]);
+			if (Ext.isIE) alert(HTMLArea.I18N.msg["ActiveX-required"]);
 		}
 	}
 };
@@ -259,25 +235,17 @@
  * Compile some regular expressions
  */
 HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
-HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
 HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
 HTMLArea.RE_body    = /<body>((.|\n)*?)<\/body>/i;
 HTMLArea.Reg_body = new RegExp("<\/?(body)[^>]*>", "gi");
 HTMLArea.reservedClassNames = /htmlarea/;
 HTMLArea.RE_email    = /([0-9a-z]+([a-z0-9_-]*[0-9a-z])*){1}(\.[0-9a-z]+([a-z0-9_-]*[0-9a-z])*)*@([0-9a-z]+([a-z0-9_-]*[0-9a-z])*\.)+[a-z]{2,9}/i;
 HTMLArea.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+\.[a-z]{2,5}(:[0-9]+)?(\/\S+)*)/i;
-
-/*
- * Editor configuration object constructor
- */
-
-HTMLArea.Config = function () {
-	this.width = "auto";
-	this.height = "auto";
-		// whether the toolbar should be included in the size or not.
-	this.sizeIncludesToolbar = true;
-		// if true then HTMLArea will retrieve the full HTML, starting with the <HTML> tag.
-	this.fullPage = false;
+/***************************************************
+ *  EDITOR CONFIGURATION
+ ***************************************************/
+HTMLArea.Config = function (editorId) {
+	this.editorId = editorId;
 		// if the site is secure, create a secure iframe
 	this.useHTTPS = false;
 		// for Mozilla
@@ -300,7 +268,9 @@
 	this.customTags = null;
 		// BaseURL included in the iframe document
 	this.baseURL = document.baseURI || document.URL;
-	if(this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/)) this.baseURL = RegExp.$1 + "/";
+	if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/)) {
+		this.baseURL = RegExp.$1 + "/";
+	}
 		// URL-s
 	this.imgURL = "images/";
 	this.popupURL = "popups/";
@@ -308,1089 +278,2035 @@
 	this.documentType = '<!DOCTYPE html\r'
 			+ '    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\r'
 			+ '    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r';
-
-	this.btnList = {
-		InsertHorizontalRule:	["Horizontal Rule", "ed_hr.gif",false, function(editor) {editor.execCommand("InsertHorizontalRule");}],
-		SelectAll:		["SelectAll", "", true, function(editor) {editor.execCommand("SelectAll");}, null, true, false]
+	this.resizable = TYPO3.settings.textareaResize;
+	this.maxHeight = TYPO3.settings.textareaMaxHeight;
+		// Hold the configuration of buttons and hot keys registered by plugins
+	this.buttonsConfig = {};
+	this.hotKeyList = {};
+		// Default configurations for toolbar items
+	this.configDefaults = {
+		all: {
+			xtype: 'htmlareabutton',
+			disabledClass: 'buttonDisabled',
+			textMode: false,
+			selection: false,
+			dialog: false,
+			hidden: false,
+			hideMode: 'display'
+		},
+		htmlareabutton: {
+			cls: 'button',
+			overCls: 'buttonHover'
+		},
+		htmlareacombo: {
+			cls: 'select',
+			typeAhead: true,
+			triggerAction: 'all',
+			editable: !Ext.isIE,
+			validationEvent: false,
+			validateOnBlur: false,
+			submitValue: false,
+			forceSelection: true,
+			mode: 'local',
+			storeFields: [ { name: 'text'}, { name: 'value'}],
+			valueField: 'value',
+			displayField: 'text',
+			labelSeparator: '',
+			hideLabel: true,
+			tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+		}
 	};
-		// Default hotkeys
-	this.hotKeyList = {
-		a:	{ cmd:	"SelectAll", 	action:	null}
-	};
-
-		// Initialize tooltips from the I18N module, generate correct image path
-	for (var buttonId in this.btnList) {
-		if (this.btnList.hasOwnProperty(buttonId)) {
-			var btn = this.btnList[buttonId];
-			if (typeof(HTMLArea.I18N.tooltips[buttonId.toLowerCase()]) !== "undefined") {
-				btn[0] = HTMLArea.I18N.tooltips[buttonId.toLowerCase()];
-			}
-			if (typeof(btn[1]) === "string") {
-				btn[1] = _editor_skin + this.imgURL + btn[1];
-			} else {
-				btn[1][0] = _editor_skin + this.imgURL + btn[1][0];
-			}
+};
+HTMLArea.Config = Ext.extend(HTMLArea.Config, {
+	/**
+	 * Registers a button for inclusion in the toolbar, adding some standard configuration properties for the ExtJS widgets
+	 *
+	 * @param	object		buttonConfiguration: the configuration object of the button:
+	 *					id		: unique id for the button
+	 *					tooltip		: tooltip for the button
+	 *					textMode	: enable in text mode
+	 *					context		: disable if not inside one of listed elements
+	 *					hidden		: hide in menu and show only in context menu
+	 *					selection	: disable if there is no selection
+	 *					hotkey		: hotkey character
+	 *					dialog		: if true, the button opens a dialogue
+	 *					dimensions	: the opening dimensions object of the dialogue window: { width: nn, height: mm }
+	 *					and potentially other ExtJS config properties (will be forwarded)
+	 *
+	 * @return	boolean		true if the button was successfully registered
+	 */
+	registerButton: function (config) {
+		config.itemId = config.id;
+		if (Ext.type(this.buttonsConfig[config.id])) {
+			HTMLArea._appendToLog('[HTMLArea.Config::registerButton]: A toolbar item with the same Id: ' + config.id + ' already exists and will be overidden.');
 		}
+			// Apply defaults
+		config = Ext.applyIf(config, this.configDefaults['all']);
+		config = Ext.applyIf(config, this.configDefaults[config.xtype]);
+			// Set some additional properties
+		switch (config.xtype) {
+			case 'htmlareacombo':
+					// Create combo store
+				config.store = new Ext.data.ArrayStore({
+					autoDestroy:  true,
+					fields: config.storeFields,
+					data: config.options
+				});
+				config.hideLabel = Ext.isEmpty(config.fieldLabel);
+				config.helpTitle = config.tooltip;
+				break;
+			default:
+				config.iconCls = config.id;
+				break;
+		}
+		config.cmd = config.id;
+		config.tooltip = { title: config.tooltip };
+		this.buttonsConfig[config.id] = config;
+		return true;
+	},
+	/*
+	 * Register a hotkey with the editor configuration.
+	 */
+	registerHotKey: function (hotKeyConfiguration) {
+		if (Ext.isDefined(this.hotKeyList[hotKeyConfiguration.id])) {
+			HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with the same key ' + hotKeyConfiguration.id + ' already exists and will be overidden.');
+		}
+		if (Ext.isDefined(hotKeyConfiguration.cmd) && !Ext.isEmpty(hotKeyConfiguration.cmd) && Ext.isDefined(this.buttonsConfig[hotKeyConfiguration.cmd])) {
+			this.hotKeyList[hotKeyConfiguration.id] = hotKeyConfiguration;
+			HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with key ' + hotKeyConfiguration.id + ' was registered for toolbar item ' + hotKeyConfiguration.cmd + '.');
+			return true;
+		} else {
+			HTMLArea._appendToLog('[HTMLArea.Config::registerHotKey]: A hotkey with key ' + hotKeyConfiguration.id + ' could not be registered because toolbar item with id ' + hotKeyConfiguration.cmd + ' was not registered.');
+			return false;
+		}
+	},
+	/*
+	 * Get the configured document type for dialogue windows
+	 */
+	getDocumentType: function () {
+		return this.documentType;
 	}
-	this.customSelects = {};
-};
-
-/*
- * Register a new button with the configuration.
- * It can be called with all arguments, or with only one (first one).  When called with
- * only one argument it must be an object with the following properties:
- * id, tooltip, image, textMode, action, context.  Examples:
- *
- * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...}, context);
- * 2. config.registerButton({
- *	id		: "my-hilite",		// Unique id for the button
- *	tooltip		: "Hilite text",	// the tooltip
- *	image		: "my-hilite.gif",	// image to be displayed in the toolbar
- *	textMode	: false,		// disabled in text mode
- *	action		: function(editor) {	// called when the button is clicked
- *				editor.surroundHTML('<span class="hilite">', '</span>');
- *				},
- *	context		: "p"			// will be disabled if not inside a <p> element
- *	hide		: false			// hide in menu and show only in context menu
- *	selection	: false			// will be disabled if there is no selection
- *	dialog		: true			// the button opens a dialogue
- *	dimensions	: { width: nn, height: mm } // opening dimensions of the dialogue window
- *    });
- */
-HTMLArea.Config.prototype.registerButton = function(id,tooltip,image,textMode,action,context,hide,selection, dialog, dimensions) {
-	var buttonId;
-	switch (typeof(id)) {
-		case "string": buttonId = id; break;
-		case "object": buttonId = id.id; break;
-		default: HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: invalid arguments");
-			 return false;
-	}
-	if (typeof(this.customSelects[buttonId]) !== "undefined") {
-		HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: A dropdown with the same Id: " + buttonId + " already exists.");
-		return false;
-	}
-	if (typeof(this.btnList[buttonId]) !== "undefined") {
-		HTMLArea._appendToLog("[HTMLArea.Config::registerButton]: A button with the same Id: " + buttonId + " already exists and will be overidden.");
-	}
-	switch (typeof(id)) {
-		case "string":
-			if (typeof(hide) === "undefined") var hide = false;
-			if (typeof(selection) === "undefined") var selection = false;
-			if (typeof(dialog) === "undefined") var dialog = true;
-			this.btnList[id] = [tooltip, image, textMode, action, context, hide, selection, dialog, dimensions];
-			break;
-		case "object":
-			if (typeof(id.hide) === "undefined") id.hide = false;
-			if (typeof(id.selection) === "undefined") id.selection = false;
-			if (typeof(id.dialog) === "undefined") id.dialog = true;
-			this.btnList[id.id] = [id.tooltip, id.image, id.textMode, id.action, id.context, id.hide, id.selection, id.dialog, id.dimensions];
-			break;
-	}
-	return true;
-};
-
-/*
- * Register a dropdown box with the editor configuration.
- */
-HTMLArea.Config.prototype.registerDropdown = function(dropDownConfiguration) {
-	if (typeof(this.customSelects[dropDownConfiguration.id]) != "undefined") {
-		HTMLArea._appendToLog("[HTMLArea.Config::registerDropdown]: A dropdown with the same ID " + dropDownConfiguration.id + " already exists and will be overidden.");
-	}
-	if (typeof(this.btnList[dropDownConfiguration.id]) != "undefined") {
-		HTMLArea._appendToLog("ERROR [HTMLArea.Config::registerDropdown]: A button with the same ID " + dropDownConfiguration.id + " already exists.");
-		return false;
-	}
-	this.customSelects[dropDownConfiguration.id] = dropDownConfiguration;
-	return true;
-};
-
-/*
- * Register a hotkey with the editor configuration.
- */
-HTMLArea.Config.prototype.registerHotKey = function(hotKeyConfiguration) {
-	if (typeof(this.hotKeyList[hotKeyConfiguration.id]) != "undefined") {
-		HTMLArea._appendToLog("[HTMLArea.Config::registerHotKey]: A hotkey with the same key " + hotKeyConfiguration.id + " already exists and will be overidden.");
-	}
-	this.hotKeyList[hotKeyConfiguration.id] = hotKeyConfiguration;
-	return true;
-};
-
-HTMLArea.Config.prototype.getDocumentType = function () {
-	return this.documentType;
-};
-
+});
 /***************************************************
- *  EDITOR FRAMEWORK
+ *  TOOLBAR COMPONENTS
  ***************************************************/
 /*
- * Update the state of a toolbar element.
- * This function is member of a toolbar element object, unnamed object created by createButton or createSelect functions.
+ * Ext.ux.HTMLAreaButton extends Ext.Button
  */
-HTMLArea.setButtonStatus = function(id,newval) {
-	var oldval = this[id];
-	var el = document.getElementById(this.elementId);
-	if (oldval != newval) {
-		switch (id) {
-			case "enabled":
-				if (newval) {
-					if (!HTMLArea.is_wamcom) {
-						HTMLArea._removeClass(el, "buttonDisabled");
-						HTMLArea._removeClass(el.parentNode, "buttonDisabled");
-					}
-					el.disabled = false;
-				} else {
-					if (!HTMLArea.is_wamcom) {
-						HTMLArea._addClass(el, "buttonDisabled");
-						HTMLArea._addClass(el.parentNode, "buttonDisabled");
-					}
-					el.disabled = true;
+Ext.ux.HTMLAreaButton = Ext.extend(Ext.Button, {
+	/*
+	 * Component initialization
+	 */
+	initComponent: function () {
+		Ext.ux.HTMLAreaButton.superclass.initComponent.call(this);
+		this.addEvents(
+			/*
+			 * @event hotkey
+			 * Fires when the button hotkey is pressed
+			 */
+			'hotkey'
+		);
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
+			}
+		});
+	},
+	/*
+	 * Initialize listeners
+	 */
+	initEventListeners: function () {
+		this.addListener({
+			click: {
+				fn: this.onButtonClick
+			},
+			hotkey: {
+				fn: this.onHotKey
+			}
+		});
+			// Monitor toolbar updates in order to refresh the state of the button
+		this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this);
+	},
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.ownerCt.editorId].editor;
+	},
+	/*
+	 * Get a reference to the toolbar
+	 */
+	getToolbar: function() {
+		return this.ownerCt;
+	},
+	/*
+	 * Add properties and function to set button active or not depending on current selection
+	 */
+	inactive: true,
+	activeClass: 'buttonActive',
+	setInactive: function (inactive) {
+		this.inactive = inactive;
+		return inactive ? this.removeClass(this.activeClass) : this.addClass(this.activeClass);
+	},
+	/*
+	 * Determine if the button should be enabled based on the current selection and context configuration property
+	 */
+	isInContext: function (mode, selectionEmpty, ancestors) {
+		var editor = this.getEditor();
+		var inContext = true;
+		if (mode === 'wysiwyg' && this.context) {
+			var attributes = [],
+				contexts = [];
+			if (/(.*)\[(.*?)\]/.test(this.context)) {
+				contexts = RegExp.$1.split(',');
+				attributes = RegExp.$2.split(',');
+			} else {
+				contexts = this.context.split(',');
+			}
+			contexts = new RegExp( '^(' + contexts.join('|') + ')$', 'i');
+			var matchAny = contexts.test('*');
+			Ext.each(ancestors, function (ancestor) {
+				inContext = matchAny || contexts.test(ancestor.nodeName);
+				if (inContext) {
+					Ext.each(attributes, function (attribute) {
+						inContext = eval("ancestor." + attribute);
+						return inContext;
+					});
 				}
-				break;
-			    case "active":
-				if (newval) {
-					HTMLArea._addClass(el, "buttonPressed");
-					HTMLArea._addClass(el.parentNode, "buttonPressed");
-					el.active = true;
-				} else {
-					HTMLArea._removeClass(el, "buttonPressed");
-					HTMLArea._removeClass(el.parentNode, "buttonPressed");
-					el.active = false;
-				}
-				break;
+				return !inContext;
+			});
 		}
-		this[id] = newval;
-	}
-};
-
-/*
- * Create a new line in the toolbar
- */
-HTMLArea.newLine = function(toolbar) {
-	tb_line = document.createElement("ul");
-	tb_line.className = "tb-line";
-	toolbar.appendChild(tb_line);
-	return tb_line;
-};
-
-/*
- * Add a toolbar element to the current line or group
- */
-HTMLArea.addTbElement = function(element, tb_line, first_cell_on_line) {
-	var tb_cell = document.createElement("li");
-	if (first_cell_on_line) tb_cell.className = "tb-first-cell";
-		else tb_cell.className = "tb-cell";
-	HTMLArea._addClass(tb_cell, element.className);
-	tb_line.appendChild(tb_cell);
-	tb_cell.appendChild(element);
-	if(element.style.display == "none") {
-		tb_cell.style.display = "none";
-		if(HTMLArea._hasClass(tb_cell.previousSibling, "separator")) tb_cell.previousSibling.style.display = "none";
-	}
-	return false;
-};
-
-/*
- * Create a new group on the current line
- */
-HTMLArea.addTbGroup = function(tb_line, first_cell_on_line) {
-	var tb_group = document.createElement("ul");
-	tb_group.className = "tb-group";
-	HTMLArea.addTbElement(tb_group, tb_line, first_cell_on_line);
-	return tb_group;
-};
-
-/*
- * Create a combo box and add it to the toolbar
- */
-HTMLArea.prototype.createSelect = function(txt,tb_line,first_cell_on_line,labelObj) {
-	var options = null,
-		cmd = null,
-		context = null,
-		tooltip = "",
-		newObj = {
-			created : false,
-			el : null,
-			first : first_cell_on_line,
-			labelUsed : false
-		};
-
-	cmd = txt;
-	var dropdown = this.config.customSelects[cmd];
-	if (typeof(dropdown) != "undefined") {
-		options = dropdown.options;
-		context = dropdown.context;
-		if (typeof(dropdown.tooltip) != "undefined") tooltip = dropdown.tooltip;
-	}
-	if (options) {
-		newObj["el"] = document.createElement("select");
-		newObj["el"].className = "select";
-		newObj["el"].title = tooltip;
-		newObj["el"].id = this._editorNumber + "-" + txt;
-		newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-		var obj = {
-			name 		: txt,				// field name
-			elementId 	: newObj["el"].id,		// unique id for the UI element
-			enabled 	: true,				// is it enabled?
-			text 		: false,			// enabled in text mode?
-			cmd 		: cmd,				// command ID
-			state		: HTMLArea.setButtonStatus,	// for changing state
-			context 	: context,
-			editorNumber	: this._editorNumber
-		};
-		this._toolbarObjects[txt] = obj;
-		newObj["el"]._obj = obj;
-		if (labelObj["labelRef"]) {
-			labelObj["el"].htmlFor = newObj["el"].id;
-			newObj["labelUsed"] = true;
+		return inContext && (!this.selection || !selectionEmpty);
+	},
+	/*
+	 * Handler invoked when the button is clicked
+	 */
+	onButtonClick: function (button, event, key) {
+		if (!this.disabled) {
+			if (!this.plugins[this.action](this.getEditor(), key || this.itemId) && event) {
+				event.stopEvent();
+			}
+			if (Ext.isOpera) {
+				this.getEditor().focus();
+			}
+			if (this.dialog) {
+				this.setDisabled(true);
+			} else {
+				this.getToolbar().update();
+			}
 		}
-		HTMLArea._addEvent(newObj["el"], "change", HTMLArea.toolBarButtonHandler);
-
-		for (var i in options) {
-			if (options.hasOwnProperty(i)) {
-				var op = document.createElement("option");
-				op.innerHTML = i;
-				op.value = options[i];
-				newObj["el"].appendChild(op);
+		return false;
+	},
+	/*
+	 * Handler invoked when the hotkey configured for this button is pressed
+	 */
+	onHotKey: function (key, event) {
+		return this.onButtonClick(this, event, key);
+	},
+	/*
+	 * Handler invoked when the toolbar is updated
+	 */
+	onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		this.setDisabled(mode === 'textmode' && !this.textMode);
+		if (!this.disabled) {
+			if (!this.noAutoUpdate) {
+				this.setDisabled(!this.isInContext(mode, selectionEmpty, ancestors));
 			}
+			this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
 		}
-
-		newObj["created"] = true;
 	}
-
-	return newObj;
-};
-
+});
+Ext.reg('htmlareabutton', Ext.ux.HTMLAreaButton);
 /*
- * Create a button and add it to the toolbar
+ * Ext.ux.Toolbar.HTMLAreaToolbarText extends Ext.Toolbar.TextItem
  */
-HTMLArea.prototype.createButton = function (txt,tb_line,first_cell_on_line,labelObj) {
-	var btn = null,
-		newObj = {
-			created : false,
-			el : null,
-			first : first_cell_on_line,
-			labelUsed : false
-		};
-
-	switch (txt) {
-		case "separator":
-			newObj["el"] = document.createElement("div");
-			newObj["el"].className = "separator";
-			newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-			newObj["created"] = true;
-			break;
-		case "space":
-			newObj["el"] = document.createElement("div");
-			newObj["el"].className = "space";
-			newObj["el"].innerHTML = "&nbsp;";
-			newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-			newObj["created"] = true;
-			break;
-		case "TextIndicator":
-			newObj["el"] = document.createElement("div");
-			newObj["el"].appendChild(document.createTextNode("A"));
-			newObj["el"].className = "indicator";
-			newObj["el"].title = HTMLArea.I18N.tooltips.textindicator;
-			newObj["el"].id = this._editorNumber + "-" + txt;
-			newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-			var obj = {
-				name		: txt,
-				elementId	: newObj["el"].id,
-				enabled		: true,
-				active		: false,
-				text		: false,
-				cmd		: "TextIndicator",
-				state		: HTMLArea.setButtonStatus
-			};
-			this._toolbarObjects[txt] = obj;
-			newObj["created"] = true;
-			break;
-		default:
-			btn = this.config.btnList[txt];
-	}
-	if(!newObj["created"] && btn) {
-		newObj["el"] = document.createElement("button");
-		newObj["el"].title = btn[0];
-		newObj["el"].className = "button";
-		newObj["el"].id = this._editorNumber + "-" + txt;
-		if (btn[5]) newObj["el"].style.display = "none";
-		newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-		var obj = {
-			name 		: txt, 				// the button name
-			elementId	: newObj["el"].id, 		// unique id for the UI element
-			enabled 	: true,				// is it enabled?
-			active		: false,			// is it pressed?
-			text 		: btn[2],			// enabled in text mode?
-			cmd 		: btn[3],			// the function to be invoked
-			state		: HTMLArea.setButtonStatus,	// for changing state
-			context 	: btn[4] || null,		// enabled in a certain context?
-			selection	: btn[6],			// disabled when no selection?
-			editorNumber	: this._editorNumber
-		};
-		this._toolbarObjects[txt] = obj;
-		newObj["el"]._obj = obj;
-		if (labelObj["labelRef"]) {
-			labelObj["el"].htmlFor = newObj["el"].id;
-			newObj["labelUsed"] = true;
+Ext.ux.Toolbar.HTMLAreaToolbarText = Ext.extend(Ext.Toolbar.TextItem, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		Ext.ux.Toolbar.HTMLAreaToolbarText.superclass.initComponent.call(this);
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
+			}
+		});
+	},
+	/*
+	 * Initialize listeners
+	 */
+	initEventListeners: function () {
+			// Monitor toolbar updates in order to refresh the state of the button
+		this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this);
+	},
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.ownerCt.editorId].editor;
+	},
+	/*
+	 * Get a reference to the toolbar
+	 */
+	getToolbar: function() {
+		return this.ownerCt;
+	},
+	/*
+	 * Handler invoked when the toolbar is updated
+	 */
+	onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		this.setDisabled(mode === 'textmode' && !this.textMode);
+		if (!this.disabled) {
+			this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
 		}
-		HTMLArea._addEvents(newObj["el"],["mouseover", "mouseout", "mousedown", "click"], HTMLArea.toolBarButtonHandler);
-		newObj["el"].className += " " + txt;
-		newObj["created"] = true;
 	}
-	return newObj;
-};
-
+});
+Ext.reg('htmlareatoolbartext', Ext.ux.Toolbar.HTMLAreaToolbarText);
 /*
- * Create a label and add it to the toolbar
+ * Ext.ux.form.HTMLAreaCombo extends Ext.form.ComboBox
  */
-HTMLArea.createLabel = function(txt,tb_line,first_cell_on_line) {
-	var newObj = {
-		created : false,
-		el : null,
-		labelRef : false,
-		first : first_cell_on_line
-	};
-	if (/^([IT])\[(.*?)\]/.test(txt)) {
-		var l7ed = RegExp.$1 == "I"; // localized?
-		var label = RegExp.$2;
-		if (l7ed) label = HTMLArea.I18N.dialogs[label];
-		newObj["el"] = document.createElement("label");
-		newObj["el"].className = "label";
-		newObj["el"].innerHTML = label;
-		newObj["labelRef"] = true;
-		newObj["created"] = true;
-		newObj["first"] = HTMLArea.addTbElement(newObj["el"], tb_line, first_cell_on_line);
-	}
-	return newObj;
-};
-
-/*
- * Create the toolbar and append it to the _htmlarea.
- */
-HTMLArea.prototype._createToolbar = function () {
-	var j, k, code, n = this.config.toolbar.length, m,
-		tb_line = null, tb_group = null,
-		first_cell_on_line = true,
-		labelObj = new Object(),
-		tbObj = new Object();
-
-	var toolbar = document.createElement("div");
-	this._toolbar = toolbar;
-	toolbar.className = "toolbar";
-	toolbar.unselectable = "1";
-	this._toolbarObjects = new Object();
-
-	for (j = 0; j < n; ++j) {
-		tb_line = HTMLArea.newLine(toolbar);
-		if(!this.config.keepButtonGroupTogether) HTMLArea._addClass(tb_line, "free-float");
-		first_cell_on_line = true;
-		tb_group = null;
-		var group = this.config.toolbar[j];
-		m = group.length;
-		for (k = 0; k < m; ++k) {
-			code = group[k];
-			if (code == "linebreak") {
-				tb_line = HTMLArea.newLine(toolbar);
-				if(!this.config.keepButtonGroupTogether) HTMLArea._addClass(tb_line, "free-float");
-				first_cell_on_line = true;
-				tb_group = null;
-			} else {
-				if ((code == "separator" || first_cell_on_line) && this.config.keepButtonGroupTogether) {
-					tb_group = HTMLArea.addTbGroup(tb_line, first_cell_on_line);
-					first_cell_on_line = false;
-				}
-				created = false;
-				if (/^([IT])\[(.*?)\]/.test(code)) {
-					labelObj = HTMLArea.createLabel(code, (tb_group?tb_group:tb_line), first_cell_on_line);
-					created = labelObj["created"] ;
-					first_cell_on_line = labelObj["first"];
-				}
-				if (!created) {
-					tbObj = this.createButton(code, (tb_group?tb_group:tb_line), first_cell_on_line, labelObj);
-					created = tbObj["created"];
-					first_cell_on_line = tbObj["first"];
-					if(tbObj["labelUsed"]) labelObj["labelRef"] = false;
-				}
-				if (!created) {
-					tbObj = this.createSelect(code, (tb_group?tb_group:tb_line), first_cell_on_line, labelObj);
-					created = tbObj["created"];
-					first_cell_on_line = tbObj["first"];
-					if(tbObj["labelUsed"]) labelObj["labelRef"] = false;
-				}
-				if (!created) HTMLArea._appendToLog("ERROR [HTMLArea::createToolbar]: Unknown toolbar item: " + code);
+Ext.ux.form.HTMLAreaCombo = Ext.extend(Ext.form.ComboBox, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		Ext.ux.form.HTMLAreaCombo.superclass.initComponent.call(this);
+		this.addEvents(
+			/*
+			 * @event hotkey
+			 * Fires when a hotkey configured for the combo is pressed
+			 */
+			'hotkey'
+		);
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
 			}
+		});
+	},
+	/*
+	 * Initialize listeners
+	 */
+	initEventListeners: function () {
+		this.addListener({
+			select: {
+				fn: this.onComboSelect
+			},
+			specialkey: {
+				fn: this.onSpecialKey
+			},
+			hotkey: {
+				fn: this.onHotKey
+			}
+		});
+			// Monitor toolbar updates in order to refresh the state of the combo
+		this.mon(this.getToolbar(), 'update', this.onUpdateToolbar, this);
+			// Monitor framework becoming ready
+		if (Ext.isIE) {
+			this.mon(this.getToolbar().ownerCt, 'frameworkready', this.onFrameworkReady, this);
 		}
-	}
-
-	tb_line = HTMLArea.newLine(toolbar);
-	this._htmlArea.appendChild(toolbar);
-};
-
-/*
- * Handle toolbar element events handler
- */
-HTMLArea.toolBarButtonHandler = function(ev) {
-	if(!ev) var ev = window.event;
-	var target = (ev.target) ? ev.target : ev.srcElement;
-	while (target.tagName.toLowerCase() == "img" || target.tagName.toLowerCase() == "div") target = target.parentNode;
-	var obj = target._obj;
-	var editorNumber = obj["editorNumber"];
-	var editor = RTEarea[editorNumber]["editor"];
-	if (obj.enabled) {
-		switch (ev.type) {
-			case "mouseover":
-				HTMLArea._addClass(target, "buttonHover");
-				HTMLArea._addClass(target.parentNode, "buttonHover");
-				break;
-			case "mouseout":
-				HTMLArea._removeClass(target, "buttonHover");
-				HTMLArea._removeClass(target.parentNode, "buttonHover");
-				HTMLArea._removeClass(target, "buttonActive");
-				HTMLArea._removeClass(target.parentNode, "buttonActive");
-				if (obj.active) {
-					HTMLArea._addClass(target, "buttonPressed");
-					HTMLArea._addClass(target.parentNode, "buttonPressed");
+	},
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.ownerCt.editorId].editor;
+	},
+	/*
+	 * Get a reference to the toolbar
+	 */
+	getToolbar: function() {
+		return this.ownerCt;
+	},
+	/*
+	 * Handler invoked when an item is selected in the dropdown list
+	 */
+	onComboSelect: function (combo, record, index) {
+		if (!combo.disabled) {
+			var editor = this.getEditor();
+				// In IE, reclaim lost focus on the editor iframe and restore the bookmarked selection
+			if (Ext.isIE) {
+				editor.focus();
+				if (!Ext.isEmpty(this.bookmark)) {
+					editor.selectRange(editor.moveToBookmark(this.bookmark));
+					this.bookmark = null;
 				}
-				break;
-			case "mousedown":
-				HTMLArea._addClass(target, "buttonActive");
-				HTMLArea._addClass(target.parentNode, "buttonActive");
-				HTMLArea._removeClass(target, "buttonPressed");
-				HTMLArea._removeClass(target.parentNode, "buttonPressed");
-				HTMLArea._stopEvent(ev);
-				break;
-			case "click":
-				HTMLArea._removeClass(target, "buttonActive");
-				HTMLArea._removeClass(target.parentNode, "buttonActive");
-				HTMLArea._removeClass(target, "buttonHover");
-				HTMLArea._removeClass(target.parentNode, "buttonHover");
-				obj.cmd(editor, obj.name);
-				HTMLArea._stopEvent(ev);
-				if (HTMLArea.is_opera) {
-					editor._iframe.focus();
-				}
-				if (!editor.config.btnList[obj.name][7]) {
-					editor.updateToolbar();
-				}
-				break;
-			case "change":
-				editor.focusEditor();
-				var dropdown = editor.config.customSelects[obj.name];
-				if (typeof(dropdown) !== "undefined") {
-					dropdown.action(editor, obj.name);
-					HTMLArea._stopEvent(ev);
-					if (HTMLArea.is_opera) {
-						editor._iframe.focus();
-					}
-					editor.updateToolbar();
-				} else {
-					HTMLArea._appendToLog("ERROR [HTMLArea::toolBarButtonHandler]: Combo box " + obj.name + " not registered.");
-				}
+			}
+				// Invoke the plugin onChange handler
+			this.plugins[this.action](editor, combo, record, index);
+				// In IE, bookmark the updated selection as the editor will be loosing focus
+			if (Ext.isIE) { 
+				editor.focus();
+				this.bookmark = editor.getBookmark(editor._createRange(editor._getSelection()));
+				this.triggered = true;
+			}
+			if (Ext.isOpera) {
+				editor.focus();
+			}
+			this.getToolbar().update();
 		}
-	}
-};
-
-/*
- * Create the htmlArea iframe and replace the textarea with it.
- */
-HTMLArea.prototype.generate = function () {
-	var self = this;
-		// Get the textarea, hide it and make it resizable
-	this.textArea = Ext.get(this._textArea).setVisibilityMode(2).setVisible(false);
-	if (TYPO3.settings.textareaResize) {
-		this.textArea.addClass('resizable');
-		this.textAreaResizer = new Ext.Resizable(this.textArea, {
-			minWidth:  300,
-			minHeight: 200,
-			maxHeight: TYPO3.settings.textareaMaxHeight,
-			dynamic:   true
-		});
-		this.textAreaResizer.on('resize', function(ev) { self.resizeOnTextAreaChange(2); });
-	}
-
-		// Create the editor framework and insert it before the textarea
-	this.htmlArea = Ext.DomHelper.insertBefore(this.textArea, {
-		tag: 'div',
-		cls: 'htmlarea'
-	}, true).setWidth(this.textArea.getStyle('width'));
-	this._htmlArea = this.htmlArea.dom;
-
-		// If we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
-	if (this.textArea.dom.form) {
-		var f = this.textArea.dom.form;
-		if (typeof(f.onreset) == "function") {
-			var funcref = f.onreset;
-			if (typeof(f.__msh_prevOnReset) == "undefined") f.__msh_prevOnReset = [];
-			f.__msh_prevOnReset.push(funcref);
+		return false;
+	},
+	/*
+	 * Handler invoked when the trigger element is clicked
+	 * In IE, need to reclaim lost focus for the editor in order to restore the selection
+	 */
+	onTriggerClick: function () {
+		Ext.ux.form.HTMLAreaCombo.superclass.onTriggerClick.call(this);
+			// In IE, avoid focus being stolen and selection being lost
+		if (Ext.isIE) {
+			this.triggered = true;
+			this.getEditor().focus();
 		}
-		f._editorNumber = this._editorNumber;
-		HTMLArea._addEvent(f, "reset", HTMLArea.resetHandler);
-	}
-
-		// Create & append the toolbar
-	this._createToolbar();
-	HTMLArea._appendToLog("[HTMLArea::generate]: Toolbar successfully created.");
-
-		// Create the editor iframe and append it to the toolbar
-	this.iframe = Ext.DomHelper.append(this.htmlArea, {
-			tag: 'iframe',
-			cls: 'editorIframe',
-			src: (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) ? 'javascript:void(0);' : (HTMLArea.is_opera?_typo3_host_url:'') + _editor_url + 'popups/blank.html'
-	}, true);
-	if (!this.getPluginInstance('StatusBar')) {
-		this.iframe.addClass('noStatusBar');
-	}
-	this._iframe = this.iframe.dom;
-	HTMLArea._appendToLog("[HTMLArea::generate]: Editor iframe successfully created.");
-		// Make the editor framework resizable
-	if (TYPO3.settings.textareaResize) {
-		this.htmlArea.addClass('resizable');
-		var dimensions = this.getDimensions();
-		this.htmlAreaResizer = new Ext.Resizable(this.htmlArea, {
-			maxHeight: parseInt(TYPO3.settings.textareaMaxHeight) + dimensions.toolbar.height + dimensions.statusbar.height,
-			dynamic:   false
-		});
-		this.htmlAreaResizer.on('resize', function(ev) { self.resizeOnHtmlAreaChange(2); });
-	}
-	if (HTMLArea.is_opera) {
-		this.iframe.on('load', function() { self.initIframe(); } , this);
-	} else {
-		this.initIframe();
-	}
-	return this;
-};
-
-/*
- * Resize the editor framework and the iframe when the textarea was resized
- */
-HTMLArea.prototype.resizeOnTextAreaChange = function(diff) {
-		// Set width first as it may change the height of the toolbar and of the statusbar
-	var width = this.textArea.getStyle('width');
-	if (width.indexOf('%') == -1) {
-		width = (parseInt(width) + diff) + 'px';
-	}
-	this.iframe.setStyle('width', HTMLArea.is_opera ? width : '100%');
-	this.htmlArea.setStyle('width', width);
-		// Set height
-	var dimensions = this.getDimensions();
-	var height = this.textArea.getStyle('height');
-	if (height.indexOf('%') == -1) {
-		height = (parseInt(height) + diff) + 'px';
-	}
-	this.iframe.setStyle('height', height);
-	this.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
-};
-
-/*
- * Resize the textarea and iframe when the htmlArea was resized
- */
-HTMLArea.prototype.resizeOnHtmlAreaChange = function(diff) {
-		// Set width first as it may change the height of the toolbar and of the statusbar
-	var width = this.htmlArea.getStyle('width');
-		// Do not shrink narrower than configured textarea
-	if (parseInt(width) < this.textAreaResizer.minWidth + diff) {
-		width = (this.textAreaResizer.minWidth + diff) + 'px';
-		this.htmlArea.setStyle('width', width);
-	}
-	if (width.indexOf('%') == -1) {
-		width = (parseInt(width) - diff) + 'px';
-	}
-	this.textArea.setStyle('width', width);
-		// Set height
-	var height = this.iframe.getStyle('height');
-	if (height.indexOf('%') == -1) {
-		var dimensions = this.getDimensions();
-		height = parseInt(this.htmlArea.getStyle('height')) - dimensions.toolbar.height - dimensions.statusbar.height;
-			// Do not shrink shorter than configured textarea
-		if (height < this.textAreaResizer.minHeight + diff) {
-			height = this.textAreaResizer.minHeight + diff;
-			this.htmlArea.setStyle('height', (height + dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
+	},
+	/*
+	 * Handler invoked when the list of options is clicked in
+	 */
+	onViewClick: function (doFocus) {
+			// Avoid stealing focus from the editor
+		Ext.ux.form.HTMLAreaCombo.superclass.onViewClick.call(this, false);
+	},
+	/*
+	 * Handler invoked in IE when the mouse moves out of the editor iframe
+	 */
+	saveSelection: function (event) {
+		var editor = this.getEditor();
+		if (editor.document.hasFocus()) {
+			this.bookmark = editor.getBookmark(editor._createRange(editor._getSelection()));
 		}
-		this.iframe.setStyle('height', height + 'px');
-		height = (height - diff) + 'px';
-	}
-	this.textArea.setStyle('height', height);
-};
-
-/*
- * Size the iframe according to user's prefs or initial textarea
- */
-HTMLArea.prototype.sizeIframe = function(diff) {
-		// Clone the array of nested tabs and inline levels instead of using a reference (this.accessParentElements will change the array):
-	var parentElements = (this.nested.sorted && this.nested.sorted.length ? [].concat(this.nested.sorted) : []);
-		// Walk through all nested tabs and inline levels to make a correct positioning:
-	var dimensions = this.accessParentElements(parentElements, 'this.getDimensions()');
-		// Set height
-	this.config.height = (this.config.height == "auto") ? this._textArea.style.height : this.config.height;
-	var iframeHeight = this.config.height;
-	var textareaHeight = this.config.height;
-	var htmlAreaHeight = this.config.height;
-	if (this.config.height.indexOf("%") == -1) {
-		iframeHeight = parseInt(iframeHeight) - diff;
-		if (this.config.sizeIncludesToolbar) {
-			this._initialToolbarOffsetHeight = this._initialToolbarOffsetHeight ? this._initialToolbarOffsetHeight : dimensions.toolbar.height;
-			iframeHeight -= dimensions.toolbar.height;
-			iframeHeight -= dimensions.statusbar.height;
+	},
+	/*
+	 * Handler invoked in IE when the editor gets the focus back
+	 */
+	restoreSelection: function (event) {
+		if (!Ext.isEmpty(this.bookmark) && this.triggered) {
+			var editor = this.getEditor();
+			editor.selectRange(editor.moveToBookmark(this.bookmark));
+			this.triggered = false;
 		}
-		if (iframeHeight < 0) {
-			iframeHeight = 0;
+	},
+	/*
+	 * Handler invoked when the enter key is pressed while the combo has focus
+	 */
+	onSpecialKey: function (combo, event) {
+		if (event.getKey() == event.ENTER) {
+			event.stopEvent();
+                }
+		return false;
+	},
+	/*
+	 * Handler invoked when a hot key configured for this dropdown list is pressed
+	 */
+	onHotKey: function (key) {
+		if (!this.disabled) {
+			this.plugins.onHotKey(this.getEditor(), key);
+			if (Ext.isOpera) {
+				this.getEditor().focus();
+			}
+			this.getToolbar().update();
 		}
-		htmlAreaHeight = (iframeHeight + dimensions.toolbar.height + dimensions.statusbar.height) + 'px';
-		textareaHeight = (iframeHeight - 4);
-		if (textareaHeight < 0) {
-			textareaHeight = 0;
+		return false;
+	},
+	/*
+	 * Handler invoked when the toolbar is updated
+	 */
+	onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		this.setDisabled(mode === 'textmode' && !this.textMode);
+		if (!this.disabled) {
+			this.plugins['onUpdateToolbar'](this, mode, selectionEmpty, ancestors, endPointsInSameBlock);
 		}
-		iframeHeight += "px";
-		textareaHeight += "px";
+	},
+	/*
+	 * Special handling for combo stealing focus in IE
+	 * The iframe must have been rendered
+	 */
+	onFrameworkReady: function () {
+			// Take a bookmark in case the editor looses focus by activation of this combo
+		this.mon(this.getEditor().iframe.getEl(), 'mouseleave', this.saveSelection, this);
+			// Restore the selection if combo was triggered
+		this.mon(this.getEditor().iframe.getEl(), 'focus', this.restoreSelection, this);
 	}
-	this._iframe.style.height = iframeHeight;
-	this._textArea.style.height = textareaHeight;
-	this.htmlArea.setStyle('height', htmlAreaHeight);
-		// Set width
-	this.config.width = (this.config.width == "auto") ? this._textArea.style.width : this.config.width;
-	var textareaWidth = this.config.width;
-	var iframeWidth = this.config.width;
-	if (textareaWidth.indexOf("%") == -1) {
-		iframeWidth = parseInt(textareaWidth) + "px";
-		textareaWidth = parseInt(textareaWidth) - diff;
-		if (textareaWidth < 0) {
-			textareaWidth = 0;
-		}
-		textareaWidth += "px";
-	}
-	this._iframe.style.width = "100%";
-	if (HTMLArea.is_opera) {
-		this._iframe.style.width = iframeWidth;
-	}
-	this._textArea.style.width = textareaWidth;
-};
-
+});
+Ext.reg('htmlareacombo', Ext.ux.form.HTMLAreaCombo);
+/***************************************************
+ *  EDITOR FRAMEWORK
+ ***************************************************/
 /*
- * Resize the iframes
+ * HTMLArea.Toolbar extends Ext.Container
  */
-HTMLArea.resizeIframes = function(ev) {
-	if (!ev) var ev = window.event;
-	HTMLArea._stopEvent(ev);
-	for (var editorNumber in RTEarea) {
-		if (RTEarea.hasOwnProperty(editorNumber)) {
-			var editor = RTEarea[editorNumber].editor;
-			if (editor) {
-				editor.sizeIframe(2);
+HTMLArea.Toolbar = Ext.extend(Ext.Container, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		HTMLArea.Toolbar.superclass.initComponent.call(this);
+		this.addEvents(
+			/*
+			 * @event update
+			 * Fires when the toolbar is updated
+			 */
+			'update'
+		);
+			// Build the deferred toolbar update task
+		this.updateLater = new Ext.util.DelayedTask(this.update, this);
+			// Add the toolbar items
+		this.addItems();
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
 			}
+		});
+	},
+	/*
+	 * Initialize listeners
+	 */
+	initEventListeners: function () {
+			// Monitor editor becoming ready
+		this.mon(this.getEditor(), 'editorready', this.update, this, {single: true});
+	},
+	/*
+	 * editorId should be set in config
+	 */
+	editorId: null,
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.editorId].editor;
+	},
+	/*
+	 * Create the toolbar items based on editor toolbar configuration
+	 */
+	addItems: function () {
+		var editor = this.getEditor();
+			// Walk through the editor toolbar configuration nested arrays: [ toolbar [ row [ group ] ] ]
+		var firstOnRow = true;
+		var firstInGroup = true;
+		Ext.each(editor.config.toolbar, function (row) {
+			if (!firstOnRow) {
+					// If a visible item was added to the previous line
+				this.add({
+					xtype: 'tbspacer',
+					cls: 'x-form-clear-left'
+				});
+			}
+			firstOnRow = true;
+				// Add the groups
+			Ext.each(row, function (group) {
+					// To do: this.config.keepButtonGroupTogether ...
+				if (!firstOnRow && !firstInGroup) {
+						// If a visible item was added to the line
+					this.add({
+						xtype: 'tbseparator',
+						cls: 'separator'
+					});
+				}
+				firstInGroup = true;
+					// Add each item
+				Ext.each(group, function (item) {
+					if (item == 'space') {
+						this.add({
+							xtype: 'tbspacer',
+							cls: 'space'
+						});
+					} else {
+							// Get the item's config as registered by some plugin
+						var itemConfig = editor.config.buttonsConfig[item];
+						if (!Ext.isEmpty(itemConfig)) {
+							itemConfig.id = this.editorId + '-' + itemConfig.id;
+							this.add(itemConfig);
+							firstInGroup = firstInGroup && itemConfig.hidden;
+							firstOnRow = firstOnRow && firstInGroup;
+						}
+					}
+					return true;
+				}, this);
+				return true;
+			}, this);
+			return true;
+		}, this);
+		this.add({
+			xtype: 'tbspacer',
+			cls: 'x-form-clear-left'
+		});
+	},
+	/*
+	 * Retrieve a toolbar item by itemId
+	 */
+	getButton: function (buttonId) {
+		return this.find('itemId', buttonId)[0];
+	},
+	/*
+	 * Update the state of the toolbar
+	 */
+	update: function() {
+		var editor = this.getEditor(),
+			mode = editor.getMode(),
+			selectionEmpty = true,
+			ancestors = null,
+			endPointsInSameBlock = true;
+		if (editor.getMode() === 'wysiwyg') {
+			selectionEmpty = editor._selectionEmpty(editor._getSelection());
+			ancestors = editor.getAllAncestors();
+			endPointsInSameBlock = editor.endPointsInSameBlock();
 		}
+		this.fireEvent('update', mode, selectionEmpty, ancestors, endPointsInSameBlock);
 	}
-};
-
-/**
- * Get the dimensions of the toolbar and statusbar.
- *
- * @return	object		An object with width/height pairs for statusbar and toolbar.
- * @author	Oliver Hader <oh@inpublica.de>
+});
+Ext.reg('htmlareatoolbar', HTMLArea.Toolbar);
+/*
+ * HTMLArea.Iframe extends Ext.BoxComponent
  */
-HTMLArea.prototype.getDimensions = function() {
-	return {
-		toolbar: {width: this._toolbar.offsetWidth, height: this._toolbar.offsetHeight},
-		statusbar: {width: ((this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").statusBar) ? this.getPluginInstance("StatusBar").statusBar.offsetWidth : 0), height: ((this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").statusBar) ? this.getPluginInstance("StatusBar").statusBar.offsetHeight : 0)}
-	};
-};
-
-/**
- * Access an inline relational element or tab menu and make it "accessible".
- * If a parent object has the style "display: none", offsetWidth & offsetHeight are '0'.
- *
- * @params	object		callbackFunc: A function to be called, when the embedded objects are "accessible".
- * @return	object		An object returned by the callbackFunc.
- * @author	Oliver Hader <oh@inpublica.de>
- */
-HTMLArea.prototype.accessParentElements = function(parentElements, callbackFunc) {
-	var result = {};
-
-	if (parentElements.length) {
-		var currentElement = parentElements.pop();
-		var elementStyle = document.getElementById(currentElement).style;
-		var actionRequired = (elementStyle.display == 'none' ? true : false);
-
-		if (actionRequired) {
-			var originalVisibility = elementStyle.visibility;
-			var originalPosition = elementStyle.position;
-			elementStyle.visibility = 'hidden';
-			elementStyle.position = 'absolute';
-			elementStyle.display = '';
+HTMLArea.Iframe = Ext.extend(Ext.BoxComponent, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		HTMLArea.Iframe.superclass.initComponent.call(this);
+		this.addEvents(
+			/*
+			 * @event iframeready
+			 * Fires when the iframe style sheets become accessible
+			 */
+			'iframeready'
+		);
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
+			},
+			beforeDestroy: {
+				fn: this.onBeforeDestroy,
+				single: true
+			}
+		});
+		this.config = this.getEditor().config;
+		if (!this.config.showStatusBar) {
+			this.addClass('noStatusBar');
 		}
-
-		result = this.accessParentElements(parentElements, callbackFunc);
-
-		if (actionRequired) {
-			elementStyle.display = 'none';
-			elementStyle.position = originalPosition;
-			elementStyle.visibility = originalVisibility;
+	},
+	/*
+	 * Initialize event listeners and the document after the iframe has rendered
+	 */
+	initEventListeners: function () {
+			// The editor iframe may become hidden with style.display = "none"
+			// This breaks the editor in Firefox: the designMode attribute needs to be reset after the style.display of the containing div is reset to "block"
+		if (Ext.isGecko && this.isNested) {
+			Ext.each(this.nestedParentElements.sorted, function (nested) {
+				this.mon(Ext.get(nested), 'DOMAttrModified', this.onNestedShow, this, {delay: 100});
+			}, this);
 		}
-
-	} else {
-		result = eval(callbackFunc);
-
-	}
-
-	return result;
-};
-
-/**
- * Simplify the array of nested levels. Create an indexed array with the correct names of the elements.
- *
- * @param	object		nested: The array with the nested levels
- * @return	object		The simplified array
- * @author	Oliver Hader <oh@inpublica.de>
- */
-HTMLArea.simplifyNested = function(nested) {
-	var i, type, level, max, simplifiedNested=[];
-	if (nested && nested.length) {
-		if (nested[0][0]=='inline') {
-			nested = inline.findContinuedNestedLevel(nested, nested[0][1]);
+		if (Ext.isOpera) {
+			this.mon(this.getEl(), 'load', this.initializeIframe , this, {single: true});
+		} else {
+			this.initializeIframe();
 		}
-		for (i=0, max=nested.length; i<max; i++) {
-			type = nested[i][0];
-			level = nested[i][1];
-			if (type=='tab') {
-				simplifiedNested.push(level+'-DIV');
-			} else if (type=='inline') {
-				simplifiedNested.push(level+'_fields');
+	},
+	/*
+	 * editorId should be set in config
+	 */
+	editorId: null,
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.editorId].editor;
+	},
+	/*
+	 * Get a reference to the toolbar
+	 */
+	getToolbar: function () {
+		return this.ownerCt.getTopToolbar();
+	},
+	/*
+	 * Get a reference to a button
+	 */
+	getButton: function (buttonId) {
+		return this.getToolbar().getButton(buttonId);
+	},
+	/*
+	 * Flag set to true when the iframe becomes usable for editing
+	 */
+	ready: false,
+	/*
+	 * Create the iframe element at rendering time
+	 */
+	onRender: function (ct, position){
+			// from Ext.Component
+		if (!this.el && this.autoEl) {
+			if (Ext.isString(this.autoEl)) {
+				this.el = document.createElement(this.autoEl);
+			} else {
+					// ExtJS Default method will not work with iframe element
+				this.el = Ext.DomHelper.append(ct, this.autoEl, true);
 			}
+			if (!this.el.id) {
+				this.el.id = this.getId();
+			}
 		}
-	}
-	return simplifiedNested;
-};
-
-/*
- * Initialize the iframe
- */
-HTMLArea.initIframe = function(editorNumber) {
-	var editor = RTEarea[editorNumber]["editor"];
-	editor.initIframe();
-};
-
-HTMLArea.prototype.initIframe = function() {
-	if (this._initIframeTimer) window.clearTimeout(this._initIframeTimer);
-	if (!this._iframe || (!this._iframe.contentWindow && !this._iframe.contentDocument)) {
-		this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(\'" + this._editorNumber + "\');", 50);
-		return false;
-	} else if (this._iframe.contentWindow && !HTMLArea.is_safari) {
-		if (!this._iframe.contentWindow.document || !this._iframe.contentWindow.document.documentElement) {
-			this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(\'" + this._editorNumber + "\');", 50);
-			return false;
+			// from Ext.BoxComponent
+		if (this.resizeEl){
+			this.resizeEl = Ext.get(this.resizeEl);
 		}
-	} else if (!this._iframe.contentDocument.documentElement || !this._iframe.contentDocument.body) {
-		this._initIframeTimer = window.setTimeout("HTMLArea.initIframe(\'" + this._editorNumber + "\');", 50);
-		return false;
-	}
-	var doc = this._iframe.contentWindow ? this._iframe.contentWindow.document : this._iframe.contentDocument;
-	this._doc = doc;
-		// Set Doc Type in Firefox (doctype is readonly in DOM 2)
-		// After adding doctype in Firefox, baseURL is set to the url of the parent document,
-		// base element is ignored, and all created links, including external, are prepended with incorrect base
-	/*if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-		this._doc.open();
-		this._doc.write(this.config.getDocumentType());
-		this._doc.close();
-	}*/
-	if (!this.config.fullPage) {
-		var head = doc.getElementsByTagName("head")[0];
+		if (this.positionEl){
+			this.positionEl = Ext.get(this.positionEl);
+		}
+	},
+	/*
+	 * Proceed to build the iframe document head and ensure style sheets are available after the iframe document becomes available
+	 */
+	initializeIframe: function () {
+		var iframe = this.getEl().dom;
+			// All browsers
+		if (!iframe || (!iframe.contentWindow && !iframe.contentDocument)) {
+			this.initializeIframe.defer(50, this);
+			// Gecko, except Safari
+		} else if (iframe.contentWindow && !Ext.isWebKit && (!iframe.contentWindow.document || !iframe.contentWindow.document.documentElement)) {
+			this.initializeIframe.defer(50, this);
+			// IE and Safari
+		} else if (!iframe.contentDocument.documentElement || !iframe.contentDocument.body) {
+			this.initializeIframe.defer(50, this);
+		} else {
+			this.document = iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
+			this.getEditor().document = this.document;
+			this.getEditor()._doc = this.document;
+			this.getEditor()._iframe = iframe;
+			this.createHead();
+			this.getStyleSheets();
+		}
+	},
+	/*
+	 * Build the iframe document head
+	 */
+	createHead: function () {
+		var head = this.document.getElementsByTagName('head')[0];
 		if (!head) {
-			head = doc.createElement("head");
-			doc.documentElement.appendChild(head);
+			head = this.document.createElement('head');
+			this.document.documentElement.appendChild(head);
 		}
-		if (this.config.baseURL && !HTMLArea.is_opera) {
-			var base = doc.getElementsByTagName("base")[0];
+		if (this.config.baseURL && !Ext.isOpera) {
+			var base = this.document.getElementsByTagName('base')[0];
 			if (!base) {
-				base = doc.createElement("base");
+				base = this.document.createElement('base');
 				base.href = this.config.baseURL;
 				head.appendChild(base);
 			}
-			HTMLArea._appendToLog("[HTMLArea::initIframe]: Iframe baseURL set to: " + this.config.baseURL);
+			HTMLArea._appendToLog('[HTMLArea.Iframe::createHead]: Iframe baseURL set to: ' + this.config.baseURL);
 		}
-		var link0 = doc.getElementsByTagName("link")[0];
+		var link0 = this.document.getElementsByTagName('link')[0];
 		if (!link0) {
- 			link0 = doc.createElement("link");
-			link0.rel = "stylesheet";
+			link0 = this.document.createElement('link');
+			link0.rel = 'stylesheet';
 			link0.href = this.config.editedContentStyle;
 			head.appendChild(link0);
-			HTMLArea._appendToLog("[HTMLArea::initIframe]: Skin CSS set to: " + this.config.editedContentStyle);
+			HTMLArea._appendToLog('[HTMLArea.Iframe::createHead]: Skin CSS set to: ' + this.config.editedContentStyle);
 		}
 		if (this.config.defaultPageStyle) {
-			var link = doc.getElementsByTagName("link")[1];
+			var link = this.document.getElementsByTagName('link')[1];
 			if (!link) {
- 				link = doc.createElement("link");
-				link.rel = "stylesheet";
+				link = this.document.createElement('link');
+				link.rel = 'stylesheet';
 				link.href = this.config.defaultPageStyle;
 				head.appendChild(link);
 			}
-			HTMLArea._appendToLog("[HTMLArea::initIframe]: Override CSS set to: " + this.config.defaultPageStyle);
+			HTMLArea._appendToLog('[HTMLArea.Iframe::createHead]: Override CSS set to: ' + this.config.defaultPageStyle);
 		}
 		if (this.config.pageStyle) {
-			var link = doc.getElementsByTagName("link")[2];
+			var link = this.document.getElementsByTagName('link')[2];
 			if (!link) {
- 				link = doc.createElement("link");
-				link.rel = "stylesheet";
+				link = this.document.createElement('link');
+				link.rel = 'stylesheet';
 				link.href = this.config.pageStyle;
 				head.appendChild(link);
 			}
-			HTMLArea._appendToLog("[HTMLArea::initIframe]: Content CSS set to: " + this.config.pageStyle);
+			HTMLArea._appendToLog('[HTMLArea.Iframe::createHead]: Content CSS set to: ' + this.config.pageStyle);
 		}
-	} else {
-		var html = this._textArea.value;
-		this.setFullHTML(html);
-	}
-	HTMLArea._appendToLog("[HTMLArea::initIframe]: Editor iframe head successfully initialized.");
-
-	this.stylesLoaded();
-};
-
-/*
- * Finalize editor Iframe initialization after loading the style sheets
- */
-HTMLArea.stylesLoaded = function(editorNumber) {
-	var editor = RTEarea[editorNumber]["editor"];
-	editor.stylesLoaded();
-};
-
-HTMLArea.prototype.stylesLoaded = function() {
-	var doc = this._doc;
-
-		// check if the stylesheets have been loaded
-	if (this._stylesLoadedTimer) window.clearTimeout(this._stylesLoadedTimer);
-	var stylesAreLoaded = true;
-	var errorText = '';
-	var rules;
-	if (HTMLArea.is_opera) {
-		if (doc.readyState != "complete") {
-			stylesAreLoaded = false;
-			errorText = "Stylesheets not yet loaded";
+		HTMLArea._appendToLog('[HTMLArea.Iframe::createHead]: Editor iframe document head successfully built.');
+	},
+	/*
+	 * Fire event 'iframeready' when the iframe style sheets become accessible
+	 */
+	getStyleSheets: function () {
+		var stylesAreLoaded = true;
+		var errorText = '';
+		var rules;
+		if (Ext.isOpera) {
+			if (this.document.readyState != 'complete') {
+				stylesAreLoaded = false;
+				errorText = 'Stylesheets not yet loaded';
+			}
+		} else {
+			Ext.each(this.document.styleSheets, function (styleSheet) {
+				if (!Ext.isIE) try { rules = styleSheet.cssRules; } catch(e) { stylesAreLoaded = false; errorText = e; }
+				if (Ext.isIE) try { rules = styleSheet.rules; } catch(e) { stylesAreLoaded = false; errorText = e; }
+				if (Ext.isIE) try { rules = styleSheet.imports; } catch(e) { stylesAreLoaded = false; errorText = e; }
+			});
 		}
-	} else {
-		for (var rule = 0; rule < doc.styleSheets.length; rule++) {
-			if (HTMLArea.is_gecko) try { rules = doc.styleSheets[rule].cssRules; } catch(e) { stylesAreLoaded = false; errorText = e; }
-			if (HTMLArea.is_ie) try { rules = doc.styleSheets[rule].rules; } catch(e) { stylesAreLoaded = false; errorText = e; }
-			if (HTMLArea.is_ie) try { rules = doc.styleSheets[rule].imports; } catch(e) { stylesAreLoaded = false; errorText = e; }
+		if (!stylesAreLoaded) {
+			this.getStyleSheets.defer(100, this);
+			HTMLArea._appendToLog('[HTMLArea.Iframe::getStyleSheets]: Stylesheets not yet loaded (' + errorText + '). Retrying...');
+		} else {
+			HTMLArea._appendToLog('[HTMLArea.Iframe::getStyleSheets]: Stylesheets successfully accessed.');
+				// Style the document body
+			Ext.get(this.document.body).addClass('htmlarea-content-body');
+				// Start listening to things happening in the iframe
+				// For some unknown reason, this is too early for Opera
+			if (!Ext.isOpera) {
+				this.startListening();
+			}
+				// Hide the iframe
+			this.hide();
+				// Set iframe ready
+			this.ready = true;
+			this.fireEvent('iframeready');
 		}
-	}
-	if (!stylesAreLoaded && !HTMLArea.is_wamcom) {
-		HTMLArea._appendToLog("[HTMLArea::initIframe]: Failed attempt at loading stylesheets: " + errorText + " Retrying...");
-		this._stylesLoadedTimer = window.setTimeout("HTMLArea.stylesLoaded(\'" + this._editorNumber + "\');", 100);
-		return false;
-	}
-	HTMLArea._appendToLog("[HTMLArea::initIframe]: Stylesheets successfully loaded.");
-
-	doc.body.style.borderWidth = "0px";
-	doc.body.className = "htmlarea-content-body";
-
-		// Initialize editor mode
-	if (!this.getPluginInstance("EditorMode").init()) {
-		return false;
-	}
-
-		// set editor number in iframe and document for retrieval in event handlers
-	doc._editorNo = this._editorNumber;
-	if (HTMLArea.is_ie) doc.documentElement._editorNo = this._editorNumber;
-
-		// intercept events for updating the toolbar & for keyboard handlers
-	HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["keydown","keypress","mousedown","mouseup","drag"], HTMLArea._editorEvent, true);
-
-	HTMLArea._addEvent(window, "resize", HTMLArea.resizeIframes);
-
-		// add unload handler
-	if (!HTMLArea.hasUnloadHandler) {
-		HTMLArea.hasUnloadHandler = true;
-		HTMLArea._addEvent((this._iframe.contentWindow ? this._iframe.contentWindow : this._iframe.contentDocument), "unload", HTMLArea.removeEditorEvents);
-	}
-
-	window.setTimeout("HTMLArea.generatePlugins(\'" + this._editorNumber + "\');", 100);
-};
-
-HTMLArea.generatePlugins = function(editorNumber) {
-	var editor = RTEarea[editorNumber]["editor"];
-		// check if any plugins have registered generate handlers
-		// check also if any plugin has a onKeyPress handler
-	editor._hasPluginWithOnKeyPressHandler = false;
-	for (var pluginId in editor.plugins) {
-		if (editor.plugins.hasOwnProperty(pluginId)) {
-			var pluginInstance = editor.plugins[pluginId].instance;
-			if (typeof(pluginInstance.onGenerate) === "function") {
-				pluginInstance.onGenerate();
+	},
+	/*
+	 * Focus on the iframe
+	 */
+	focus: function () {
+		try {
+			if (Ext.isWebKit) {
+				this.getEl().dom.focus();
+			} else {
+				this.getEl().dom.contentWindow.focus();
 			}
-			if (typeof(pluginInstance.onGenerateOnce) === "function") {
-				pluginInstance.onGenerateOnce();
-				pluginInstance.onGenerateOnce = null;
+		} catch(e) { }
+	},
+	/*
+	 * Flag indicating whether the framework is inside a tab or inline element that may be hidden
+	 * Should be set in config
+	 */
+	isNested: false,
+	/*
+	 * All nested tabs and inline levels in the sorting order they were applied
+	 * Should be set in config
+	 */
+	nestedParentElements: {},
+	/*
+	 * Set designMode
+	 *
+	 * @param	boolean		on: if true set designMode to on, otherwise set to off
+	 *
+	 * @rturn	void
+	 */
+	setDesignMode: function (on) {
+		if (on) {
+	 		if (!Ext.isIE) {
+				if (Ext.isGecko) {
+						// In Firefox, we can't set designMode when we are in a hidden TYPO3 tab or inline element
+					if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+						this.document.designMode = 'on';
+						this.setOptions();
+					}
+				} else {
+					this.document.designMode = 'on';
+					this.setOptions();
+				}
 			}
-			if (typeof(pluginInstance.onKeyPress) === "function") {
-				editor._hasPluginWithOnKeyPressHandler = true;
+			if (Ext.isIE || Ext.isWebKit) {
+				this.document.body.contentEditable = true;
 			}
+		} else {
+	 		if (!Ext.isIE) {
+	 			this.document.designMode = 'off';
+	 		}
+	 		if (Ext.isIE || Ext.isWebKit) {
+	 			this.document.body.contentEditable = false;
+	 		}
+	 	}
+	},
+	/*
+	 * Set editing mode options (if we can... raises exception in Firefox 3)
+	 *
+	 * @return	void
+	 */
+	setOptions: function () {
+		if (!Ext.isIE) {
+			try {
+				if (this.document.queryCommandEnabled('insertbronreturn')) {
+					this.document.execCommand('insertbronreturn', false, this.config.disableEnterParagraphs);
+				}
+				if (this.document.queryCommandEnabled('styleWithCSS')) {
+					this.document.execCommand('styleWithCSS', false, this.config.useCSS);
+				} else if (Ext.isGecko && this.document.queryCommandEnabled('useCSS')) {
+					this.document.execCommand('useCSS', false, !this.config.useCSS);
+				}
+				if (Ext.isGecko) {
+					if (this.document.queryCommandEnabled('enableObjectResizing')) {
+						this.document.execCommand('enableObjectResizing', false, !this.config.disableObjectResizing);
+					}
+					if (this.document.queryCommandEnabled('enableInlineTableEditing')) {
+						this.document.execCommand('enableInlineTableEditing', false, (this.config.buttons.table && this.config.buttons.table.enableHandles) ? true : false);
+					}
+				}
+			} catch(e) {}
 		}
-	}
-	if (typeof(editor.onGenerate) === "function") {
-		editor.onGenerate();
-		editor.onGenerate = null;
-	}
-	HTMLArea._appendToLog("[HTMLArea::initIframe]: All plugins successfully generated.");
-		// Size the iframe
-	editor.sizeIframe(2);
-		// Focus on the first editor instance
-	for (var editorId in RTEarea) {
-		if (RTEarea.hasOwnProperty(editorId)) {
-			if (RTEarea[editorId].editor) {
-				if (editorNumber == editorId) {
-					editor.focusEditor();
+	},
+	/*
+	 * Handler invoked when an hidden TYPO3 hidden nested tab or inline element is shown
+	 */
+	onNestedShow: function (event, target) {
+		var styleEvent = true;
+			// In older versions of Mozilla ev.attrName is not yet set and refering to it causes a non-catchable crash
+			// We are assuming that this was fixed in Firefox 2.0.0.11
+		if (navigator.productSub > 20071127) {
+			styleEvent = (event.browserEvent.attrName == 'style');
+		}
+		if (styleEvent && this.nestedParentElements.sorted.indexOf(target.id) != -1 && this.getEditor().getMode() === 'wysiwyg' && (target.style.display == '' || target.style.display == 'block')) {
+				// Check if all affected nested elements are displayed (style.display!='none'):
+			if (HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+				this.setDesignMode(true);
+				this.getEditor().updateToolbar();
+			}
+		}
+		event.stopEvent();
+	},
+	/*
+	 * Get the HTML content of the iframe
+	 */
+	getHTML: function () {
+		return HTMLArea.getHTML(this.document.body, false, this.getEditor());
+	},
+	/*
+	 * Start listening to things happening in the iframe
+	 */
+	startListening: function () {
+		var documentElement = Ext.get(Ext.isIE ? this.document.body : this.document.documentElement);
+			// Create keyMap so that plugins may bind key handlers
+		this.keyMap = new Ext.KeyMap(documentElement, [], (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress');
+			// Special keys map
+		this.keyMap.addBinding([
+			{
+				key: [Ext.EventObject.DOWN, Ext.EventObject.UP, Ext.EventObject.LEFT, Ext.EventObject.RIGHT],
+				alt: false,
+				handler: this.onArrow,
+				scope: this
+			},
+			{
+				key: Ext.EventObject.TAB,
+				ctrl: false,
+				alt: false,
+				handler: this.onTab,
+				scope: this
+			},
+			{
+				key: [Ext.EventObject.BACKSPACE, Ext.EventObject.DELETE],
+				alt: false,
+				handler: this.onBackSpace,
+				scope: this
+			},
+			{
+				key: Ext.EventObject.SPACE,
+				ctrl: true,
+				shift: false,
+				alt: false,
+				handler: this.onCtrlSpace,
+				scope: this
+			}
+		]);
+		if (!Ext.isIE && !this.config.disableEnterParagraphs) {
+			this.keyMap.addBinding(
+			{
+				key: Ext.EventObject.ENTER,
+				shift: false,
+				handler: this.onEnter,
+				scope: this
+			});
+		}
+		if (Ext.isWebKit) {
+			this.keyMap.addBinding(
+			{
+				key: Ext.EventObject.ENTER,
+				alt: false,
+				handler: this.onWebKitEnter,
+				scope: this
+			});
+		}
+			// Hot key map (on keydown for all brwosers)
+		var hotKeys = '';
+		Ext.iterate(this.config.hotKeyList, function (key) {
+			if (key.length == 1) {
+				hotKeys += key.toUpperCase();
+			}
+		});
+		if (!Ext.isEmpty(hotKeys)) {
+			this.hotKeyMap = new Ext.KeyMap(documentElement,
+			{
+				key: hotKeys,
+				ctrl: true,
+				shift: false,
+				alt: false,
+				handler: this.onHotKey,
+				scope: this
+			});
+		}
+		this.mon(documentElement, (Ext.isIE || Ext.isWebKit) ? 'keydown' : 'keypress', this.onAnyKey, this);
+		this.mon(documentElement, 'mouseup', this.onMouse, this);
+		Ext.EventManager.on(this.document,  'mouseup', this.onMouse, this);
+		this.mon(documentElement, 'drag', this.onMouse, this);
+	},
+	/*
+	 * Handler for other key events
+	 */
+	onAnyKey: function(event) {
+			// In Opera, inhibit key events while synchronous XMLHttpRequest is being processed
+		if (Ext.isOpera && HTMLArea.pendingSynchronousXMLHttpRequest) {
+			event.stopEvent();
+			return false;
+		}
+			// onKeyPress deprecated as of TYPO3 4.4
+		if (this.getEditor().hasPluginWithOnKeyPressHandler) {
+			var letBubble = true;
+			Ext.iterate(this.getEditor().plugins, function (pluginId) {
+				var plugin = this.getEditor().getPlugin(pluginId);
+				if (Ext.isFunction(plugin.onKeyPress)) {
+					if (!plugin.onKeyPress(event.browserEvent)) {
+						event.stopEvent();
+						letBubble = false;
+					}
 				}
-				break;
+				return letBubble;
+			}, this);
+			if (!letBubble) {
+				return letBubble;
 			}
 		}
+		if (!event.altKey && !event.ctrlKey) {
+				// Detect URL in non-IE browsers
+			if (!Ext.isIE) {
+				this.getEditor()._detectURL(event);
+			}
+				// Handle option+SPACE for Mac users
+			if (Ext.isMac && event.browserEvent.charCode == 160) {
+				return this.onOptionSpace(event.browserEvent.charCode, event);
+			}
+		}
+		return true;
+	},
+	/*
+	 * Handler for mouse events
+	 */
+	onMouse: function () {
+		this.getToolbar().updateLater.delay(100);
+		return true;
+	},
+	/*
+	 * Handler for UP, DOWN, LEFT and RIGHT keys
+	 */
+	onArrow: function () {
+		this.getToolbar().updateLater.delay(100);
+		return true;
+	},
+	/*
+	 * Handler for TAB and SHIFT-TAB keys
+	 *
+	 * If available, BlockElements plugin will handle the TAB key
+	 */
+	onTab: function (key, event) {
+		var keyName = (event.shiftKey ? 'SHIFT-' : '') + 'TAB';
+		if (this.config.hotKeyList[keyName] && this.config.hotKeyList[keyName].cmd) {
+			var button = this.getButton(this.config.hotKeyList[keyName].cmd);
+			if (button) {
+				event.stopEvent();
+				button.fireEvent('hotkey', keyName, event);
+				return false;
+			}
+		}
+		return true;
+	},
+	/*
+	 * Handler for BACKSPACE and DELETE keys
+	 */
+	onBackSpace: function (key, event) {
+		if ((!Ext.isIE && !event.shiftKey) || Ext.isIE) {
+			if (this.getEditor()._checkBackspace()) {
+				event.stopEvent();
+			}
+		}
+			// Update the toolbar state after some time
+		this.getToolbar().updateLater.delay(200);
+		return false;
+	},
+	/*
+	 * Handler for ENTER key in non-IE browsers
+	 */
+	onEnter: function (key, event) {
+		if (!event.shiftKey) {
+			if (this.getEditor()._checkInsertP()) {
+				event.stopEvent();
+			}
+		}
+			// Update the toolbar state after some time
+		this.getToolbar().updateLater.delay(200);
+		return false;
+	},
+	/*
+	 * Handler for ENTER key in WebKit browsers
+	 */
+	onWebKitEnter: function (key, event) {
+		if (event.shiftKey || this.config.disableEnterParagraphs) {
+			var brNode = this.document.createElement('br');
+			this.getEditor().insertNodeAtSelection(brNode);
+			if (!brNode.nextSibling || !HTMLArea.getInnerText(brNode.nextSibling)) {
+				var secondBrNode = this.document.createElement('br');
+				secondBrNode = brNode.parentNode.appendChild(secondBrNode);
+				this.getEditor().selectNode(secondBrNode, false);
+			}
+			event.stopEvent();
+		}
+			// Update the toolbar state after some time
+		this.getToolbar().updateLater.delay(200);
+		return false;
+	},
+	/*
+	 * Handler for CTRL-SPACE keys
+	 */
+	onCtrlSpace: function (key, event) {
+		this.getEditor().insertHTML('&nbsp;');
+		event.stopEvent();
+		return false;
+	},
+	/*
+	 * Handler for OPTION-SPACE keys on Mac
+	 */
+	onOptionSpace: function (key, event) {
+		this.getEditor().insertHTML('&nbsp;');
+		event.stopEvent();
+		return false;
+	},
+	/*
+	 * Handler for configured hotkeys
+	 */
+	onHotKey: function (key, event) {
+		var hotKey = String.fromCharCode(key).toLowerCase();
+		this.getButton(this.config.hotKeyList[hotKey].cmd).fireEvent('hotkey', hotKey, event);
+		return false;
+	},
+	/*
+	 * Cleanup
+	 */
+	onBeforeDestroy: function () {
+		this.keyMap.disable();
+		this.hotKeyMap.disable();
 	}
-	editor.updateToolbar();
-};
-
+});
+Ext.reg('htmlareaiframe', HTMLArea.Iframe);
 /*
- * When we have a form, on reset, re-initialize the HTMLArea content and update the toolbar
+ * HTMLArea.StatusBar extends Ext.Container
  */
-HTMLArea.resetHandler = function(ev) {
-	if(!ev) var ev = window.event;
-	var form = (ev.target) ? ev.target : ev.srcElement;
-	var editor = RTEarea[form._editorNumber]["editor"];
-	editor.getPluginInstance("EditorMode").setHTML(editor._textArea.value);
-	editor.updateToolbar();
-	var a = form.__msh_prevOnReset;
-		// call previous reset methods if they were there.
-	if (typeof(a) != "undefined") {
-		for (var i=a.length; --i >= 0; ) { a[i](); }
-	}
-};
-
-/*
- * Clean up event handlers and object references, undo/redo snapshots, update the textarea for submission
- */
-HTMLArea.removeEditorEvents = function(ev) {
-	if (!ev) var ev = window.event;
-	HTMLArea._stopEvent(ev);
-	if (HTMLArea._eventCache) {
-		HTMLArea._eventCache.flush();
-	}
-	for (var editorNumber in RTEarea) {
-		if (RTEarea.hasOwnProperty(editorNumber)) {
-			var editor = RTEarea[editorNumber].editor;
-			if (editor) {
-				RTEarea[editorNumber].editor = null;
-					// save the HTML content into the original textarea for submit, back/forward, etc.
-				editor._textArea.value = editor.getPluginInstance("EditorMode").getHTML();
-					// do final cleanup
-				HTMLArea.cleanup(editor);
+HTMLArea.StatusBar = Ext.extend(Ext.Container, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		HTMLArea.StatusBar.superclass.initComponent.call(this);
+		this.addListener({
+			render: {
+				fn: this.addComponents,
+				single: true
+			},
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
 			}
+		});
+	},
+	/*
+	 * Initialize listeners
+	 */
+	initEventListeners: function () {
+		this.addListener({
+			beforedestroy: {
+				fn: this.clear,
+				single: true
+			}
+		});
+			// Monitor toolbar updates in order to refresh the contents of the statusbar
+			// The toolbar must have been rendered
+		this.mon(this.ownerCt.toolbar, 'update', this.onUpdateToolbar, this);
+			// Monitor editor changing mode
+		this.mon(this.getEditor(), 'modeChange', this.onModeChange, this);
+	},
+	/*
+	 * editorId should be set in config
+	 */
+	editorId: null,
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.editorId].editor;
+	},
+	/*
+	 * Create span elements to display when the status bar tree or a message when the editor is in text mode
+	 */
+	addComponents: function () {
+		this.statusBarTree = Ext.DomHelper.append(this.getEl(), {
+			id: this.editorId + '-statusBarTree',
+			tag: 'span',
+			cls: 'statusBarTree',
+			html: HTMLArea.I18N.msg['Path'] + ': '
+		}, true).setVisibilityMode(Ext.Element.DISPLAY).setVisible(true);
+		this.statusBarTextMode = Ext.DomHelper.append(this.getEl(), {
+			id: this.editorId + '-statusBarTextMode',
+			tag: 'span',
+			cls: 'statusBarTextMode',
+			html: HTMLArea.I18N.msg['TEXT_MODE']
+		}, true).setVisibilityMode(Ext.Element.DISPLAY).setVisible(false);
+	},
+	/*
+	 * Clear the status bar tree
+	 */
+	clear: function () {
+		this.statusBarTree.removeAllListeners();
+		Ext.each(this.statusBarTree.query('a'), function (node) {
+			Ext.QuickTips.unregister(node);
+		});
+		this.statusBarTree.update('');
+		this.setSelection(null);
+	},
+	/*
+	 * Flag indicating that the status bar should not be updated on this toolbar update
+	 */
+	noUpdate: false,
+	/*
+	 * Update the status bar
+	 */
+	onUpdateToolbar: function (mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		if (mode === 'wysiwyg' && !this.noUpdate) {
+			var text,
+				language,
+				languageObject = this.getEditor().getPlugin('Language'),
+				classes = new Array(),
+				classText;
+			this.clear();
+			var path = Ext.DomHelper.append(this.statusBarTree, {
+				tag: 'span',
+				html: HTMLArea.I18N.msg['Path'] + ': '
+			},true);
+			Ext.each(ancestors, function (ancestor, index) {
+				if (!ancestor) {
+					return true;
+				}
+				text = ancestor.nodeName.toLowerCase();
+					// Do not show any id generated by ExtJS
+				if (ancestor.id && text !== 'body' && ancestor.id.substr(0, 7) !== 'ext-gen') {
+					text += '#' + ancestor.id;
+				}
+				if (languageObject && languageObject.getLanguageAttribute) {
+					language = languageObject.getLanguageAttribute(ancestor);
+					if (language != 'none') {
+						text += '[' + language + ']';
+					}
+				}
+				if (ancestor.className) {
+					classText = '';
+					classes = ancestor.className.trim().split(' ');
+					for (var j = 0, n = classes.length; j < n; ++j) {
+						if (!HTMLArea.reservedClassNames.test(classes[j])) {
+							classText += '.' + classes[j];
+						}
+					}
+					text += classText;
+				}
+				var element = Ext.DomHelper.insertAfter(path, {
+					tag: 'a',
+					href: '#',
+					'ext:qtitle': HTMLArea.I18N.dialogs['statusBarStyle'],
+					'ext:qtip': ancestor.style.cssText.split(';').join('<br />'),
+					html: text
+				}, true);
+					// Ext.DomHelper does not honour the custom attribute
+				element.dom.ancestor = ancestor;
+				if (Ext.isIE) {
+					element.on('click', this.onClick, this);
+				} else {
+					element.on('mousedown', this.onMouseDown, this);
+				}
+				if (!Ext.isOpera) {
+					element.on('contextmenu', this.onContextMenu, this);
+				}
+				if (index) {
+					Ext.DomHelper.insertAfter(element, {
+						tag: 'span',
+						html: String.fromCharCode(0xbb)
+					});
+				}
+			}, this);
 		}
+		this.noUpdate = false;
+	},
+	/*
+	 * Adapt status bar to current editor mode
+	 *
+	 * @param	string	mode: the mode to which the editor got switched to
+	 */
+	onModeChange: function (mode) {
+		switch (mode) {
+			case 'wysiwyg':
+				this.statusBarTextMode.setVisible(false);
+				this.statusBarTree.setVisible(true);
+				break;
+			case 'textmode':
+			default:
+				this.statusBarTree.setVisible(false);
+				this.statusBarTextMode.setVisible(true);
+				break;
+		}
+	},
+	/*
+	 * Refrence to the element last selected on the status bar
+	 */
+	selected: null,
+	/*
+	 * Get the status bar selection
+	 */
+	getSelection: function() {
+		return this.selected;
+	},
+	/*
+	 * Set the status bar selection
+	 *
+	 * @param	object	element: set the status bar selection to the given element
+	 */
+	setSelection: function(element) {
+		this.selected = element ? element : null;
+	},
+	/*
+	 * Select the element that was clicked in the status bar and set the status bar selection
+	 */
+	selectElement: function (element) {
+		var editor = this.getEditor();
+		element.blur();
+		if (!Ext.isIE) {
+			editor.selectNodeContents(element.ancestor);
+		} else {
+			var nodeName = element.ancestor.nodeName.toLowerCase();
+			if (nodeName == 'table' || nodeName == 'img') {
+				var range = editor.document.body.createControlRange();
+				range.addElement(element.ancestor);
+				range.select();
+			} else {
+				editor.selectNode(element.ancestor);
+			}
+		}
+		this.setSelection(element.ancestor);
+		this.noUpdate = true;
+		editor.toolbar.update();
+	},
+	/*
+	 * Click handler
+	 */
+	onClick: function (event, element) {
+		this.selectElement(element);
+		event.stopEvent();
+		return false;
+	},
+	/*
+	 * MouseDown handler
+	 */
+	onMouseDown: function (event, element) {
+		this.selectElement(element);
+		if (Ext.isIE) {
+			return true;
+		} else {
+			event.stopEvent();
+			return false;
+		}
+	},
+	/*
+	 * ContextMenu handler
+	 */
+	onContextMenu: function (event, target) {
+		this.selectElement(target);
+		return this.getEditor().getPlugin('ContextMenu') ? this.getEditor().getPlugin('ContextMenu').show(event, target.ancestor) : false;
 	}
-};
-
+});
+Ext.reg('htmlareastatusbar', HTMLArea.StatusBar);
 /*
- * Clean up a bunch of references in order to avoid memory leakages mainly in IE, but also in Firefox and Opera
+ * HTMLArea.Framework extends Ext.Panel
  */
-HTMLArea.cleanup = function (editor) {
-		// nullify envent handlers
-	for (var handler in editor.eventHandlers) {
-		if (editor.eventHandlers.hasOwnProperty(handler)) {
-			editor.eventHandlers[handler] = null;
+HTMLArea.Framework = Ext.extend(Ext.Panel, {
+	/*
+	 * Constructor
+	 */
+	initComponent: function () {
+		HTMLArea.Framework.superclass.initComponent.call(this);
+			// Set some references
+		this.toolbar = this.getTopToolbar();
+		this.statusBar = this.getBottomToolbar();
+		this.iframe = this.getComponent('iframe');
+		this.textAreaContainer = this.getComponent('textAreaContainer');
+		this.addEvents(
+			/*
+			 * @event frameworkready
+			 * Fires when the iframe is ready and all components are rendered
+			 */
+			'frameworkready'
+		);
+		this.addListener({
+			afterrender: {
+				fn: this.initEventListeners,
+				single: true
+			}
+		});
+			// Let the framefork render itself, but it will fail to do so if inside a hidden tab or inline element
+		if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+			this.render(this.textArea.parent(), this.textArea.id);
+		} else {
+				// Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+			var parentElements = [].concat(this.nestedParentElements.sorted);
+				// Walk through all nested tabs and inline levels to get correct sizes
+			HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].render(args[0].textArea.parent(), args[0].textArea.id)', [this]);
 		}
-	}
-	for (var button in editor.btnList) {
-		if (editor.btnList.hasOwnProperty(button)) {
-			editor.btnList[button][3] = null;
+	},
+	/*
+	 * Initiate events monitoring
+	 */
+	initEventListeners: function () {
+			// Monitor iframe becoming ready
+		this.mon(this.iframe, 'iframeready', this.onIframeReady, this, {single: true});
+			// Make the framework resizable, if configured by the user
+		this.makeResizable();
+			// Monitor textArea container becoming shown or hidden as it may change the height of the status bar
+		this.mon(this.textAreaContainer, 'show', this.onTextAreaShow, this);
+		if (this.resizable) {
+				// Monitor iframe becoming shown or hidden as it may change the height of the status bar
+			this.mon(this.iframe, 'show', this.onIframeShow, this);
 		}
-	}
-	for (var dropdown in editor.config.customSelects) {
-		if (editor.config.customSelects.hasOwnProperty(dropdown)) {
-			editor.config.customSelects[dropdown].action = null;
-			editor.config.customSelects[dropdown].refresh = null;
+			// Monitor window resizing
+		if (this.resizable || this.textAreaInitialSize.width.indexOf('%') !== -1) {
+			Ext.EventManager.onWindowResize(this.onWindowResize, this);
 		}
-	}
-	for (var hotKey in editor.config.hotKeyList) {
-		if (editor.config.customSelects.hasOwnProperty(hotKey)) {
-			editor.config.hotKeyList[hotKey].action = null;
+			// If the textarea is inside a form, on reset, re-initialize the HTMLArea content and update the toolbar
+		var form = this.textArea.dom.form;
+		if (form) {
+			if (Ext.isFunction(form.onsubmit)) {
+				if (typeof(form.htmlAreaPreviousOnReset) == 'undefined') {
+					form.htmlAreaPreviousOnReset = [];
+				}
+				form.htmlAreaPreviousOnReset.push(form.onreset);
+			}
+			this.mon(Ext.get(form), 'reset', this.onReset, this);
 		}
+		this.addListener({
+			beforedestroy: {
+				fn: this.onBeforeDestroy
+			}
+		});
+	},
+	/*
+	 * editorId should be set in config
+	 */
+	editorId: null,
+	/*
+	 * Get a reference to the editor
+	 */
+	getEditor: function() {
+		return RTEarea[this.editorId].editor;
+	},
+	/*
+	 * Flag indicating whether the framework is inside a tab or inline element that may be hidden
+	 * Should be set in config
+	 */
+	isNested: false,
+	/*
+	 * All nested tabs and inline levels in the sorting order they were applied
+	 * Should be set in config
+	 */
+	nestedParentElements: {},
+	/*
+	 * Flag set to true when the framework is ready
+	 */
+	ready: false,
+	/*
+	 * All nested tabs and inline levels in the sorting order they were applied
+	 * Should be set in config
+	 */
+	nestedParentElements: {},
+	/*
+	 * Whether the framework should be made resizable
+	 * May be set in config
+	 */
+	resizable: false,
+	/*
+	 * Maximum height to which the framework may resized (in pixels)
+	 * May be set in config
+	 */
+	maxHeight: 2000,
+	/*
+	 * Initial textArea dimensions
+	 * Should be set in config
+	 */
+	textAreaInitialSize: {
+		width: 0,
+		contextWidth: 0,
+		height: 0
+	},
+	/*
+	 * Make the framework resizable, if configured
+	 */
+	makeResizable: function () {
+		if (this.resizable) {
+			this.addClass('resizable');
+			this.resizer = new Ext.Resizable(this.getEl(), {
+				minWidth: 300,
+				maxHeight: this.maxHeight,
+				dynamic: false
+			});
+			this.resizer.on('resize', this.onHtmlAreaResize, this);
+		}
+	},
+	/*
+	 * Size the iframe according to initial textarea size as set by Page and User TSConfig
+	 */
+	onWindowResize: function(width, height) {
+		if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+			this.resizeFramework(width, height);
+		} else {
+				// Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+			var parentElements = [].concat(this.nestedParentElements.sorted);
+				// Walk through all nested tabs and inline levels to get correct sizes
+			HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].resizeFramework(args[1], args[2])', [this, width, height]);
+		}
+	},
+	/*
+	 * Resize the framework to its initial size
+	 */
+	resizeFramework: function (width, height) {
+		var frameworkHeight = this.fullScreen ? HTMLArea.util.TYPO3.getWindowSize().height - 20 : parseInt(this.textAreaInitialSize.height);
+		if (this.textAreaInitialSize.width.indexOf('%') === -1) {
+				// Width is specified in pixels
+			var frameworkWidth = parseInt(this.textAreaInitialSize.width) - this.getFrameWidth();
+		} else {
+				// Width is specified in %
+			if (Ext.isDefined(width)) {
+					// Framework sizing on actual window resize
+				var frameworkWidth = parseInt(((width - this.textAreaInitialSize.nextSiblingWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+			} else {
+					// Initial framework sizing
+				var frameworkWidth = parseInt(((HTMLArea.util.TYPO3.getWindowSize().width - this.textAreaInitialSize.nextSiblingWidth - (this.fullScreen ? 10 : Ext.getScrollBarWidth()) - this.getBox().x - 15) * parseInt(this.textAreaInitialSize.width))/100);
+			}
+		}
+		if (this.resizable) {
+			this.resizer.resizeTo(frameworkWidth, frameworkHeight);
+		} else {
+			this.setSize(frameworkWidth, frameworkHeight);
+				// Adjust height of iframe and textarea to height of toolbar and statusbar
+			this.iframe.setSize(this.getInnerWidth(), this.getInnerHeight());
+			this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
+		}
+	},
+	/*
+	 * Resize the components when the editor framework was resized
+	 */
+	onHtmlAreaResize: function (resizer, width, height, event) {
+			// Set width first as it may change the height of the toolbar and of the statusBar
+		this.setWidth(width);
+			// Set height of iframe and textarea
+		this.iframe.setHeight(this.getInnerHeight());
+		this.textArea.setSize(this.getInnerWidth(), this.getInnerHeight());
+	},
+	/*
+	 * Adjust the height to the changing size of the statusbar when the textarea is shown
+	 */
+	onTextAreaShow: function () {
+		this.iframe.setHeight(this.getInnerHeight());
+		this.textArea.setHeight(this.getInnerHeight());
+	},
+	/*
+	 * Adjust the height to the changing size of the statusbar when the iframe is shown
+	 */
+	onIframeShow: function () {
+		this.iframe.setHeight(this.getInnerHeight());
+		this.textArea.setHeight(this.getInnerHeight());
+	},
+	/*
+	 * Fire the editor when all components of the framework are rendered and ready
+	 */
+	onIframeReady: function () {
+		this.ready = this.toolbar.rendered && this.statusBar.rendered && this.textAreaContainer.rendered;
+		if (this.ready) {
+			this.textAreaContainer.show();
+			if (!this.getEditor().config.showStatusBar) {
+				this.statusBar.hide();
+			}
+				// Set the initial size of the framework
+			this.onWindowResize();
+			this.fireEvent('frameworkready');
+		} else {
+			this.onIframeReady.defer(50, this);
+		}
+	},
+	/*
+	 * Handler invoked if we are inside a form and the form is reset
+	 * On reset, re-initialize the HTMLArea content and update the toolbar
+	 */
+	onReset: function (event) {
+		this.getEditor().setHTML(this.textArea.getValue());
+		this.toolbar.update();
+			// Invoke previous reset handlers, if any
+		var htmlAreaPreviousOnReset = event.getTarget().dom.htmlAreaPreviousOnReset;
+		if (typeof(htmlAreaPreviousOnReset) != 'undefined') {
+			Ext.each(htmlAreaPreviousOnReset, function (onReset) {
+				onReset();
+				return true;
+			});
+		}
+	},
+	/*
+	 * Cleanup on framework destruction
+	 */
+	onBeforeDestroy: function () {
+		if (this.resizable) {
+			Ext.EventManager.removeResizeListener(this.onWindowResize, this);
+		}
+		var form = this.textArea.dom.form;
+		if (form) {
+			form.htmlAreaPreviousOnReset = null;
+		}
 	}
-	editor.onGenerate = null;
-	if(editor._textArea.form) {
-		editor._textArea.form.__msh_prevOnReset = null;
-		editor._textArea.form._editorNumber = null;
-	}
-
-		// cleaning plugins
-	for (var plugin in editor.plugins) {
-		if (editor.plugins.hasOwnProperty(plugin)) {
-			var pluginInstance = editor.plugins[plugin].instance;
-			if (typeof(pluginInstance.onClose) === "function") {
-				pluginInstance.onClose();
+});
+Ext.reg('htmlareaframework', HTMLArea.Framework);
+/***************************************************
+ *  HTMLArea.Editor extends Ext.util.Observable
+ ***************************************************/
+HTMLArea.Editor = Ext.extend(Ext.util.Observable, {
+	/*
+	 * HTMLArea.Editor constructor
+	 */
+	constructor: function (config) {
+		HTMLArea.Editor.superclass.constructor.call(this, {});
+			// Save the config
+		this.config = config;
+			// Establish references to this editor
+		this.editorId = this.config.editorId;
+		RTEarea[this.editorId].editor = this;
+			// Get textarea size and wizard context
+		this.textArea = Ext.get(this.config.id);
+		this.textAreaInitialSize = {
+			width: this.config.RTEWidthOverride ? this.config.RTEWidthOverride : this.textArea.getStyle('width'),
+			height: this.config.fullScreen ? HTMLArea.util.TYPO3.getWindowSize().height - 20 : this.textArea.getStyle('height'),
+			nextSiblingWidth: 0
+		};
+			// TYPO3 Inline elements and tabs
+		this.nestedParentElements = {
+			all: this.config.tceformsNested,
+			sorted: HTMLArea.util.TYPO3.simplifyNested(this.config.tceformsNested)
+		};
+		this.isNested = !Ext.isEmpty(this.nestedParentElements.sorted);
+			// Get width of wizards
+		var nextSibling = this.textArea.parent().parent().next();
+		if (nextSibling) {
+			if (!this.isNested || HTMLArea.util.TYPO3.allElementsAreDisplayed(this.nestedParentElements.sorted)) {
+				this.textAreaInitialSize.nextSiblingWidth = nextSibling.getWidth();
+			} else {
+					// Clone the array of nested tabs and inline levels instead of using a reference as HTMLArea.util.TYPO3.accessParentElements will modify the array
+				var parentElements = [].concat(this.nestedParentElements.sorted);
+					// Walk through all nested tabs and inline levels to get correct size
+					this.textAreaInitialSize.nextSiblingWidth = HTMLArea.util.TYPO3.accessParentElements(parentElements, 'args[0].getWidth()', [nextSibling]);
 			}
-			pluginInstance.onClose = null;
-			pluginInstance.onChange = null;
-			pluginInstance.onButtonPress = null;
-			pluginInstance.onGenerate = null;
-			pluginInstance.onGenerateOnce = null;
-			pluginInstance.onMode = null;
-			pluginInstance.onHotKey = null;
-			pluginInstance.onKeyPress = null;
-			pluginInstance.onSelect = null;
-			pluginInstance.onUpdateTolbar = null;
 		}
+			// Plugins register
+		this.plugins = {};
+			// Register the plugins included in the configuration
+		Ext.iterate(this.config.plugin, function (plugin) {
+			if (this.config.plugin[plugin]) {
+				this.registerPlugin(plugin);
+			}
+		}, this);
+		this.addEvents(
+			/*
+			 * @event editorready
+			 * Fires when initializatio of the editor is complete
+			 */
+			'editorready',
+			/*
+			 * @event modeChange
+			 * Fires when the editor changes mode
+			 */
+			'modeChange'
+		);
+	},
+	/*
+	 * Flag set to true when the editor initialization has completed
+	 */
+	ready: false,
+	/*
+	 * The current mode of the editor: 'wysiwyg' or 'textmode'
+	 */
+	mode: 'textmode',
+	/*
+	 * Create the htmlArea framework
+	 */
+	generate: function () {
+			// Create the editor framework
+		this.htmlArea = new HTMLArea.Framework({
+			id: this.editorId + '-htmlArea',
+			layout: 'anchor',
+			baseCls: 'htmlarea',
+			editorId: this.editorId,
+			textArea: this.textArea,
+			textAreaInitialSize: this.textAreaInitialSize,
+			fullScreen: this.config.fullScreen,
+			resizable: this.config.resizable,
+			maxHeight: this.config.maxHeight,
+			isNested: this.isNested,
+			nestedParentElements: this.nestedParentElements,
+				// The toolbar
+			tbar: {
+				xtype: 'htmlareatoolbar',
+				id: this.editorId + '-toolbar',
+				anchor: '100%',
+				layout: 'form',
+				cls: 'toolbar',
+				editorId: this.editorId
+			},
+			items: [{
+						// The iframe
+					xtype: 'htmlareaiframe',
+					itemId: 'iframe',
+					anchor: '100%',
+					width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+					height: parseInt(this.textAreaInitialSize.height),
+					autoEl: {
+						id: this.editorId + '-iframe',
+						tag: 'iframe',
+						cls: 'editorIframe',
+						src: Ext.isGecko ? 'javascript:void(0);' : (Ext.isOpera ? _typo3_host_url : '') + _editor_url + 'popups/blank.html'
+					},
+					isNested: this.isNested,
+					nestedParentElements: this.nestedParentElements,
+					editorId: this.editorId
+				},{
+						// Box container for the textarea
+					xtype: 'box',
+					itemId: 'textAreaContainer',
+					anchor: '100%',
+					width: (this.textAreaInitialSize.width.indexOf('%') === -1) ? parseInt(this.textAreaInitialSize.width) : 300,
+						// Let the framework swallow the textarea
+					listeners: {
+						afterRender: {
+							fn: function (textAreaContainer) { textAreaContainer.getEl().appendChild(this.textArea); },
+							single: true,
+							scope: this
+						}
+					}
+				}
+			],
+				// The status bar
+			bbar: {
+				xtype: 'htmlareastatusbar',
+				anchor: '100%',
+				cls: 'statusBar',
+				editorId: this.editorId
+			}
+		});
+			// Set some references
+		this.toolbar = this.htmlArea.getTopToolbar();
+		this.statusBar = this.htmlArea.getBottomToolbar();
+		this.iframe = this.htmlArea.getComponent('iframe');
+		this.textAreaContainer = this.htmlArea.getComponent('textAreaContainer');
+			// Get triggered when the framework becomes ready
+		this.relayEvents(this.htmlArea, 'frameworkready');
+		this.on('frameworkready', this.onFrameworkReady, this, {single: true});
+	},
+	/*
+	 * Initialize the editor
+	 */
+	onFrameworkReady: function () {
+			// Initialize editor mode
+		this.setMode('wysiwyg');
+			// Initiate events listening
+		this.initEventsListening();
+			// Generate plugins
+		this.generatePlugins();
+			// Make the editor visible
+		this.show();
+			// Focus on the first editor that is not hidden
+		Ext.iterate(RTEarea, function (editorId, RTE) {
+			if (!Ext.isDefined(RTE.editor) || (RTE.editor.isNested && !HTMLArea.util.TYPO3.allElementsAreDisplayed(RTE.editor.nestedParentElements.sorted))) {
+				return true;
+			} else {
+				RTE.editor.focus();
+				return false;
+			}
+		}, this);
+		this.ready = true;
+		this.fireEvent('editorready');
+		HTMLArea._appendToLog('[HTMLArea.Editor::start]: Editor ready.');
+	},
+	/*
+	 * Set editor mode
+	 *
+	 * @param	string		mode: 'textmode' or 'wysiwyg'
+	 *
+	 * @return	void
+	 */
+	setMode: function (mode) {
+		switch (mode) {
+			case 'textmode':
+				this.textArea.set({ value: this.getHTML() }, false);
+				this.iframe.setDesignMode(false);
+				this.iframe.hide();
+				this.textAreaContainer.show();
+				this.mode = mode;
+				break;
+			case 'wysiwyg':
+				try {
+					this.document.body.innerHTML = this.getHTML();
+				} catch(e) {
+					HTMLArea._appendToLog('[HTMLArea.Editor::setMode]: The HTML document is not well-formed.');
+					alert(HTMLArea.I18N.msg['HTML-document-not-well-formed']);
+					break;
+				}
+				this.textAreaContainer.hide();
+				this.iframe.show();
+				this.iframe.setDesignMode(true);
+				this.mode = mode;
+				break;
+		}
+		this.fireEvent('modeChange', this.mode);
+		this.focus();
+		Ext.iterate(this.plugins, function(pluginId) {
+			this.getPlugin(pluginId).onMode(this.mode);
+		}, this);
+	},
+	/*
+	 * Get current editor mode
+	 */
+	getMode: function () {
+		return this.mode;
+	},
+	/*
+	 * Retrieve the HTML
+	 * In the case of the wysiwyg mode, the html content is parsed
+	 *
+	 * @return	string		the textual html content from the current editing mode
+	 */
+	getHTML: function () {
+		switch (this.mode) {
+			case 'wysiwyg':
+				return this.iframe.getHTML();
+			case 'textmode':
+				return this.textArea.getValue();
+			default:
+				return '';
+		}
+	},
+	/*
+	 * Retrieve raw HTML
+	 *
+	 * @return	string	the textual html content from the current editing mode
+	 */
+	getInnerHTML: function () {
+		switch (this.mode) {
+			case 'wysiwyg':
+				return this.document.body.innerHTML;
+			case 'textmode':
+				return this.textArea.getValue();
+			default:
+				return '';
+		}
+	},
+	/*
+	 * Replace the html content
+	 *
+	 * @param	string		html: the textual html
+	 *
+	 * @return	void
+	 */
+	setHTML: function (html) {
+		switch (this.mode) {
+			case 'wysiwyg':
+				this.document.body.innerHTML = html;
+				break;
+			case 'textmode':
+				this.textArea.set({ value: html }, false);;
+				break;
+		}
+	},
+	/*
+	 * Generate registered plugins
+	 */
+	generatePlugins: function () {
+		this.hasPluginWithOnKeyPressHandler = false;
+		Ext.iterate(this.plugins, function (pluginId) {
+			var plugin = this.getPlugin(pluginId);
+			plugin.onGenerate();
+				// onKeyPress deprecated as of TYPO3 4.4
+			if (Ext.isFunction(plugin.onKeyPress)) {
+				this.hasPluginWithOnKeyPressHandler = true;
+				HTMLArea._appendToLog('[HTMLArea.Editor::generatePlugins]: Deprecated use of onKeyPress function by plugin ' + pluginId + '. Use keyMap instead.');
+			}
+		}, this);
+		HTMLArea._appendToLog('[HTMLArea.Editor::generatePlugins]: All plugins successfully generated.');
+	},
+	/*
+	 * Get the instance of the specified plugin, if it exists
+	 *
+	 * @param	string		pluginName: the name of the plugin
+	 * @return	object		the plugin instance or null
+	 */
+	getPlugin: function(pluginName) {
+		return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
+	},
+	/*
+	 * Focus on the editor
+	 */
+	focus: function () {
+		switch (this.getMode()) {
+			case 'wysiwyg':
+				this.iframe.focus();
+				break;
+			case 'textmode':
+				this.textArea.focus();
+				break;
+		}
+	},
+	/*
+	 * Add listeners
+	 */
+	initEventsListening: function () {
+		if (Ext.isOpera) {
+			this.iframe.startListening();
+		}
+			// Add unload handler
+		var iframe = this.iframe.getEl().dom;
+		Ext.EventManager.on(iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument, 'unload', this.onUnload, this, {single: true});
+	},
+	/*
+	 * Make the editor framework visible
+	 */
+	show: function () {
+		document.getElementById('pleasewait' + this.editorId).style.display = 'none';
+		document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
+	},
+	/*
+	 * Iframe unload handler: Update the textarea for submission and cleanup
+	 */
+	onUnload: function (event) {;
+			// Save the HTML content into the original textarea for submit, back/forward, etc.
+		if (this.ready) {
+			this.textArea.set({
+				value: this.getHTML()
+			}, false);
+		}
+			// Cleanup
+		Ext.TaskMgr.stopAll();
+		this.htmlArea.destroy();
+		RTEarea[this.editorId].editor = null;
 	}
-		// cleaning the toolbar elements
-	for (var txt in editor._toolbarObjects) {
-		if (editor._toolbarObjects.hasOwnProperty(txt)) {
-			var obj = editor._toolbarObjects[txt];
-			obj.state = null;
-			obj.cmd = null;
-			var element = document.getElementById(obj.elementId);
-			if (element) {
-				element._obj = null;
+});
+/***************************************************
+ * HTMLArea.util.TYPO3: Utility functions for dealing with tabs and inline elements in TYPO3 forms
+ ***************************************************/
+HTMLArea.util.TYPO3 = function () {
+	return {
+		/*
+		 * Simplify the array of nested levels. Create an indexed array with the correct names of the elements.
+		 *
+		 * @param	object		nested: The array with the nested levels
+		 * @return	object		The simplified array
+		 * @author	Oliver Hader <oh@inpublica.de>
+		 */
+		simplifyNested: function(nested) {
+			var i, type, level, max, simplifiedNested=[];
+			if (nested && nested.length) {
+				if (nested[0][0]=='inline') {
+					nested = inline.findContinuedNestedLevel(nested, nested[0][1]);
+				}
+				for (i=0, max=nested.length; i<max; i++) {
+					type = nested[i][0];
+					level = nested[i][1];
+					if (type=='tab') {
+						simplifiedNested.push(level+'-DIV');
+					} else if (type=='inline') {
+						simplifiedNested.push(level+'_fields');
+					}
+				}
 			}
-			editor._toolbarObjects[txt] = null;
+			return simplifiedNested;
+		},
+		/*
+		 * Access an inline relational element or tab menu and make it "accessible".
+		 * If a parent or ancestor object has the style "display: none", offsetWidth & offsetHeight are '0'.
+		 *
+		 * @params	arry		parentElements: array of parent elements id's; note that this input array will be modified
+		 * @params	object		callbackFunc: A function to be called, when the embedded objects are "accessible".
+		 * @params	array		args: array of arguments
+		 * @return	object		An object returned by the callbackFunc.
+		 * @author	Oliver Hader <oh@inpublica.de>
+		 */
+		accessParentElements: function (parentElements, callbackFunc, args) {
+			var result = {};
+			if (parentElements.length) {
+				var currentElement = parentElements.pop();
+				var elementStyle = document.getElementById(currentElement).style;
+				var actionRequired = (elementStyle.display == 'none' ? true : false);
+				if (actionRequired) {
+					var originalVisibility = elementStyle.visibility;
+					var originalPosition = elementStyle.position;
+					elementStyle.visibility = 'hidden';
+					elementStyle.position = 'absolute';
+					elementStyle.display = '';
+				}
+				result = this.accessParentElements(parentElements, callbackFunc, args);
+				if (actionRequired) {
+					elementStyle.display = 'none';
+					elementStyle.position = originalPosition;
+					elementStyle.visibility = originalVisibility;
+				}
+			} else {
+				result = eval(callbackFunc);
+			}
+			return result;
+		},
+		/*
+		 * Check if all elements in input array are currently displayed
+		 *
+		 * @param	array		elements: array of element id's
+		 * @return	boolean		true if all elements are displayed
+		 */
+		allElementsAreDisplayed: function(elements) {
+			var allDisplayed = true;
+			Ext.each(elements, function (element) {
+				allDisplayed = Ext.get(element).getStyle('display') != 'none';
+				return allDisplayed;
+			});
+			return allDisplayed;
+		},
+		/*
+		 * Get current size of window
+		 *
+		 * @return	object		width and height of window
+		 */
+		getWindowSize: function () {
+			if (Ext.isIE) {
+				var size = Ext.getBody().getSize();
+			} else {
+				var size = {
+					width: window.innerWidth,
+					height: window.innerHeight
+				};
+			}
+				// Subtract the docheader height from the calculated window height
+			var docHeader = Ext.get('typo3-docheader');
+			if (docHeader) {
+				size.height -= docHeader.getHeight();
+			}
+			return size;
 		}
 	}
-		// final cleanup
-	editor._toolbar = null;
-	editor._htmlArea = null;
-	editor._iframe = null;
-};
-
-/*
- * Get editor mode
- */
-HTMLArea.prototype.getMode = function() {
-	return this.getPluginInstance("EditorMode").getEditorMode();
-};
-
-/*
- * Initialize iframe content when in full page mode
- */
-HTMLArea.prototype.setFullHTML = function(html) {
-	var save_multiline = RegExp.multiline;
-	RegExp.multiline = true;
-	if(html.match(HTMLArea.RE_doctype)) {
-		this.setDoctype(RegExp.$1);
-		html = html.replace(HTMLArea.RE_doctype, "");
-	};
-	RegExp.multiline = save_multiline;
-	if(!HTMLArea.is_ie) {
-		if(html.match(HTMLArea.RE_head)) this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
-		if(html.match(HTMLArea.RE_body)) this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
-	} else {
-		var html_re = /<html>((.|\n)*?)<\/html>/i;
-		html = html.replace(html_re, "$1");
-		this._doc.open();
-		this._doc.write(html);
-		this._doc.close();
-		this._doc.body.contentEditable = true;
-		return true;
-	};
-};
-
+}();
 /***************************************************
  *  PLUGINS, STYLESHEETS, AND IMAGE AND POPUP URL'S
  ***************************************************/
-
 /*
  * Instantiate the specified plugin and register it with the editor
  *
@@ -1398,7 +2314,7 @@
  *
  * @return	boolean		true if the plugin was successfully registered
  */
-HTMLArea.prototype.registerPlugin = function(plugin) {
+HTMLArea.Editor.prototype.registerPlugin = function(plugin) {
 	var pluginName = plugin;
 	if (typeof(plugin) === "string") {
 		try {
@@ -1429,16 +2345,6 @@
 };
 
 /*
- * Get the instance of the specified plugin, if it exists
- *
- * @param	string		pluginName: the name of the plugin
- * @return	object		the plugin instance or null
- */
-HTMLArea.prototype.getPluginInstance = function(pluginName) {
-	return (this.plugins[pluginName] ? this.plugins[pluginName].instance : null);
-};
-
-/*
  * Load the required plugin script
  */
 HTMLArea.loadPlugin = function (pluginName, url, asynchronous) {
@@ -1468,7 +2374,7 @@
 /*
  * Get the url of some image
  */
-HTMLArea.prototype.imgURL = function(file, plugin) {
+HTMLArea.Editor.prototype.imgURL = function(file, plugin) {
 	if (typeof(plugin) == "undefined") return _editor_skin + this.config.imgURL + file;
 		else return _editor_skin + this.config.imgURL + plugin + "/" + file;
 };
@@ -1476,7 +2382,7 @@
 /*
  * Get the url of some popup
  */
-HTMLArea.prototype.popupURL = function(file) {
+HTMLArea.Editor.prototype.popupURL = function(file) {
 	var url = "";
 	if(file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
 		var pluginId = RegExp.$1;
@@ -1509,36 +2415,22 @@
 	return txt;
 };
 
-HTMLArea.prototype.forceRedraw = function() {
-	this._doc.body.style.visibility = "hidden";
-	this._doc.body.style.visibility = "visible";
+HTMLArea.Editor.prototype.forceRedraw = function() {
+	this.htmlArea.doLayout();
 };
 
 /*
- * Focus the editor iframe document or the textarea.
+ * Focus the editor iframe window or the textarea.
  */
-HTMLArea.prototype.focusEditor = function() {
-	switch (this.getMode()) {
-		case "wysiwyg" :
-			try {
-				if (HTMLArea.is_safari) {
-					this._iframe.focus();
-				} else {
-					this._iframe.contentWindow.focus();
-				}
-			} catch(e) { }
-			break;
-		case "textmode":
-			this._textArea.focus();
-			break;
-	}
-	return this._doc;
+HTMLArea.Editor.prototype.focusEditor = function() {
+	this.focus();
+	return this.document;
 };
 
 /*
  * Check if any plugin has an opened window
  */
-HTMLArea.prototype.hasOpenedWindow = function () {
+HTMLArea.Editor.prototype.hasOpenedWindow = function () {
 	for (var plugin in this.plugins) {
 		if (this.plugins.hasOwnProperty(plugin)) {
 			if (HTMLArea.Dialog[plugin.name] && HTMLArea.Dialog[plugin.name].hasOpenedWindow && HTMLArea.Dialog[plugin.name].hasOpenedWindow()) {
@@ -1548,111 +2440,9 @@
 	}
 	return false
 };
-
-/*
- * Update the enabled/disabled/active state of the toolbar elements
- */
-HTMLArea.updateToolbar = function(editorNumber) {
-	var editor = RTEarea[editorNumber]["editor"];
-	editor.updateToolbar();
-	editor._timerToolbar = null;
+HTMLArea.Editor.prototype.updateToolbar = function(noStatus) {
+	this.toolbar.update(noStatus);
 };
-
-HTMLArea.prototype.updateToolbar = function(noStatus) {
-	var doc = this._doc,
-		initialToolbarHeight = this.getDimensions().toolbar.height,
-		text = (this.getMode() == "textmode"),
-		selection = false,
-		ancestors = null,
-		inContext, match, matchAny, k, j, n, commandState;
-	if (!text) {
-		selection = !this._selectionEmpty(this._getSelection());
-		ancestors = this.getAllAncestors();
-	}
-	for (var cmd in this._toolbarObjects) {
-		if (this._toolbarObjects.hasOwnProperty(cmd)) {
-			var btn = this._toolbarObjects[cmd];
-				// Determine if the button should be enabled
-			inContext = true;
-			if (btn.context && !text) {
-				inContext = false;
-				var attrs = [];
-				var contexts = [];
-				if (/(.*)\[(.*?)\]/.test(btn.context)) {
-					contexts = RegExp.$1.split(",");
-					attrs = RegExp.$2.split(",");
-				} else {
-					contexts = btn.context.split(",");
-				}
-				for (j = contexts.length; --j >= 0;) contexts[j] = contexts[j].toLowerCase();
-				matchAny = (contexts[0] == "*");
-				for (k = 0; k < ancestors.length; ++k) {
-					if (!ancestors[k]) continue;
-					match = false;
-					for (j = contexts.length; --j >= 0;) match = match || (ancestors[k].tagName.toLowerCase() == contexts[j]);
-					if (matchAny || match) {
-						inContext = true;
-						for (j = attrs.length; --j >= 0;) {
-							if (!eval("ancestors[k]." + attrs[j])) {
-								inContext = false;
-								break;
-							}
-						}
-						if (inContext) break;
-					}
-				}
-			}
-
-			if (cmd == "CreateLink") {
-				btn.state("enabled", (!text || btn.text) && (inContext || selection));
-			} else {
-				btn.state("enabled", (!text || btn.text) && inContext && (selection || !btn.selection));
-			}
-			if (typeof(cmd) == "function") { continue; };
-				// look-it-up in the custom dropdown boxes
-			var dropdown = this.config.customSelects[cmd];
-			if ((!text || btn.text) && (typeof(dropdown) !== "undefined") && (typeof(dropdown.refresh) === "function")) {
-				dropdown.refresh(this, cmd);
-				continue;
-			}
-			switch (cmd) {
-				case "TextIndicator":
-					if(!text) {
-						try {with (document.getElementById(btn.elementId).style) {
-							backgroundColor = HTMLArea._makeColor(doc.queryCommandValue((HTMLArea.is_ie || HTMLArea.is_safari) ? "BackColor" : "HiliteColor"));
-								// Mozilla
-							if(/transparent/i.test(backgroundColor)) { backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("BackColor")); }
-							color = HTMLArea._makeColor(doc.queryCommandValue("ForeColor"));
-							fontFamily = doc.queryCommandValue("FontName");
-								// Check if queryCommandState is available
-							fontWeight = "normal";
-							fontStyle = "normal";
-							try { fontWeight = doc.queryCommandState("Bold") ? "bold" : "normal"; } catch(ex) { fontWeight = "normal"; };
-							try { fontStyle = doc.queryCommandState("Italic") ? "italic" : "normal"; } catch(ex) { fontStyle = "normal"; };
-						}} catch (e) {
-							// alert(e + "\n\n" + cmd);
-						}
-					}
-					break;
-				default:
-					break;
-			}
-		}
-	}
-	
-	for (var pluginId in this.plugins) {
-		if (this.plugins.hasOwnProperty(pluginId)) {
-			var pluginInstance = this.plugins[pluginId].instance;
-			if (typeof(pluginInstance.onUpdateToolbar) === "function") {
-				pluginInstance.onUpdateToolbar();
-			}
-		}
-	}
-	if (this.getDimensions().toolbar.height != initialToolbarHeight) {
-		this.sizeIframe(2);
-	}
-};
-
 /***************************************************
  *  DOM TREE MANIPULATION
  ***************************************************/
@@ -1661,15 +2451,15 @@
  * Surround the currently selected HTML source code with the given tags.
  * Delete the selection, if any.
  */
-HTMLArea.prototype.surroundHTML = function(startTag,endTag) {
+HTMLArea.Editor.prototype.surroundHTML = function(startTag,endTag) {
 	this.insertHTML(startTag + this.getSelectedHTML().replace(HTMLArea.Reg_body, "") + endTag);
 };
 
 /*
  * Change the tag name of a node.
  */
-HTMLArea.prototype.convertNode = function(el,newTagName) {
-	var newel = this._doc.createElement(newTagName), p = el.parentNode;
+HTMLArea.Editor.prototype.convertNode = function(el,newTagName) {
+	var newel = this.document.createElement(newTagName), p = el.parentNode;
 	while (el.firstChild) newel.appendChild(el.firstChild);
 	p.insertBefore(newel, el);
 	p.removeChild(el);
@@ -1692,7 +2482,7 @@
  *
  * @return	void
  */
-HTMLArea.prototype.removeMarkup = function(element) {
+HTMLArea.Editor.prototype.removeMarkup = function(element) {
 	var bookmark = this.getBookmark(this._createRange(this._getSelection()));
 	var parent = element.parentNode;
 	while (element.firstChild) {
@@ -1732,28 +2522,28 @@
 /*
  * Return true if we have some selected content
  */
-HTMLArea.prototype.hasSelectedText = function() {
+HTMLArea.Editor.prototype.hasSelectedText = function() {
 	return this.getSelectedHTML() != "";
 };
 
 /*
  * Get an array with all the ancestor nodes of the selection.
  */
-HTMLArea.prototype.getAllAncestors = function() {
+HTMLArea.Editor.prototype.getAllAncestors = function() {
 	var p = this.getParentElement();
 	var a = [];
 	while (p && (p.nodeType === 1) && (p.nodeName.toLowerCase() !== "body")) {
 		a.push(p);
 		p = p.parentNode;
 	}
-	a.push(this._doc.body);
+	a.push(this.document.body);
 	return a;
 };
 
 /*
  * Get the block ancestors of an element within a given block
  */
-HTMLArea.prototype.getBlockAncestors = function(element, withinBlock) {
+HTMLArea.Editor.prototype.getBlockAncestors = function(element, withinBlock) {
 	var ancestors = new Array();
 	var ancestor = element;
 	while (ancestor && (ancestor.nodeType === 1) && !/^(body)$/i.test(ancestor.nodeName) && ancestor != withinBlock) {
@@ -1769,9 +2559,9 @@
 /*
  * Get the block elements containing the start and the end points of the selection
  */
-HTMLArea.prototype.getEndBlocks = function(selection) {
+HTMLArea.Editor.prototype.getEndBlocks = function(selection) {
 	var range = this._createRange(selection);
-	if (HTMLArea.is_gecko) {
+	if (!Ext.isIE) {
 		var parentStart = range.startContainer;
 		var parentEnd = range.endContainer;
 	} else {
@@ -1802,7 +2592,7 @@
  *
  * @return	boolean	true if the end points of the current selection are inside the same block element
  */
-HTMLArea.prototype.endPointsInSameBlock = function() {
+HTMLArea.Editor.prototype.endPointsInSameBlock = function() {
 	var selection = this._getSelection();
 	if (this._selectionEmpty(selection)) {
 		return true;
@@ -1817,11 +2607,11 @@
  * Get the deepest ancestor of the selection that is of the specified type
  * Borrowed from Xinha (is not htmlArea) - http://xinha.gogo.co.nz/
  */
-HTMLArea.prototype._getFirstAncestor = function(sel,types) {
+HTMLArea.Editor.prototype._getFirstAncestor = function(sel,types) {
 	var prnt = this._activeElement(sel);
 	if (prnt == null) {
 		try {
-			prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
+			prnt = (Ext.isIE ? this._createRange(sel).parentElement() : this._createRange(sel).commonAncestorContainer);
 		} catch(e) {
 			return null;
 		}
@@ -1847,208 +2637,34 @@
  ***************************************************/
 
 /*
- * Intercept some commands and replace them with our own implementation
+ * Intercept some native execCommand commands
  */
-HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
-	this.focusEditor();
+HTMLArea.Editor.prototype.execCommand = function(cmdID, UI, param) {
+	this.focus();
 	switch (cmdID) {
 		default:
 			try {
-				this._doc.execCommand(cmdID, UI, param);
+				this.document.execCommand(cmdID, UI, param);
 			} catch(e) {
 				if (this.config.debug) alert(e + "\n\nby execCommand(" + cmdID + ");");
 			}
 	}
-	this.updateToolbar();
+	this.toolbar.update();
 	return false;
 };
 
-/*
-* A generic event handler for things that happen in the IFRAME's document.
-*/
-HTMLArea._editorEvent = function(ev) {
-	if(!ev) var ev = window.event;
-	var target = (ev.target) ? ev.target : ev.srcElement;
-	var owner = (target.ownerDocument) ? target.ownerDocument : target;
-	if(HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument
-		while (owner.parentElement) { owner = owner.parentElement; }
-	}
-	var editor = RTEarea[owner._editorNo]["editor"];
-	var keyEvent = ((HTMLArea.is_ie || HTMLArea.is_safari) && ev.type == "keydown") || (HTMLArea.is_gecko && ev.type == "keypress");
-	var mouseEvent = (ev.type == "mousedown" || ev.type == "mouseup");
-	editor.focusEditor();
-
-	if(keyEvent) {
-			// In Opera, inhibit key events while synchronous XMLHttpRequest is being processed
-		if (HTMLArea.is_opera && HTMLArea.pendingSynchronousXMLHttpRequest) {
-			HTMLArea._stopEvent(ev);
-			return false;
-		}
-		if (editor._hasPluginWithOnKeyPressHandler) {
-			for (var pluginId in editor.plugins) {
-				if (editor.plugins.hasOwnProperty(pluginId)) {
-					var pluginInstance = editor.plugins[pluginId].instance;
-					if (typeof(pluginInstance.onKeyPress) === "function") {
-						if (!pluginInstance.onKeyPress(ev)) {
-							HTMLArea._stopEvent(ev);
-							return false;
-						}
-					}
-				}
-			}
-		}
-		if (ev.ctrlKey && !ev.shiftKey) {
-			if (!ev.altKey) {
-					// Execute hotkey command
-				var key = String.fromCharCode((HTMLArea.is_ie || HTMLArea.is_safari || HTMLArea.is_opera) ? ev.keyCode : ev.charCode).toLowerCase();
-				if (key == " " || ev.keyCode == 32) {
-					editor.insertHTML("&nbsp;");
-					editor.updateToolbar();
-					HTMLArea._stopEvent(ev);
-					return false;
-				}
-				if (!editor.config.hotKeyList[key]) return true;
-				var cmd = editor.config.hotKeyList[key].cmd;
-				if (!cmd) return true;
-				switch (cmd) {
-					case "SelectAll":
-						cmd = editor.config.hotKeyList[key].cmd;
-						editor.execCommand(cmd, false, null);
-						HTMLArea._stopEvent(ev);
-						return false;
-						break;
-					default:
-						if (editor.config.hotKeyList[key] && editor.config.hotKeyList[key].action) {
-							if (!editor.config.hotKeyList[key].action(editor, key)) {
-								HTMLArea._stopEvent(ev);
-								return false;
-							}
-						}
-				}
-				return true;
-			}
-		} else if (ev.altKey) {
-				// check if context menu is already handling this event
-			if(editor.plugins["ContextMenu"] && editor.plugins["ContextMenu"].instance) {
-				var keys = editor.plugins["ContextMenu"].instance.keys;
-				if (keys.length > 0) {
-					var k;
-					for (var i = keys.length; --i >= 0;) {
-						k = keys[i];
-						if (k[0].toLowerCase() == key) {
-							HTMLArea._stopEvent(ev);
-							return false;
-						}
-					}
-				}
-			}
-			return true;
-		} else if (keyEvent) {
-			if (HTMLArea.is_gecko) editor._detectURL(ev);
-			switch (ev.keyCode) {
-				case 13	: // KEY enter
-					if (HTMLArea.is_gecko) {
-						if (!ev.shiftKey && !editor.config.disableEnterParagraphs) {
-							if (editor._checkInsertP()) {
-								HTMLArea._stopEvent(ev);
-							}
-						} else if (HTMLArea.is_safari) {
-							var brNode = editor._doc.createElement("br");
-							editor.insertNodeAtSelection(brNode);
-							if (!brNode.nextSibling || !HTMLArea.getInnerText(brNode.nextSibling)) {
-								var secondBrNode = editor._doc.createElement("br");
-								secondBrNode = brNode.parentNode.appendChild(secondBrNode);
-								editor.selectNode(secondBrNode, false);
-							}
-							HTMLArea._stopEvent(ev);
-						}
-							// update the toolbar state after some time
-						if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
-						editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
-						return false;
-					}
-					break;
-				case 8	: // KEY backspace
-				case 46	: // KEY delete
-					if ((HTMLArea.is_gecko && !ev.shiftKey) || HTMLArea.is_ie) {
-						if (editor._checkBackspace()) HTMLArea._stopEvent(ev);
-					}
-						// update the toolbar state after some time
-					if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
-					editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
-					break;
-				case 9: // KEY horizontal tab
-					var newkey = (ev.shiftKey ? "SHIFT-" : "") + "TAB";
-					if (editor.config.hotKeyList[newkey] && editor.config.hotKeyList[newkey].action) {
-						if (!editor.config.hotKeyList[newkey].action(editor, newkey)) {
-							HTMLArea._stopEvent(ev);
-							return false;
-						}
-					}
-					break;
-				case 37: // LEFT arrow key
-				case 38: // UP arrow key
-				case 39: // RIGHT arrow key
-				case 40: // DOWN arrow key
-					if (HTMLArea.is_ie || HTMLArea.is_safari) {
-						if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
-						editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 200);
-						return true;
-					}
-					break;
-				default:
-					break;
-			}
-			switch (ev.charCode) {
-				case 160:
-						// Handle option+SPACE for Mac users
-					if (navigator.platform.indexOf("Mac") != -1) {
-						editor.insertHTML("&nbsp;");
-						editor.updateToolbar();
-						HTMLArea._stopEvent(ev);
-						return false;
-					}
-					break;
-				default:
-					break;
-			}
-			return true;
-		}
-	} else if (mouseEvent) {
-			// mouse event
-		if (editor._timerToolbar) window.clearTimeout(editor._timerToolbar);
-		if (ev.type == "mouseup") editor.updateToolbar();
-			else editor._timerToolbar = window.setTimeout("HTMLArea.updateToolbar(\'" + editor._editorNumber + "\');", 50);
-	}
-};
-
-HTMLArea.prototype.scrollToCaret = function() {
-	if (HTMLArea.is_gecko) {
+HTMLArea.Editor.prototype.scrollToCaret = function() {
+	if (!Ext.isIE) {
 		var e = this.getParentElement(),
 			w = this._iframe.contentWindow ? this._iframe.contentWindow : window,
 			h = w.innerHeight || w.height,
-			d = this._doc,
+			d = this.document,
 			t = d.documentElement.scrollTop || d.body.scrollTop;
 		if (e.offsetTop > h+t || e.offsetTop < t) {
 			this.getParentElement().scrollIntoView();
 		}
 	}
 };
-
-/*
- * Get the html content of the current editing mode
- */
-HTMLArea.prototype.getHTML = function() {
-	return this.getPluginInstance("EditorMode").getHTML();
-};
-
-/*
- * Set the given doctype when config.fullPage is true
- */
-HTMLArea.prototype.setDoctype = function(doctype) {
-	this.doctype = doctype;
-};
-
 /***************************************************
  *  UTILITY FUNCTIONS
  ***************************************************/
@@ -2060,118 +2676,10 @@
  * Check if the client agent is supported
  */
 HTMLArea.checkSupportedBrowser = function() {
-	if(HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-		if(navigator.productSub < 20030210) return false;
-	}
-	return HTMLArea.is_gecko || HTMLArea.is_ie;
+	return Ext.isGecko || Ext.isWebKit || Ext.isOpera || Ext.isIE;
 };
 
-/*	EventCache Version 1.0
- *	Copyright 2005 Mark Wubben
- *	Adaptation by Stanislas Rolland
- *	Provides a way for automatically removing events from nodes and thus preventing memory leakage.
- *	See <http://novemberborn.net/javascript/event-cache> for more information.
- *	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
- *	Event Cache uses an anonymous function to create a hidden scope chain. This is to prevent scoping issues.
- */
-HTMLArea._eventCacheConstructor = function() {
-	var listEvents = [];
-
-	return ({
-		listEvents : listEvents,
-
-		add : function(node, sEventName, fHandler) {
-			listEvents.push(arguments);
-		},
-
-		flush : function() {
-			var item;
-			for (var i = listEvents.length; --i >= 0;) {
-				item = listEvents[i];
-				try {
-					HTMLArea._removeEvent(item[0], item[1], item[2]);
-					item[0][item[1]] = null;
-					item[0] = null;
-					item[2] = null;
-				} catch(e) { }
-			}
-			listEvents.length = 0;
-		}
-	});
-};
-
 /*
- * Register an event
- */
-HTMLArea._addEvent = function(el,evname,func,useCapture) {
-	if (typeof(useCapture) == "undefined") {
-		var useCapture = false;
-	}
-	if (HTMLArea.is_gecko) {
-		el.addEventListener(evname, func, !HTMLArea.is_opera || useCapture);
-	} else {
-		el.attachEvent("on" + evname, func);
-	}
-	HTMLArea._eventCache.add(el, evname, func);
-};
-
-/*
- * Register a list of events
- */
-HTMLArea._addEvents = function(el,evs,func,useCapture) {
-	if (typeof(useCapture) == "undefined") {
-		var useCapture = false;
-	}
-	for (var i = evs.length; --i >= 0;) {
-		HTMLArea._addEvent(el,evs[i], func, useCapture);
-	}
-};
-
-/*
- * Remove an event listener
- */
-HTMLArea._removeEvent = function(el,evname,func) {
-	if (HTMLArea.is_gecko) {
-			// Avoid Safari crash when removing events on some orphan documents
-		if (!HTMLArea.is_safari || HTMLArea.is_chrome) {
-			try {
-				el.removeEventListener(evname, func, true);
-				el.removeEventListener(evname, func, false);
-			} catch(e) { }
-		} else if (el.nodeType != 9 || el.defaultView) {
-			try {
-				el.removeEventListener(evname, func, true);
-				el.removeEventListener(evname, func, false);
-			} catch(e) { }
-		}
-	} else {
-		try {
-			el.detachEvent("on" + evname, func);
-		} catch(e) { }
-	}
-};
-
-/*
- * Remove a list of events
- */
-HTMLArea._removeEvents = function(el,evs,func) {
-	for (var i = evs.length; --i >= 0;) { HTMLArea._removeEvent(el, evs[i], func); }
-};
-
-/*
- * Stop event propagation
- */
-HTMLArea._stopEvent = function(ev) {
-	if(HTMLArea.is_gecko) {
-		ev.stopPropagation();
-		ev.preventDefault();
-	} else {
-		ev.cancelBubble = true;
-		ev.returnValue = false;
-	}
-};
-
-/*
  * Remove a class name from the class attribute of an element
  *
  * @param	object		el: the element
@@ -2193,9 +2701,9 @@
 		}
 	}
 	if (newClasses.length == 0) {
-		if (!HTMLArea.is_opera) {
+		if (!Ext.isOpera) {
 			el.removeAttribute("class");
-			if (HTMLArea.is_ie) {
+			if (Ext.isIE) {
 				el.removeAttribute("className");
 			}
 		} else {
@@ -2240,22 +2748,6 @@
 	return false;
 };
 
-/*
- * Select a value in a select element
- *
- * @param	object		select: the select object
- * @param	string		value: the value
- * @return	void
- */
-HTMLArea.selectValue = function(select, value) {
-	var options = select.getElementsByTagName("option");
-	for (var i = options.length; --i >= 0;) {
-		var option = options[i];
-		option.selected = (option.value == value);
-		select.selectedIndex = i;
-	}
-};
-
 HTMLArea.RE_blockTags = /^(body|p|h1|h2|h3|h4|h5|h6|ul|ol|pre|dl|dt|dd|div|noscript|blockquote|form|hr|table|caption|fieldset|address|td|tr|th|li|tbody|thead|tfoot|iframe)$/;
 HTMLArea.isBlockElement = function(el) { return el && el.nodeType == 1 && HTMLArea.RE_blockTags.test(el.nodeName.toLowerCase()); };
 HTMLArea.RE_closingTags = /^(p|blockquote|a|li|ol|ul|dl|dt|td|th|tr|tbody|thead|tfoot|caption|colgroup|table|div|b|bdo|big|cite|code|del|dfn|em|i|ins|kbd|label|q|samp|small|span|strike|strong|sub|sup|tt|u|var|abbr|acronym|font|center|object|embed|style|script|title|head)$/;
@@ -2295,7 +2787,7 @@
 		HTMLArea._appendToLog("The HTML document is not well-formed.");
 		if(!HTMLArea._debugMode) alert(HTMLArea.I18N.msg["HTML-document-not-well-formed"]);
 			else return HTMLArea.getHTMLWrapper(root,outputRoot,editor);
-		return editor._doc.body.innerHTML;
+		return editor.document.body.innerHTML;
 	}
 };
 
@@ -2315,19 +2807,8 @@
 		if (config.htmlRemoveTagsAndContents && config.htmlRemoveTagsAndContents.test(root_tag)) break;
 		var custom_tag = (config.customTags && config.customTags.test(root_tag));
 		if (outputRoot) outputRoot = !(config.htmlRemoveTags && config.htmlRemoveTags.test(root_tag));
-		if ((HTMLArea.is_ie || HTMLArea.is_safari) && root_tag == "head") {
-			if(outputRoot) html += "<head>";
-			var save_multiline = RegExp.multiline;
-			RegExp.multiline = true;
-			var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
-				return p1 + p2.toLowerCase();
-			});
-			RegExp.multiline = save_multiline;
-			html += txt;
-			if(outputRoot) html += "</head>";
-			break;
-		} else if (outputRoot) {
-			if (HTMLArea.is_gecko && root.hasAttribute('_moz_editor_bogus_node')) break;
+		if (outputRoot) {
+			if (Ext.isGecko && root.hasAttribute('_moz_editor_bogus_node')) break;
 			closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root) || custom_tag));
 			html = "<" + root_tag;
 			var a, name, value, attrs = root.attributes;
@@ -2336,14 +2817,14 @@
 				a = attrs.item(i);
 				name = a.nodeName.toLowerCase();
 				if ((!a.specified && name != 'value') || /_moz|contenteditable|_msh|complete/.test(name)) continue;
-				if (!HTMLArea.is_ie || name != "style") {
+				if (!Ext.isIE || name != "style") {
 						// IE5.5 reports wrong values. For this reason we extract the values directly from the root node.
 						// Using Gecko the values of href and src are converted to absolute links unless we get them using nodeValue()
 					if (typeof(root[a.nodeName]) != "undefined" && name != "href" && name != "src" && name != "style" && !/^on/.test(name)) {
 						value = root[a.nodeName];
 					} else {
 						value = a.nodeValue;
-						if (HTMLArea.is_ie && (name == "href" || name == "src") && editor.plugins.link && editor.plugins.link.instance && editor.plugins.link.instance.stripBaseURL) {
+						if (Ext.isIE && (name == "href" || name == "src") && editor.plugins.link && editor.plugins.link.instance && editor.plugins.link.instance.stripBaseURL) {
 							value = editor.plugins.link.instance.stripBaseURL(value);
 						}
 					}
@@ -2353,7 +2834,11 @@
 					// Mozilla reports some special values; we don't need them.
 				if(/(_moz|^$)/.test(value)) continue;
 					// Strip value="0" reported by IE on all li tags
-				if(HTMLArea.is_ie && root_tag == "li" && name == "value" && a.nodeValue == 0) continue;
+				if(Ext.isIE && root_tag == "li" && name == "value" && value == 0) continue;
+					// Strip id generated by ExtJS
+				if (name === 'id' && value.substr(0, 7) === 'ext-gen') {
+					continue;
+				}
 				html += " " + name + '="' + HTMLArea.htmlEncode(value) + '"';
 			}
 			if (html != "") html += closed ? " />" : ">";
@@ -2407,66 +2892,322 @@
 	pN.removeChild(el);
 	return el;
 };
-
-String.prototype.trim = function() {
-	return this.replace(/^\s+/, '').replace(/\s+$/, '');
-};
-
-// creates a rgb-style color from a number
-HTMLArea._makeColor = function(v) {
-	if (typeof(v) != "number") {
-		// already in rgb (hopefully); IE doesn't get here.
-		return v;
+/***************************************************
+ *  TIPS ON FORM FIELDS AND MENU ITEMS
+ ***************************************************/
+/*
+ * Intercept Ext.form.Field.afterRender in order to provide tips on form fields and menu items
+ * Adapted from: http://www.extjs.com/forum/showthread.php?t=36642
+ */
+HTMLArea.util.Tips = function () {
+	return {
+		tipsOnFormFields: function () {
+			if (this.helpText || this.helpTitle) {
+				if (!this.helpDisplay) {
+					this.helpDisplay = 'both';
+				}
+				var label = this.label;
+					// IE has problems with img inside label tag
+				if (label && this.helpIcon && !Ext.isIE) {
+					var helpImage = label.insertFirst({
+						tag: 'img',
+						src: _editor_skin + 'images/helpbubble.gif',
+						style: 'vertical-align: middle; padding-right: 2px;'
+					});
+					if (this.helpDisplay == 'image' || this.helpDisplay == 'both'){
+						Ext.QuickTips.register({
+							target: helpImage,
+							title: this.helpTitle,
+							text: this.helpText
+						});
+					}
+				}
+				if (this.helpDisplay == 'field' || this.helpDisplay == 'both'){
+					Ext.QuickTips.register({
+						target: this,
+						title: this.helpTitle,
+						text: this.helpText
+					});
+				}
+			}
+		},
+		tipsOnMenuItems: function () {
+			if (this.helpText || this.helpTitle) {
+				Ext.QuickTips.register({
+					target: this,
+					title: this.helpTitle,
+					text: this.helpText
+				});
+			}
+		}
 	}
-	// IE sends number; convert to rgb.
-	var r = v & 0xFF;
-	var g = (v >> 8) & 0xFF;
-	var b = (v >> 16) & 0xFF;
-	return "rgb(" + r + "," + g + "," + b + ")";
-};
-
-// returns hexadecimal color representation from a number or a rgb-style color.
-HTMLArea._colorToRgb = function(v) {
-	if (!v)
-		return '';
-
-	// returns the hex representation of one byte (2 digits)
-	function hex(d) {
-		return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
-	};
-
-	if (typeof(v) == "number") {
-		// we're talking to IE here
-		var r = v & 0xFF;
-		var g = (v >> 8) & 0xFF;
-		var b = (v >> 16) & 0xFF;
-		return "#" + hex(r) + hex(g) + hex(b);
+}();
+Ext.form.Field.prototype.afterRender = Ext.form.Field.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnFormFields);
+Ext.menu.BaseItem.prototype.afterRender = Ext.menu.BaseItem.prototype.afterRender.createInterceptor(HTMLArea.util.Tips.tipsOnMenuItems);
+/***************************************************
+ *  COLOR WIDGETS AND UTILITIES
+ ***************************************************/
+HTMLArea.util.Color = function () {
+	return {
+		/*
+		 * Returns a rgb-style color from a number
+		 */
+		colorToRgb: function(v) {
+			if (typeof(v) != 'number') {
+				return v;
+			}
+			var r = v & 0xFF;
+			var g = (v >> 8) & 0xFF;
+			var b = (v >> 16) & 0xFF;
+			return 'rgb(' + r + ',' + g + ',' + b + ')';
+		},
+		/*
+		 * Returns hexadecimal color representation from a number or a rgb-style color.
+		 */
+		colorToHex: function(v) {
+			if (!v) {
+				return '';
+			}
+			function hex(d) {
+				return (d < 16) ? ('0' + d.toString(16)) : d.toString(16);
+			};
+			if (typeof(v) == 'number') {
+				var r = v & 0xFF;
+				var g = (v >> 8) & 0xFF;
+				var b = (v >> 16) & 0xFF;
+				return '#' + hex(r) + hex(g) + hex(b);
+			}
+			if (v.substr(0, 3) === 'rgb') {
+				var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+				if (v.match(re)) {
+					var r = parseInt(RegExp.$1);
+					var g = parseInt(RegExp.$2);
+					var b = parseInt(RegExp.$3);
+					return ('#' + hex(r) + hex(g) + hex(b)).toUpperCase();
+				}
+				return null;
+			}
+			if (v.substr(0, 1) === '#') {
+				return v;
+			}
+			return null;
+		},
+		/*
+		 * Select interceptor to ensure that the color exists in the palette before trying to select
+		 */
+		checkIfColorInPalette: function (color) {
+				// Do not continue if the new color is not in the palette
+			if (this.el && !this.el.child('a.color-' + color)) {
+					// Remove any previous selection
+				this.deSelect();
+				return false;
+			}
+		}
 	}
-
-	if (v.substr(0, 3) == "rgb") {
-		// in rgb(...) form -- Mozilla
-		var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
-		if (v.match(re)) {
-			var r = parseInt(RegExp.$1);
-			var g = parseInt(RegExp.$2);
-			var b = parseInt(RegExp.$3);
-			return "#" + hex(r) + hex(g) + hex(b);
+}();
+/*
+ * Interim backward compatibility
+ */
+HTMLArea._makeColor = HTMLArea.util.Color.colorToRgb;
+HTMLArea._colorToRgb = HTMLArea.util.Color.colorToHex;
+/*
+ * Intercept Ext.ColorPalette.prototype.select
+ */
+Ext.ColorPalette.prototype.select = Ext.ColorPalette.prototype.select.createInterceptor(HTMLArea.util.Color.checkIfColorInPalette);
+/*
+ * Add deSelect method to Ext.ColorPalette
+ */
+Ext.override(Ext.ColorPalette, {
+	deSelect: function () {
+		if (this.el && this.value){
+			this.el.child('a.color-' + this.value).removeClass('x-color-palette-sel');
+			this.value = null;
 		}
-		// doesn't match RE?!  maybe uses percentages or float numbers
-		// -- FIXME: not yet implemented.
-		return null;
 	}
-
-	if (v.substr(0, 1) == "#") {
-		// already hex rgb (hopefully :D )
-		return v;
+});
+Ext.ux.menu.HTMLAreaColorMenu = Ext.extend(Ext.menu.Menu, {
+	enableScrolling: false,
+	hideOnClick: true,
+	cls: 'x-color-menu',
+	colorPaletteValue: '',
+	customColorsValue: '',
+	plain: true,
+	showSeparator: false,
+	initComponent: function () {
+		var paletteItems = [];
+		var width = 'auto';
+		if (this.colorsConfiguration) {
+			paletteItems.push({
+				xtype: 'container',
+				layout: 'anchor',
+				width: 160,
+				style: { float: 'right' },
+				items: {
+					xtype: 'colorpalette',
+					itemId: 'custom-colors',
+					cls: 'htmlarea-custom-colors',
+					colors: this.colorsConfiguration,
+					value: this.value,
+					allowReselect: true,
+					tpl: new Ext.XTemplate(
+						'<tpl for="."><a href="#" class="color-{1}" hidefocus="on"><em><span style="background:#{1}" unselectable="on">&#160;</span></em><span unselectable="on">{0}<span></a></tpl>'
+					)
+				}
+			});
+			width = 350;
+		}
+		paletteItems.push({
+			xtype: 'container',
+			layout: 'anchor',
+			items: {
+				xtype: 'colorpalette',
+				itemId: 'color-palette',
+				cls: 'color-palette',
+				colors: this.colors,
+				value: this.value,
+				allowReselect: true
+			}
+		});
+		Ext.apply(this, {
+			layout: 'menu',
+			width: width,
+			items: paletteItems
+		});
+		Ext.ux.menu.HTMLAreaColorMenu.superclass.initComponent.call(this);
+		this.standardPalette = this.find('itemId', 'color-palette')[0];
+		this.customPalette = this.find('itemId', 'custom-colors')[0];
+		if (this.standardPalette) {
+			this.standardPalette.purgeListeners();
+			this.relayEvents(this.standardPalette, ['select']);
+		}
+		if (this.customPalette) {
+			this.customPalette.purgeListeners();
+			this.relayEvents(this.customPalette, ['select']);
+		}
+		this.on('select', this.menuHide, this);
+		if (this.handler){
+			this.on('select', this.handler, this.scope || this);
+		}
+	},
+	menuHide: function() {
+		if (this.hideOnClick){
+			this.hide(true);
+		}
 	}
-
-	// if everything else fails ;)
-	return null;
-};
-
+});
+Ext.reg('htmlareacolormenu', Ext.ux.menu.HTMLAreaColorMenu);
 /*
+ * Color palette trigger field
+ * Based on http://www.extjs.com/forum/showthread.php?t=89312
+ */
+Ext.ux.form.ColorPaletteField = Ext.extend(Ext.form.TriggerField, {
+	triggerClass : 'x-form-color-trigger',
+	colors : [
+		'000000', '222222', '444444', '666666', '999999', 'BBBBBB', 'DDDDDD', 'FFFFFF',
+		'660000', '663300', '996633', '003300', '003399', '000066', '330066', '660066',
+		'990000', '993300', 'CC9900', '006600', '0033FF', '000099', '660099', '990066',
+		'CC0000', 'CC3300', 'FFCC00', '009900', '0066FF', '0000CC', '663399', 'CC0099',
+		'FF0000', 'FF3300', 'FFFF00', '00CC00', '0099FF', '0000FF', '9900CC', 'FF0099',
+		'CC3333', 'FF6600', 'FFFF33', '00FF00', '00CCFF', '3366FF', '9933FF', 'FF00FF',
+		'FF6666', 'FF6633', 'FFFF66', '66FF66', '00FFFF', '3399FF', '9966FF', 'FF66FF',
+		'FF9999', 'FF9966', 'FFFF99', '99FF99', '99FFFF', '66CCFF', '9999FF', 'FF99FF',
+		'FFCCCC', 'FFCC99', 'FFFFCC', 'CCFFCC', 'CCFFFF', '99CCFF', 'CCCCFF', 'FFCCFF'
+	],
+		// Whether or not the field background, text, or triggerbackgroud are set to the selected color
+	colorizeFieldBackgroud: true,
+	colorizeFieldText: true,
+	colorizeTrigger: false,
+	editable: true,
+	initComponent: function () {
+		Ext.ux.form.ColorPaletteField.superclass.initComponent.call(this);
+		this.addEvents(            
+			'select'
+		);
+	},
+		// private
+	validateBlur: function () {
+		return !this.menu || !this.menu.isVisible();
+	},
+	setValue: function (color) {
+		if (color) {
+			if (this.colorizeFieldBackgroud) {
+				this.el.applyStyles('background: #' + color  + ';');
+			}
+			if (this.colorizeFieldText) {
+				this.el.applyStyles('color: #' + this.rgbToHex(this.invert(this.hexToRgb(color)))  + ';');
+			}
+			if (this.colorizeTrigger) {
+				this.trigger.applyStyles('background-color: #' + color  + ';');
+			}
+		}
+		return Ext.ux.form.ColorPaletteField.superclass.setValue.call(this, color);
+	},
+		// private
+	onDestroy: function () {
+		Ext.destroy(this.menu);
+		Ext.ux.form.ColorPaletteField.superclass.onDestroy.call(this);
+	},
+		// private
+	onTriggerClick: function () {
+		if (this.disabled) {
+			return;
+		}
+		if (this.menu == null) {
+			this.menu = new Ext.ux.menu.HTMLAreaColorMenu({
+				hideOnClick: false,
+				colors: this.colors,
+				colorsConfiguration: this.colorsConfiguration,
+				value: this.getValue()
+			});
+		}
+		this.onFocus();
+		this.menu.show(this.el, "tl-bl?");
+		this.menuEvents('on');
+	},
+		//private
+	menuEvents: function (method) {
+		this.menu[method]('select', this.onSelect, this);
+		this.menu[method]('hide', this.onMenuHide, this);
+		this.menu[method]('show', this.onFocus, this);
+	},
+	onSelect: function (m, d) {
+		this.setValue(d);
+		this.fireEvent('select', this, d);
+		this.menu.hide();
+	},
+	onMenuHide: function () {
+		this.focus(false, 60);
+		this.menuEvents('un');
+	},
+	invert: function ( r, g, b ) {
+		if( r instanceof Array ) { return this.invert.call( this, r[0], r[1], r[2] ); }
+		return [255-r,255-g,255-b];
+	},
+	hexToRgb: function ( hex ) {
+		return [ this.hexToDec( hex.substr(0, 2) ), this.hexToDec( hex.substr(2, 2) ), this.hexToDec( hex.substr(4, 2) ) ];
+	},
+	hexToDec: function( hex ) {
+		var s = hex.split('');
+		return ( ( this.getHCharPos( s[0] ) * 16 ) + this.getHCharPos( s[1] ) );
+	},
+	getHCharPos: function( c ) {
+		var HCHARS = '0123456789ABCDEF';
+		return HCHARS.indexOf( c.toUpperCase() );
+	},
+	rgbToHex: function( r, g, b ) {
+		if( r instanceof Array ) { return this.rgbToHex.call( this, r[0], r[1], r[2] ); }
+		return this.decToHex( r ) + this.decToHex( g ) + this.decToHex( b );
+	},
+	decToHex: function( n ) {
+		var HCHARS = '0123456789ABCDEF';
+		n = parseInt(n, 10);
+		n = ( !isNaN( n )) ? n : 0;
+		n = (n > 255 || n < 0) ? 0 : n;
+		return HCHARS.charAt( ( n - n % 16 ) / 16 ) + HCHARS.charAt( n % 16 );
+	}
+});
+Ext.reg('colorpalettefield', Ext.ux.form.ColorPaletteField);
+/*
  * Use XML HTTPRequest to post some data back to the server and do something
  * with the response (asyncronously or syncronously); this is used by such things as the spellchecker update personal dict function
  */
@@ -2555,107 +3296,39 @@
  * TYPO3-SPECIFIC FUNCTIONS
  ***************************************************/
 /*
- * Set the size of textarea with the RTE. It's called, if we are in fullscreen-mode.
- */
-var setRTEsizeByJS = function(divId, height, width) {
-	if (HTMLArea.is_gecko) height = height - 25;
-		else height = height - 60;
-	if (height > 0) document.getElementById(divId).style.height =  height + "px";
-	if (HTMLArea.is_gecko) width = "99%";
-		else width = "97%";
-	document.getElementById(divId).style.width = width;
-};
-
-/*
  * Extending the TYPO3 Lorem Ipsum extension
  */
 var lorem_ipsum = function(element,text) {
 	if (element.tagName.toLowerCase() == "textarea" && element.id && element.id.substr(0,7) == "RTEarea") {
 		var editor = RTEarea[element.id.substr(7, element.id.length)]["editor"];
 		editor.insertHTML(text);
-		editor.updateToolbar();
+		editor.toolbar.update();
 	}
 };
-
 /*
- * Initialize the editor, configure the toolbar, setup the plugins, etc.
+ * Create the editor when HTMLArea is loaded and when Ext is ready
  */
-HTMLArea.initTimer = new Object();
-
-HTMLArea.onGenerateHandler = function(editorNumber) {
-	return (function() {
-		document.getElementById('pleasewait' + editorNumber).style.display = 'none';
-		document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
-		editorNumber = null;
-	});
-};
-
 HTMLArea.initEditor = function(editorNumber) {
-	if (document.getElementById('pleasewait' + editorNumber))	{
-	if(HTMLArea.checkSupportedBrowser()) {
-		document.getElementById('pleasewait' + editorNumber).style.display = 'block';
-		document.getElementById('editorWrap' + editorNumber).style.visibility = 'hidden';
-		if(HTMLArea.initTimer[editorNumber]) window.clearTimeout(HTMLArea.initTimer[editorNumber]);
-		if(!HTMLArea.is_loaded) {
-			HTMLArea.initTimer[editorNumber] = window.setTimeout("HTMLArea.initEditor(\'" + editorNumber + "\');", 150);
+	if (document.getElementById('pleasewait' + editorNumber)) {
+		if (HTMLArea.checkSupportedBrowser()) {
+			document.getElementById('pleasewait' + editorNumber).style.display = 'block';
+			document.getElementById('editorWrap' + editorNumber).style.visibility = 'hidden';
+			if (!HTMLArea.is_loaded) {
+				HTMLArea.initEditor.defer(150, null, [editorNumber]);
+			} else {
+					// Create an editor for the textarea
+				HTMLArea._appendToLog("[HTMLArea::initEditor]: Initializing editor with editor Id: " + editorNumber + ".");
+				var editor = new HTMLArea.Editor(Ext.apply(new HTMLArea.Config(editorNumber), RTEarea[editorNumber]));
+				editor.generate();
+				return false;
+			}
 		} else {
-			var RTE = RTEarea[editorNumber];
-			HTMLArea._appendToLog("[HTMLArea::initEditor]: Initializing editor with editor Id: " + editorNumber + ".");
-
-				// Get the configuration properties
-			var config = new HTMLArea.Config();
-			for (var property in RTE) {
-				if (RTE.hasOwnProperty(property)) {
-					config[property] = RTE[property] ? RTE[property] : false;
-				}
-			}
-				// Create an editor for the textarea
-			var editor = new HTMLArea(RTE.id, config);
-			RTE.editor = editor;
-
-				// Save the editornumber in the object
-			editor._typo3EditerNumber = editorNumber;
-			editor._editorNumber = editorNumber;
-
-				// Override these settings if they were ever modified
-			editor.config.width = "auto";
-			editor.config.height = "auto";
-			editor.config.sizeIncludesToolbar = true;
-			editor.config.fullPage = false;
-
-				// All nested tabs and inline levels in the sorting order they were applied
-			editor.nested = {};
-			editor.nested.all = RTEarea[editorNumber].tceformsNested;
-			editor.nested.sorted = HTMLArea.simplifyNested(editor.nested.all);
-
-				// Register the plugins included in the configuration
-			for (var plugin in editor.config.plugin) {
-				if (editor.config.plugin.hasOwnProperty(plugin) && editor.config.plugin[plugin]) {
-					editor.registerPlugin(plugin);
-				}
-			}
-
-			editor.onGenerate = HTMLArea.onGenerateHandler(editorNumber);
-
-			editor.generate();
-			return false;
+			document.getElementById('pleasewait' + editorNumber).style.display = 'none';
+			document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
 		}
-	} else {
-		document.getElementById('pleasewait' + editorNumber).style.display = 'none';
-		document.getElementById('editorWrap' + editorNumber).style.visibility = 'visible';
 	}
-	}
 };
 
-HTMLArea.allElementsAreDisplayed = function(elements) {
-	for (var i=0, length=elements.length; i < length; i++) {
-		if (document.getElementById(elements[i]).style.display == "none") {
-			return false;
-		}
-	}
-	return true;
-};
-
 /**
  *	Base, version 1.0.2
  *	Copyright 2006, Dean Edwards
@@ -2754,7 +3427,7 @@
 	// single instance
 	var object = constructor ? klass : _prototype;
 	// class initialisation
-	if (object.init instanceof Function) object.init();
+	//if (object.init instanceof Function) object.init();
 	return object;
 };
 
@@ -2781,7 +3454,7 @@
 	 */
 	constructor : function(editor, pluginName) {
 		this.editor = editor;
-		this.editorNumber = editor._editorNumber;
+		this.editorNumber = editor.editorId;
 		this.editorConfiguration = editor.config;
 		this.name = pluginName;
 		try {
@@ -2854,7 +3527,7 @@
 	 * @return	object		the plugin object or null
 	 */
 	getPluginInstance : function(pluginName) {
-		return this.editor.getPluginInstance(pluginName);
+		return this.editor.getPlugin(pluginName);
 	},
 
 	/**
@@ -2863,7 +3536,7 @@
 	 * @return	string		editor mode
 	 */
 	getEditorMode : function() {
-		return this.getPluginInstance("EditorMode").getEditorMode();
+		return this.editor.getMode();
 	},
 
 	/**
@@ -2874,52 +3547,70 @@
 	 * @return	boolean		true if the button is enabled in the toolbar configuration
 	 */
 	isButtonInToolbar : function(buttonId) {
-		var toolbar = this.editorConfiguration.toolbar;
-		var n = toolbar.length;
-		for ( var i = 0; i < n; ++i ) {
-			var buttonInToolbar = new RegExp( "^(" + toolbar[i].join("|") + ")$", "i");
-			if (buttonInToolbar.test(buttonId)) {
-				return true;
-			}
-		}
-		return false;
+		var index = -1;
+		Ext.each(this.editorConfiguration.toolbar, function (row) {
+			Ext.each(row, function (group) {
+				index = group.indexOf(buttonId);
+				return index === -1;
+			});
+			return index === -1;
+		});
+		return index !== -1;
 	},
 
 	/**
-	 * Registors a button for inclusion in the toolbar
+	 * Returns the button object from the toolbar
 	 *
+	 * @param	string		buttonId: identification of the button
+	 *
+	 * @return	object		the toolbar button object
+	 */
+	getButton: function(buttonId) {
+		return this.editor.toolbar.getButton(buttonId);
+	},
+
+	/**
+	 * Arrays of ExtJS config properties that may be used on a button or dropdown in Page TSConfig
+	 */
+	ExtJSProperties: {
+		htmlareabutton: [],
+		htmlareacombo: ['width', 'listWidth', 'maxHeight' ]
+	},
+
+	/**
+	 * Registers a button for inclusion in the toolbar
+	 *
 	 * @param	object		buttonConfiguration: the configuration object of the button:
 	 *					id		: unique id for the button
 	 *					tooltip		: tooltip for the button
 	 *					textMode	: enable in text mode
 	 *					action		: name of the function invoked when the button is pressed
 	 *					context		: will be disabled if not inside one of listed elements
-	 *					hide		: hide in menu and show only in context menu?
-	 *					selection	: will be disabled if there is no selection?
+	 *					hide		: hide in menu and show only in context menu (deprecated, use hidden)
+	 *					hidden		: synonym of hide
+	 *					selection	: will be disabled if there is no selection
 	 *					hotkey		: hotkey character
 	 *					dialog		: if true, the button opens a dialogue
 	 *					dimensions	: the opening dimensions object of the dialogue window
 	 *
 	 * @return	boolean		true if the button was successfully registered
 	 */
-	registerButton : function (buttonConfiguration) {
+	registerButton: function (buttonConfiguration) {
 		if (this.isButtonInToolbar(buttonConfiguration.id)) {
-			if ((typeof(buttonConfiguration.action) === "string") && (typeof(this[buttonConfiguration.action]) === "function")) {
-				var hotKeyAction = buttonConfiguration.action;
-				var actionFunctionReference = this.makeFunctionReference(buttonConfiguration.action);
-				buttonConfiguration.action = actionFunctionReference;
-				if (!buttonConfiguration.textMode) {
-					buttonConfiguration.textMode = false;
-				}
+			if (Ext.isString(buttonConfiguration.action) && Ext.isFunction(this[buttonConfiguration.action])) {
+				buttonConfiguration.plugins = this;
 				if (buttonConfiguration.dialog) {
 					if (!buttonConfiguration.dimensions) {
 						buttonConfiguration.dimensions = { width: 250, height: 250};
 					}
 					buttonConfiguration.dimensions.top = buttonConfiguration.dimensions.top ?  buttonConfiguration.dimensions.top : this.editorConfiguration.dialogueWindows.defaultPositionFromTop;
 					buttonConfiguration.dimensions.left = buttonConfiguration.dimensions.left ?  buttonConfiguration.dimensions.left : this.editorConfiguration.dialogueWindows.defaultPositionFromLeft;
-				} else {
-					buttonConfiguration.dialog = false;
 				}
+				buttonConfiguration.hidden = buttonConfiguration.hide;
+					// Copy ExtJS properties for the button
+				if (this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]]) {
+					buttonConfiguration = Ext.copyTo(buttonConfiguration, this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]], this.ExtJSProperties['htmlareabutton']);
+				}
 				if (this.editorConfiguration.registerButton(buttonConfiguration)) {
 					var hotKey = buttonConfiguration.hotKey ? buttonConfiguration.hotKey :
 						((this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]] && this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]].hotKey) ? this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonConfiguration.id]].hotKey : null);
@@ -2932,8 +3623,7 @@
 					if (hotKey || hotKey == "0") {
 						var hotKeyConfiguration = {
 							id	: hotKey,
-							cmd	: buttonConfiguration.id,
-							action	: hotKeyAction
+							cmd	: buttonConfiguration.id
 						};
 						return this.registerHotKey(hotKeyConfiguration);
 					}
@@ -2945,44 +3635,52 @@
 		}
 		return false;
 	},
-
 	/**
-	 * Registors a drop-down list for inclusion in the toolbar
+	 * Registers a drop-down list for inclusion in the toolbar
 	 *
 	 * @param	object		dropDownConfiguration: the configuration object of the drop-down:
 	 *					id		: unique id for the drop-down
 	 *					tooltip		: tooltip for the drop-down
+	 *					action		: name of function to invoke when an option is selected
 	 *					textMode	: enable in text mode
-	 *					action		: name of the function invoked when a new option is selected
-	 *					refresh		: name of the function invoked in order to refresh the drop-down when the toolbar is updated
-	 *					context		: will be disabled if not inside one of listed elements
 	 *
 	 * @return	boolean		true if the drop-down list was successfully registered
 	 */
-	registerDropDown : function (dropDownConfiguration) {
+	registerDropDown: function (dropDownConfiguration) {
 		if (this.isButtonInToolbar(dropDownConfiguration.id)) {
-			if (typeof((dropDownConfiguration.action) === "string") && (typeof(this[dropDownConfiguration.action]) === "function")) {
-				var actionFunctionReference = this.makeFunctionReference(dropDownConfiguration.action);
-				dropDownConfiguration.action = actionFunctionReference;
-				if (!dropDownConfiguration.textMode) {
-					dropDownConfiguration.textMode = false;
+			if (Ext.isString(dropDownConfiguration.action) && Ext.isFunction(this[dropDownConfiguration.action])) {
+				dropDownConfiguration.plugins = this;
+				dropDownConfiguration.hidden = dropDownConfiguration.hide;
+				dropDownConfiguration.xtype = 'htmlareacombo';
+				if (this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[dropDownConfiguration.id]]) {
+					dropDownConfiguration = Ext.copyTo(dropDownConfiguration, this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[dropDownConfiguration.id]], this.ExtJSProperties['htmlareacombo']);
 				}
-				if (typeof(dropDownConfiguration.refresh) === "string") {
-					if (typeof(this[dropDownConfiguration.refresh]) === "function") {
-						var refreshFunctionReference = this.makeFunctionReference(dropDownConfiguration.refresh);
-						dropDownConfiguration.refresh = refreshFunctionReference;
-					} else {
-						this.appendToLog("registerDropDown", "Function " + dropDownConfiguration.refresh + " was not defined when registering drop-down " + dropDownConfiguration.id);
-						return false;
-					}
-				}
-				return this.editorConfiguration.registerDropdown(dropDownConfiguration);
+				return this.editorConfiguration.registerButton(dropDownConfiguration);
 			} else {
-				this.appendToLog("registerDropDown", "Function " + dropDownConfiguration.action + " was not defined when registering drop-down " + dropDownConfiguration.id);
+				this.appendToLog('registerDropDown', 'Function ' + dropDownConfiguration.action + ' was not defined when registering drop-down ' + dropDownConfiguration.id);
 			}
 		}
 		return false;
 	},
+	/**
+	 * Registers a text element for inclusion in the toolbar
+	 *
+	 * @param	object		textConfiguration: the configuration object of the text element:
+	 *					id		: unique id for the text item
+	 *					text		: the text litteral
+	 *					tooltip		: tooltip for the text item
+	 *					cls		: a css class to be assigned to the text element
+	 *
+	 * @return	boolean		true if the drop-down list was successfully registered
+	 */
+	registerText: function (textConfiguration) {
+		if (this.isButtonInToolbar(textConfiguration.id)) {
+			textConfiguration.plugins = this;
+			textConfiguration.xtype = 'htmlareatoolbartext';
+			return this.editorConfiguration.registerButton(textConfiguration);
+		}
+		return false;
+	},
 
 	/**
 	 * Returns the drop-down configuration
@@ -2992,7 +3690,7 @@
 	 * @return	object		the drop-down configuration object
 	 */
 	getDropDownConfiguration : function(dropDownId) {
-		return this.editorConfiguration.customSelects[dropDownId];
+		return this.editorConfiguration.buttonsConfig[dropDownId];
 	},
 
 	/**
@@ -3000,19 +3698,13 @@
 	 *
 	 * @param	object		hotKeyConfiguration: the configuration object of the hotkey:
 	 *					id		: the key
-	 *					action		: name of the function invoked when a hotkey is pressed
+	 *					cmd		: name of the button corresponding to the hot key
+	 *					element		: value of the record to be selected in the dropDown item
 	 *
 	 * @return	boolean		true if the hotkey was successfully registered
 	 */
 	registerHotKey : function (hotKeyConfiguration) {
-		if (typeof((hotKeyConfiguration.action) === "string") && (typeof(this[hotKeyConfiguration.action]) === "function")) {
-			var actionFunctionReference = this.makeFunctionReference(hotKeyConfiguration.action);
-			hotKeyConfiguration.action = actionFunctionReference;
-			return this.editorConfiguration.registerHotKey(hotKeyConfiguration);
-		} else {
-			this.appendToLog("registerHotKey", "Function " + hotKeyConfiguration.action + " was not defined when registering hotkey " + hotKeyConfiguration.id);
-			return false;
-		}
+		return this.editorConfiguration.registerHotKey(hotKeyConfiguration);
 	},
 
 	/**
@@ -3041,24 +3733,33 @@
 	 *
 	 * @return	object		the hotkey configuration object
 	 */
-	getHotKeyConfiguration : function(key) {
-		if (typeof(this.editorConfiguration.hotKeyList[key]) !== "undefined") {
+	getHotKeyConfiguration: function(key) {
+		if (Ext.isDefined(this.editorConfiguration.hotKeyList[key])) {
 			return this.editorConfiguration.hotKeyList[key];
 		} else {
 			return null;
 		}
 	},
-
 	/**
+	 * Initializes the plugin
+	 * Is invoked when the toolbar component is created (subclass of Ext.ux.HTMLAreaButton or Ext.ux.form.HTMLAreaCombo)
+	 *
+	 * @param	object		button: the component
+	 *
+	 * @return	void
+	 */
+	init: Ext.emptyFn,
+	/**
 	 * The toolbar refresh handler of the plugin
 	 * This function may be defined by the plugin subclass.
 	 * If defined, the function will be invoked whenever the toolbar state is refreshed.
 	 *
 	 * @return	boolean
 	 */
-	onUpdateToolbar : null,
-
+	onUpdateToolbar: Ext.emptyFn,
 	/**
+	 * Deprecated as of TYPO3 4.4
+	 * Register the key handler to the editor keyMap in onGenerate function
 	 * The keyPress event handler
 	 * This function may be defined by the plugin subclass.
 	 * If defined, the function is invoked whenever a key is pressed.
@@ -3067,20 +3768,8 @@
 	 *
 	 * @return	boolean
 	 */
-	onKeyPress : null,
-
+	onKeyPress: null,
 	/**
-	 * The hotKey event handler
-	 * This function may be defined by the plugin subclass.
-	 * If defined, the function is invoked whenever a hot key is pressed.
-	 *
-	 * @param	event		key: the hot key that was pressed
-	 *
-	 * @return	boolean
-	 */
-	onHotKey : null,
-
-	/**
 	 * The onMode event handler
 	 * This function may be redefined by the plugin subclass.
 	 * The function is invoked whenever the editor changes mode.
@@ -3089,21 +3778,19 @@
 	 *
 	 * @return	boolean
 	 */
-	onMode : function(mode) {
-		if (mode === "textmode" && this.dialog && HTMLArea.Dialog[this.name] == this.dialog && !(this.dialog.buttonId && this.editorConfiguration.btnList[this.dialog.buttonId] && this.editorConfiguration.btnList[this.dialog.buttonId].textMode)) {
+	onMode: function(mode) {
+		if (mode === "textmode" && this.dialog && HTMLArea.Dialog[this.name] == this.dialog && !(this.dialog.buttonId && this.editorConfiguration.buttons[this.dialog.buttonId] && this.editorConfiguration.buttons[this.dialog.buttonId].textMode)) {
 			this.dialog.close();
 		}
 	},
-
 	/**
 	 * The onGenerate event handler
 	 * This function may be defined by the plugin subclass.
-	 * If defined, the function is invoked when the editor is initialized
+	 * The function is invoked when the editor is initialized
 	 *
 	 * @return	boolean
 	 */
-	onGenerate : null,
-
+	onGenerate: Ext.emptyFn,
 	/**
 	 * Make function reference in order to avoid memory leakage in IE
 	 *
@@ -3113,8 +3800,8 @@
 	 */
 	makeFunctionReference : function (functionName) {
 		var self = this;
-		return (function(arg1, arg2) {
-			return (self[functionName](arg1, arg2));});
+		return (function(arg1, arg2, arg3) {
+			return (self[functionName](arg1, arg2, arg3));});
 	},
 
 	/**
@@ -3197,45 +3884,45 @@
 					this.appendToLog("openDialog", "Function " + action + " was not defined when opening dialog for " + buttonId);
 				}
 			}
-				// Window dimensions as per call or button registration
-			var dialogueWindowDimensions = {
-				width:	((dimensions && dimensions.width) ? dimensions.width :
-						(this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].width : 250)),
-				height:	((dimensions && dimensions.height) ? dimensions.height :
-						(this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].height : 250)),
-				top:	((dimensions && dimensions.top) ? dimensions.top :
-						(this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].top : this.editorConfiguration.dialogueWindows.defaultPositionFromTop)),
-				left:	((dimensions && dimensions.left) ? dimensions.left :
-						(this.editorConfiguration.btnList[buttonId] ? this.editorConfiguration.btnList[buttonId][8].left : this.editorConfiguration.dialogueWindows.defaultPositionFromLeft))
-			};
-				// Overrride window dimensions as per PageTSConfig
-			var buttonConfiguration = this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonId]];
-			if (buttonConfiguration && buttonConfiguration.dialogueWindow) {
-				if (buttonConfiguration.dialogueWindow.width) {
-					dialogueWindowDimensions.width = buttonConfiguration.dialogueWindow.width;
-				}
-				if (buttonConfiguration.dialogueWindow.height) {
-					dialogueWindowDimensions.height = buttonConfiguration.dialogueWindow.height;
-				}
-				if (buttonConfiguration.dialogueWindow.top) {
-					dialogueWindowDimensions.top = buttonConfiguration.dialogueWindow.positionFromTop;
-				}
-				if (buttonConfiguration.dialogueWindow.left) {
-					dialogueWindowDimensions.left = buttonConfiguration.dialogueWindow.positionFromLeft;
-				}
-			}
 			return new HTMLArea.Dialog(
 					this,
 					buttonId,
 					url,
 					actionFunctionReference,
 					arguments,
-					dialogueWindowDimensions,
+					this.getWindowDimensions(dimensions, buttonId),
 					(showScrollbars?showScrollbars:"no"),
 					dialogOpener
 				);
 		}
 	},
+	getWindowDimensions: function (dimensions, buttonId) {
+			// Apply default dimensions
+		var dialogueWindowDimensions = {
+			width: 250,
+			height: 250,
+			top: this.editorConfiguration.dialogueWindows.defaultPositionFromTop,
+			left: this.editorConfiguration.dialogueWindows.defaultPositionFromLeft
+		};
+			// Apply dimensions as per button registration
+		if (this.editorConfiguration.buttonsConfig[buttonId]) {
+			Ext.apply(dialogueWindowDimensions, this.editorConfiguration.buttonsConfig[buttonId].dimensions);
+		}
+			// Apply dimensions as per call
+		Ext.apply(dialogueWindowDimensions, dimensions);
+			// Overrride dimensions as per PageTSConfig
+		var buttonConfiguration = this.editorConfiguration.buttons[this.editorConfiguration.convertButtonId[buttonId]];
+		if (buttonConfiguration && buttonConfiguration.dialogueWindow) {
+			Ext.apply(dialogueWindowDimensions, buttonConfiguration.dialogueWindow);
+			if (buttonConfiguration.dialogueWindow.top) {
+				dialogueWindowDimensions.top = buttonConfiguration.dialogueWindow.positionFromTop;
+			}
+			if (buttonConfiguration.dialogueWindow.left) {
+				dialogueWindowDimensions.left = buttonConfiguration.dialogueWindow.positionFromLeft;
+			}
+		}
+		return dialogueWindowDimensions;
+	},
 
 	/**
 	 * Make url from the name of a popup of the plugin
@@ -3270,6 +3957,100 @@
 	 */
 	appendToLog : function (functionName, text) {
 		HTMLArea._appendToLog("[" + this.name + "::" + functionName + "]: " + text);
+	},
+	/*
+	 * Add a config element to config array if not empty
+	 *
+	 * @param	object		configElement: the config element
+	 * @param	array		configArray: the config array
+	 *
+	 * @return	void
+	 */
+	addConfigElement: function (configElement, configArray) {
+		if (!Ext.isEmpty(configElement)) {
+			configArray.push(configElement);
+		}
+	},
+	/*
+	 * Handler for Ext.TabPanel tabchange event
+	 * Force window ghost height synchronization
+	 * Working around ExtJS 3.1 bug
+	 */
+	syncHeight: function (tabPanel, tab) {
+		var position = this.dialog.getPosition();
+		if (position[0] > 0) {
+			this.dialog.setPosition(position);
+		}
+	},
+	/*
+	 * Show the dialogue window
+	 */
+	show: function () {
+			// Close the window if the editor changes mode
+		this.dialog.mon(this.editor, 'modeChange', this.close, this, {single: true });
+		this.saveSelection();
+		this.dialog.show();
+		this.restoreSelection();
+	},
+	/*
+	 * Close the dialogue window (after saving the selection, if IE)
+	 */
+	close: function () {
+		this.saveSelection();
+		this.dialog.close();
+	},
+	/*
+	 * Dialogue window onClose handler
+	 */
+	onClose: function () {
+		this.restoreSelection();
+	 	this.editor.updateToolbar();
+	},
+	/*
+	 * Handler for window cancel
+	 */
+	onCancel: function () {
+		this.dialog.close();
+	},
+	/*
+	 * Save selection
+	 * Should be called after processing button other than Cancel
+	 */
+	saveSelection: function () {
+			// If IE, save the current selection
+		if (Ext.isIE) {
+			this.bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
+		}
+	},
+	/*
+	 * Restore selection
+	 * Should be called before processing dialogue button or result
+	 */
+	restoreSelection: function () {
+			// If IE, restore the selection saved when the window was shown
+		if (Ext.isIE) {
+			this.editor.selectRange(this.editor.moveToBookmark(this.bookmark));
+		}
+	},
+	/*
+	 * Build the configuration object of a button
+	 *
+	 * @param	string		button: the text of the button
+	 * @param	function	handler: button handler
+	 * 
+	 * @return	object		the button configuration object
+	 */
+	buildButtonConfig: function (button, handler) {
+		return {
+			xtype: 'button',
+			text: this.localize(button),
+			listeners: {
+				click: {
+					fn: handler,
+					scope: this
+				}
+			}
+		};
 	}
 });
 
@@ -3310,7 +4091,6 @@
 		}
 		HTMLArea.Dialog[this.plugin.name] = this;
 		this.dialogWindow = window.open(url, this.plugin.name + "Dialog", "toolbar=no,location=no,directories=no,menubar=no,resizable=yes,top=" + dimensions.top + ",left=" + dimensions.left + ",dependent=yes,dialog=yes,chrome=no,width=" + dimensions.width + ",height=" + dimensions.height + ",scrollbars=" + showScrollbars);
-
 		if (!this.dialogWindow) {
 			this.plugin.appendToLog("openDialog", "Dialog window could not be opened with url " + url);
 			return false;
@@ -3323,67 +4103,9 @@
 		if (!this.dialogWindow.opener) {
 			this.dialogWindow.opener = this.window;
 		}
-
-		if (!url) this.createForm();
 		return true;
 	},
-
 	/**
-	 * Creates the document and the dialogue form of the dialogue window
-	 *
-	 * @return	void
-	 */
-	createForm : function () {
-
-		this.document = this.dialogWindow.document;
-		this.editor = this.plugin.editor;
-
-		this.document.open();
-		var html = this.plugin.editorConfiguration.getDocumentType()
-			+ '<html><head></head><body></body></html>\n';
-		this.document.write(html);
-		this.document.close();
-			// IE needs the stylesheets to be loaded before we create the form
-		if (HTMLArea.is_ie) {
-			this.loadStyle();
-		}
-		var head = this.document.getElementsByTagName("head")[0];
-		var title = this.document.getElementsByTagName("title")[0];
-		if (!title) {
-			var title = this.document.createElement("title");
-			head.appendChild(title);
-		}
-		this.document.title = this.arguments.title;
-		var body = this.document.body;
-		body.className = "popupwin dialog";
-		body.id = "--HA-body";
-		var content = this.document.createElement("div");
-		content.className = "content";
-		content.id = "content";
-		this.content = content;
-		body.appendChild(content);
-			// Create the form
-			// Localize, resize and initiate capture of events
-		if (HTMLArea.is_ie) {
-				// Catch errors for IE loosing control in case the window is closed while being initialized
-			try {
-				this.arguments.initialize(this);
-				this.initialize(false, false, "noStyle");
-				this.focus();
-			} catch(e) { }
-		} else {
-			this.arguments.initialize(this);
-				// Firefox needs a delay defore we resize
-			this.initialize(false, (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera));
-			this.focus();
-			if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-				var self = this;
-				setTimeout( function() { self.resize(); }, 100);
-			}
-		}
-	},
-
-	/**
 	 * Adds OK and Cancel buttons to the dialogue window
 	 *
 	 * @return	void
@@ -3473,7 +4195,6 @@
 			// Resize the dialog window to its contents
 		if (!noResize) this.resize(noResize);
 	},
-
 	/**
 	 * Load the stylesheets in the dialog window
 	 *
@@ -3485,7 +4206,7 @@
 		link.rel = "stylesheet";
 		link.type = "text/css";
 		link.href = HTMLArea.editorCSS;
-		if (link.href.indexOf("http") == -1 && HTMLArea.is_gecko) link.href = _typo3_host_url + link.href;
+		if (link.href.indexOf("http") == -1 && !Ext.isIE) link.href = _typo3_host_url + link.href;
 		head.appendChild(link);
 	},
 
@@ -3536,8 +4257,7 @@
 			var doc = dialogWindow.document;
 			var content = doc.getElementById("content");
 				// As of Google Chrome build 1798, window resizeTo and resizeBy are completely erratic: do nothing
-			if ((HTMLArea.is_gecko && !HTMLArea.is_opera && !HTMLArea.is_safari)
-					|| ((HTMLArea.is_ie || HTMLArea.is_opera || (HTMLArea.is_safari && !HTMLArea.is_chrome)) && content)) {
+			if (Ext.isGecko || ((Ext.isIE || Ext.isOpera || (Ext.isWebKit && !Ext.isChrome)) && content)) {
 				var self = this;
 				setTimeout( function() {
 					if (!noResize) {
@@ -3551,7 +4271,7 @@
 				}, 75);
 			} else if (!noResize) {
 				var body = doc.body;
-				if (HTMLArea.is_ie) {
+				if (Ext.isIE) {
 					var innerX = (doc.documentElement && doc.documentElement.clientWidth) ? doc.documentElement.clientWidth : body.clientWidth;
 					var innerY = (doc.documentElement && doc.documentElement.clientHeight) ? doc.documentElement.clientHeight : body.clientHeight;
 					var pageY = Math.max(body.scrollHeight, body.offsetHeight);
@@ -3561,7 +4281,7 @@
 						dialogWindow.resizeBy((innerX < body.scrollWidth) ? (Math.max(body.scrollWidth, body.offsetWidth) - innerX) : 0, (body.scrollHeight - body.offsetHeight));
 					}
 					// As of Google Chrome build 1798, window resizeTo and resizeBy are completely erratic: do nothing
-				} else if ((HTMLArea.is_safari && !HTMLArea.is_chrome) || HTMLArea.is_opera) {
+				} else if (Ext.isSafari || Ext.isOpera) {
 					dialogWindow.resizeTo(dialogWindow.innerWidth, body.offsetHeight + 10);
 					if (dialogWindow.innerHeight < body.scrollHeight) {
 						dialogWindow.resizeBy(0, (body.scrollHeight - dialogWindow.innerHeight) + 10);
@@ -3592,8 +4312,8 @@
 
 		var contentWidth = content.offsetWidth;
 		var contentHeight = content.offsetHeight;
-		if (HTMLArea.is_gecko && !HTMLArea.is_opera) {
-			dialogWindow.resizeTo(contentWidth, contentHeight + (HTMLArea.is_safari ? 40 : (HTMLArea.is_ff2 ? 75 : 95)));
+		if (Ext.isGecko || Ext.isWebKit) {
+			dialogWindow.resizeTo(contentWidth, contentHeight + (Ext.isWebKit ? 40 : (Ext.isGecko2 ? 75 : 95)));
 		} else {
 			dialogWindow.resizeTo(contentWidth + 200, contentHeight + 200);
 			if (dialogWindow.innerWidth) {
@@ -3622,7 +4342,7 @@
 			var doc = dialogWindow.document;
 			var body = doc.body;
 				// Center on parent if allowed
-			if (HTMLArea.is_gecko) {
+			if (!Ext.isIE) {
 				var x = dialogWindow.opener.screenX + (dialogWindow.opener.outerWidth - dialogWindow.outerWidth) / 2;
 				var y = dialogWindow.opener.screenY + (dialogWindow.opener.outerHeight - dialogWindow.outerHeight) / 2;
 			} else {
@@ -3632,7 +4352,7 @@
 				var y = (screen.availHeight - H) / 2;
 			}
 				// As of build 1798, Google Chrome moveTo breaks the window dimensions: do nothing
-			if (!HTMLArea.is_chrome) {
+			if (!Ext.isChrome) {
 				try {
 					dialogWindow.moveTo(x, y);
 				} catch(e) { }
@@ -3661,22 +4381,7 @@
 			this.dialogWindow.focus();
 		}
 	},
-
 	/**
-	 * Recover focus from the parent window
-	 *
-	 * @return	void
-	 */
-	recoverFocus : function(ev) {
-		if (this.dialogWindow && !this.dialogWindow.closed) {
-			if (!ev) var ev = window.event;
-			HTMLArea._stopEvent(ev);
-			this.focus();
-		}
-		return false;
-	},
-
-	/**
 	 * Close the dialog window
 	 *
 	 * @return	void
@@ -3688,11 +4393,10 @@
 					this.dialogWindow.openedDialog.close();
 				}
 			} catch(e) { }
-			this.releaseEvents();
 			HTMLArea.Dialog[this.plugin.name] = null;
 			if (!this.dialogWindow.closed) {
 				this.dialogWindow.dialog = null;
-				if (HTMLArea.is_safari || HTMLArea.is_ie) {
+				if (Ext.isWebKit || Ext.isIE) {
 					this.dialogWindow.blur();
 				}
 				this.dialogWindow.close();
@@ -3703,7 +4407,7 @@
 			}
 				// Opera unload event may be triggered after the editor iframe is gone
 			if (this.plugin.editor._iframe) {
-				this.plugin.editor.updateToolbar();
+				this.plugin.editor.toolbar.update();
 			}
 		}
 		return false;
@@ -3729,10 +4433,10 @@
 	 *
 	 * @return	boolean		false if the event was handled
 	 */
-	closeOnEscape : function(ev) {
-		if (!ev) var ev = window.event;
+	closeOnEscape : function(event) {
+		var ev = event.browserEvent;
 		if (ev.keyCode == 27) {
-			if (HTMLArea.is_gecko) {
+			if (!Ext.isIE) {
 				var parentWindow = ev.currentTarget.defaultView;
 			} else {
 				var parentWindow = ev.srcElement.parentNode.parentNode.parentWindow;
@@ -3750,81 +4454,21 @@
 		}
 		return true;
 	},
-
 	/**
-	 * Capture unload, escape and focus events
+	 * Capture unload and escape events
 	 *
 	 * @return	void
 	 */
 	captureEvents : function (skipUnload) {
-			// Capture unload events on the dialogue window, the opener window and the editor frame
-		this.unloadFunctionReference = this.makeFunctionReference("close");
-		HTMLArea._addEvent(this.dialogWindow.opener, "unload", this.unloadFunctionReference);
-		if (HTMLArea.is_gecko && this.plugin.editor._iframe.contentWindow) {
-			HTMLArea._addEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
+			// Capture unload events on the dialogue window and the editor frame
+		if (!Ext.isIE && this.plugin.editor._iframe.contentWindow) {
+			Ext.EventManager.on(this.plugin.editor._iframe.contentWindow, 'unload', this.close, this, {single: true});
 		}
-		if (!skipUnload) HTMLArea._addEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
+		if (!skipUnload) {
+			Ext.EventManager.on(this.dialogWindow, 'unload', this.close, this, {single: true});
+		}
 			// Capture escape key on the dialogue window
-		this.escapeFunctionReference = this.makeFunctionReference("closeOnEscape");
-		HTMLArea._addEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
-			// Capture focus events on the opener window and its frames
-		this.recoverFocusFunctionReference = this.makeFunctionReference("recoverFocus");
-		this.captureFocus(this.dialogWindow.opener);
-	 },
-
-	/**
-	 * Capture focus events
-	 *
-	 * @return	void
-	 */
-	captureFocus : function (w) {
-		if (HTMLArea.is_gecko) {
-			w.addEventListener("focus", this.recoverFocusFunctionReference, true);
-		} else {
-			HTMLArea._addEvent(w, "focus", this.recoverFocusFunctionReference);
-		}
-		for (var i = w.frames.length; --i >= 0;) {
-			this.captureFocus(w.frames[i]);
-		}
-	},
-
-	/**
-	 * Release all event handlers that were set when the dialogue window was opened
-	 *
-	 * @return	void
-	 */
-	releaseEvents : function() {
-		if (this.dialogWindow) {
-			HTMLArea._removeEvent(this.dialogWindow, "unload", this.unloadFunctionReference);
-			try {
-				if (this.dialogWindow.document) {
-					HTMLArea._removeEvent(this.dialogWindow.document, "keypress", this.escapeFunctionReference);
-				}
-			} catch(e) { }
-			try {
-				if (this.dialogWindow.opener && !this.dialogWindow.opener.closed) {
-					HTMLArea._removeEvent(this.dialogWindow.opener, "unload", this.unloadFunctionReference);
-					if (HTMLArea.is_gecko) {
-						this.releaseFocus(this.dialogWindow.opener);
-					}
-				}
-			} catch(e) { }
-		}
-		if ((HTMLArea.is_gecko && !HTMLArea.is_opera) && this.plugin.editor._iframe.contentWindow) {
-			HTMLArea._removeEvent(this.plugin.editor._iframe.contentWindow, "unload", this.unloadFunctionReference);
-		}
-	},
-
-	/**
-	 * Release focus capturing events that were set when the dialogue window was opened
-	 *
-	 * @return	void
-	 */
-	releaseFocus : function(w) {
-		HTMLArea._removeEvent(w, "focus", this.recoverFocusFunctionReference);
-		for (var i = w.frames.length; --i >= 0;) {
-			this.releaseFocus(w.frames[i]);
-		}
-	}
+		Ext.EventManager.on(this.dialogWindow.document, 'keypress', this.closeOnEscape, this, {single: true});
+	 }
 });
 };
Index: typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/locallang_dialogs.xml	(copie de travail)
@@ -10,6 +10,7 @@
 			<label index="Cancel">Cancel</label>
 			<label index="Close">Close</label>
 			<label index="Not set">Not set</label>
+			<label index="General">General</label>
 			<label index="Alignment:">Text alignment:</label>
 			<label index="Alignment not set">Not set</label>
 			<label index="Left">Left</label>
@@ -86,7 +87,7 @@
 			<label index="About HTMLArea">About htmlArea RTE</label>
 			<label index="About">About</label>
 			<label index="free_editor">A free and open-source editor for &lt;textarea&gt; fields, featuring integration with TYPO3.</label>
-			<label index="Mozilla_or_IE">For Firefox 0.8+, Mozilla 1.3.1+, Netscape 7.1+, SeaMonkey 1.0+, Safari 3.0.4+, Google Chrome 1.0+ and Opera 9.62+ on any platform, and for Internet Explorer 5.5+ on Windows.</label>
+			<label index="Mozilla_or_IE">For Firefox 1.5+, SeaMonkey 1.0+, Safari 3.0.4+, Google Chrome 1.0+ and Opera 9.62+ on any platform, and for Internet Explorer 6.0+ on Windows.</label>
 			<label index="product_documentation">For more information, please visit:</label>
 			<label index="All rights reserved.">All Rights Reserved.</label>
 			<label index="License">License</label>
@@ -101,14 +102,15 @@
 			<label index="style">Paragraph:</label>
 			<label index="Block style label">Block style:</label>
 			<label index="text_style">Text style:</label>
-			<label index="LeftToRight">Left to right1</label>
-			<label index="RightToLeft">Right to left1</label>
+			<label index="LeftToRight">Left to right</label>
+			<label index="RightToLeft">Right to left</label>
 			<label index="Language">Language</label>
 			<label index="Text direction">Text direction</label>
 			<label index="Language:">Language:</label>
 			<label index="Text direction:">Text direction:</label>
 			<label index="No language mark">No language</label>
 			<label index="Remove language mark">Remove language</label>
+			<label index="statusBarStyle">Style</label>
 		</languageKey>
 	</data>
 	<orig_hash type="array">
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/acronym.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -30,25 +30,28 @@
  * TYPO3 SVN ID: $Id$
  */
 Acronym = HTMLArea.Plugin.extend({
-	
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-	
 	/*
 	 * This function gets called by the class constructor
 	 */
 	configurePlugin : function(editor) {
-		
 		this.pageTSConfiguration = this.editorConfiguration.buttons.acronym;
 		this.acronymUrl = this.pageTSConfiguration.acronymUrl;
-		this.acronymModulePath = this.pageTSConfiguration.pathAcronymModule;
-		
+		this.data = this.getJavascriptFile(this.acronymUrl, 'noEval');
+		if (this.data) {
+			eval(this.data);
+		};
+		this.data = {
+			acronym: acronyms,
+			abbr: abbreviations
+		};
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.7",
+			version		: "2.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -67,14 +70,27 @@
 			tooltip		: this.localize("Insert/Modify Acronym"),
 			action		: "onButtonPress",
 			hide		: (this.pageTSConfiguration.noAcronym && this.pageTSConfiguration.noAbbr),
-			dialog		: true
+			dialog		: true,
+			contextMenuTitle: this.localize(buttonId + '-contextMenuTitle')
 		};
 		this.registerButton(buttonConfiguration);
 		
 		return true;
 	 },
-	 
 	/*
+	 * Sets of default configuration values for dialogue form fields
+	 */
+	configDefaults: {
+		combo: {
+			editable: true,
+			typeAhead: true,
+			triggerAction: 'all',
+			forceSelection: true,
+			mode: 'local',
+			helpIcon: true
+		}
+	},
+	/*
 	 * This function gets called when the button was pressed
 	 *
 	 * @param	object		editor: the editor instance
@@ -82,58 +98,434 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function(editor, id) {
+	onButtonPress: function(editor, id) {
+			// Could be a button or its hotkey
+		var buttonId = this.translateHotKey(id);
+		buttonId = buttonId ? buttonId : id;
 		var selection = editor._getSelection();
-		var html = editor.getSelectedHTML();
-		this.abbr = editor._activeElement(selection);
-		this.abbrType = null;
+		var abbr = editor._activeElement(selection);
 			// Working around Safari issue
-		if (!this.abbr && this.getPluginInstance("StatusBar") && this.getPluginInstance("StatusBar").getSelection()) {
-			this.abbr = this.getPluginInstance("StatusBar").getSelection();
+		if (!abbr && this.editor.statusBar && this.editor.statusBar.getSelection()) {
+			abbr = this.editor.statusBar.getSelection();
 		}
-		if (!(this.abbr != null && /^(acronym|abbr)$/i.test(this.abbr.nodeName))) {
-			this.abbr = editor._getFirstAncestor(selection, ["acronym", "abbr"]);
+		if (!abbr || !/^(acronym|abbr)$/i.test(abbr.nodeName)) {
+			abbr = editor._getFirstAncestor(selection, ['acronym', 'abbr']);
 		}
-		if (this.abbr != null && /^(acronym|abbr)$/i.test(this.abbr.nodeName)) {
-			this.param = { title : this.abbr.title, text : this.abbr.innerHTML};
-			this.abbrType = this.abbr.nodeName.toLowerCase();
-		} else {
-			this.param = { title : "", text : html};
-		}
-		this.dialog = this.openDialog("Acronym", this.makeUrlFromModulePath(this.acronymModulePath), null, null, {width:580, height:280});
+		var type = !Ext.isEmpty(abbr) ? abbr.nodeName.toLowerCase() : '';
+		this.params = {
+			abbr: abbr,
+			title: !Ext.isEmpty(abbr) ? abbr.title : '',
+			text: !Ext.isEmpty(abbr) ? abbr.innerHTML : this.editor.getSelectedHTML()
+		};
+			// Open the dialogue window
+		this.openDialogue(
+			'Insert/Modify Acronym',
+			buttonId,
+			this.getWindowDimensions({ width: 580}, buttonId),
+			this.buildTabItemsConfig(abbr),
+			this.buildButtonsConfig(abbr, this.okHandler, this.deleteHandler),
+			(type == 'acronym') ? 1 : 0
+		);
 		return false;
 	},
-	
 	/*
-	 * This function removes the given markup element
+	 * Open the dialogue window
+	 *
+	 * @param	string		title: the window title
+	 * @param	string		buttonId: the itemId of the button that was pressed
+	 * @param	integer		dimensions: the opening width of the window
+	 * @param	object		tabItems: the configuration of the tabbed panel
+	 * @param	object		buttonsConfig: the configuration of the buttons
+	 * @param	number		activeTab: index of the opening tab
+	 *
+	 * @return	void
 	 */
-	removeMarkup : function(element) {
-		var bookmark = this.editor.getBookmark(this.editor._createRange(this.editor._getSelection()));
-		var parent = element.parentNode;
-		while (element.firstChild) {
-			parent.insertBefore(element.firstChild, element);
+	openDialogue: function (title, buttonId, dimensions, tabItems, buttonsConfig, activeTab) {
+		this.dialog = new Ext.Window({
+			title: this.localize(title),
+			cls: 'htmlarea-window',
+				// As of ExtJS 3.1, JS error with IE when the window is resizable
+			resizable: !Ext.isIE,
+			border: false,
+			width: dimensions.width,
+			height: 'auto',
+			iconCls: buttonId,
+			listeners: {
+				close: {
+					fn: this.onClose,
+					scope: this
+				}
+			},
+			items: {
+				xtype: 'tabpanel',
+				activeTab: activeTab ? activeTab : 0,
+				defaults: {
+					xtype: 'container',
+					layout: 'form',
+					defaults: {
+						labelWidth: 150
+					}
+				},
+				listeners: {
+					tabchange: {
+						fn: this.syncHeight,
+						scope: this
+					}
+				},
+				items: tabItems
+			},
+			buttons: buttonsConfig
+		});
+		this.show();
+	},
+	/*
+	 * Build the dialogue tab items config
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the tab items configuration
+	 */
+	buildTabItemsConfig: function (element) {
+		var type = !Ext.isEmpty(element) ? element.nodeName.toLowerCase() : '';
+		var tabItems = [];
+		var abbrTabItems = [];
+			// abbr tab not shown if the current selection is an acronym
+		if (type !== 'acronym') {
+			if (!this.pageTSConfiguration.noAbbr) {
+				this.addConfigElement(this.buildDefinedTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), abbrTabItems);
+			}
+			this.addConfigElement(this.buildUseTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), abbrTabItems);
 		}
-		parent.removeChild(element);
-		this.editor.selectRange(this.editor.moveToBookmark(bookmark));
+		if (!Ext.isEmpty(abbrTabItems)) {
+			tabItems.push({
+				title: this.localize('Abbreviation'),
+				itemId: 'abbr',
+				items: abbrTabItems
+			});
+		}
+		var acronymTabItems = [];
+			// acronym tab not shown if the current selection is an abbr
+		if (type !== 'abbr') {
+			if (!this.pageTSConfiguration.noAcronym) {
+				this.addConfigElement(this.buildDefinedTermFieldsetConfig((type == 'acronym') ? element : null, 'acronym'), acronymTabItems);
+			}
+			this.addConfigElement(this.buildUseTermFieldsetConfig((type == 'abbr') ? element : null, 'abbr'), acronymTabItems);
+		}
+		if (!Ext.isEmpty(acronymTabItems)) {
+			tabItems.push({
+				title: this.localize('Acronym'),
+				itemId: 'acronym',
+				items: acronymTabItems
+			});
+		}
+		return tabItems;
 	},
-	
 	/*
-	 * This function gets called when the toolbar is updated
+	 * Build the dialogue buttons config
+	 *
+	 * @param	object		element: the element being edited, if any
+	 * @param	function	okHandler: the handler for the ok button
+	 * @param	function	deleteHandler: the handler for the delete button
+	 *
+	 * @return	object		the buttons configuration
 	 */
-	onUpdateToolbar : function () {
-		if (this.editor.getMode() === "wysiwyg" && this.editor.isEditable()) {
-			var buttonId = "Acronym";
-			if (this.isButtonInToolbar(buttonId)) {
-				var el = this.editor.getParentElement();
-				if (el) {
-					this.editor._toolbarObjects[buttonId].state("enabled", !((el.nodeName.toLowerCase() == "acronym" && this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == "abbr" && this.pageTSConfiguration.noAbbr)));
-					this.editor._toolbarObjects[buttonId].state("active", ((el.nodeName.toLowerCase() == "acronym" && !this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == "abbr" && !this.pageTSConfiguration.noAbbr)));
+	buildButtonsConfig: function (element, okHandler, deleteHandler) {
+		var buttonsConfig = [this.buildButtonConfig('Cancel', this.onCancel)];
+		if (element) {
+			buttonsConfig.push(this.buildButtonConfig('Delete', deleteHandler));
+		}
+		buttonsConfig.push(this.buildButtonConfig('OK', okHandler));
+		return buttonsConfig;
+	},
+	/*
+	 * This function builds the configuration object for the defined Abbreviation or Acronym fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildDefinedTermFieldsetConfig: function (element, type) {
+		var itemsConfig = [];
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			displayField: 'term',
+			valueField: 'term',
+			fieldLabel: this.localize('Unabridged_term'),
+			itemId: 'termSelector',
+			helpTitle: this.localize('Select_a_term'),
+			tpl: '<tpl for="."><div ext:qtip="{abbr}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{term}</div></tpl>',
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'term'}, { name: 'abbr'},  { name: 'language'}],
+				data: this.data[type]
+			}),
+			width: 350,
+			listeners: {
+				beforerender: {
+					fn: this.onSelectorRender,
+					scope: this
+				},
+				select: {
+					fn: this.onTermSelect,
+					scope: this
 				}
-				if (this.dialog) {
-					this.dialog.focus();
+			}
+		}, this.configDefaults['combo']));
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			displayField: 'abbr',
+			valueField: 'abbr',
+			tpl: '<tpl for="."><div ext:qtip="{language}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{abbr}</div></tpl>',
+			fieldLabel: this.localize('Abridged_term'),
+			itemId: 'abbrSelector',
+			helpTitle: this.localize('Select_an_' + type),
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'term'}, { name: 'abbr'},  { name: 'language'}],
+				data: this.data[type]
+			}),
+			width: 100,
+			listeners: {
+				beforerender: {
+					fn: this.onSelectorRender,
+					scope: this
+				},
+				select: {
+					fn: this.onAbbrSelect,
+					scope: this
 				}
 			}
+		}, this.configDefaults['combo']));
+		var languageObject = this.getPluginInstance('Language');
+		if (this.getButton('Language')) {
+			var languageStore = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'} ],
+				data: this.getDropDownConfiguration('Language').options
+			});
+			var selectedLanguage = !Ext.isEmpty(element) ? languageObject.getLanguageAttribute(element) : 'none';
+			if (selectedLanguage !== 'none') {
+				languageStore.removeAt(0);
+				languageStore.insert(0, new languageStore.recordType({
+					text: languageObject.localize('Remove language mark'),
+					value: 'none'
+				}));
+			}
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Language'),
+				itemId: 'language',
+				helpTitle: this.localize('Select_a_language'),
+				helpText: this.localize('Language_' + type + '_helpText'),
+				valueField: 'value',
+				displayField: 'text',
+				tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>',
+				store: languageStore,
+				width: 200,
+				value: selectedLanguage
+			}, this.configDefaults['combo']));
 		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Defined_' + type),
+			items: itemsConfig,
+			listeners: {
+				render: {
+					fn: this.onDefinedTermFieldsetRender,
+					scope: this
+				}
+			}
+		};
+	},
+	/*
+	 * Handler on rendering the defined abbreviation fieldset
+	 * If an abbr is selected but no term is selected, select any corresponding term with the correct language value, if any
+	 */
+	onDefinedTermFieldsetRender: function (fieldset) {
+		var termSelector = fieldset.find('itemId', 'termSelector')[0];
+		var term = termSelector.getValue();
+		var abbrSelector = fieldset.find('itemId', 'abbrSelector')[0];
+		var abbr = abbrSelector.getValue();
+		var language = '';
+		var languageSelector = fieldset.find('itemId', 'language')[0];
+		if (languageSelector) {
+			var language = languageSelector.getValue();
+			if (language == 'none') {
+				language = '';
+			}
+		}
+		if (abbr && !term) {
+			var abbrStore = abbrSelector.getStore();
+			var index = abbrStore.findBy(function (record) {
+				return record.get('abbr') == abbr && (!languageSelector || record.get('language') == language);
+			}, this);
+			if (index !== -1) {
+				term = abbrStore.getAt(index).get('term');
+				termSelector.setValue(term);
+				fieldset.ownerCt.find('itemId', 'useTerm')[0].setValue(term);
+			}
+		}
+	},
+	/*
+	 * Filter the term and abbr selector lists
+	 * Set initial values
+	 * If there is already an abbr and the filtered list has only one or no element, hide the fieldset
+	 */
+	onSelectorRender: function (combo) {
+		var store = combo.getStore();
+		store.filterBy(function (record) {
+			return !this.params.text || !this.params.title || this.params.text == record.get('term') || this.params.title == record.get('term') || this.params.title == record.get('abbr');
+		}, this);
+			// Make sure the combo list is filtered
+		store.snapshot = store.data;
+		var store = combo.getStore();
+		if (combo.getItemId() == 'termSelector' && this.params.title) {
+			var index = store.findExact('term', this.params.title);
+			if (index !== -1) {
+				combo.setValue(store.getAt(index).get('term'));
+			}
+		} else if (combo.getItemId() == 'abbrSelector' && this.params.text) {
+			var index = store.findExact('abbr', this.params.text);
+			if (index !== -1) {
+				combo.setValue(store.getAt(index).get('abbr'));
+			}
+		}
+		if (this.params.abbr && store.getCount() < 2) {
+			combo.ownerCt.hide();
+		}
+	},
+	/*
+	 * Handler when a term is selected
+	 */
+	onTermSelect: function (combo, record, index) {
+		var tab = combo.findParentByType('container');
+		var term = record.get('term');
+		var abbr = record.get('abbr');
+		var language = record.get('language');
+			// Update the abbreviation selector
+		var abbrSelector = tab.find('itemId', 'abbrSelector')[0];
+		abbrSelector.setValue(abbr);
+			// Update the language selector
+		var languageSelector = tab.find('itemId', 'language');
+		if (!Ext.isEmpty(languageSelector)) {
+			if (language) {
+				languageSelector[0].setValue(language);
+			} else {
+				languageSelector[0].setValue('none');
+			}
+		}
+			// Update the term to use
+		tab.find('itemId', 'useTerm')[0].setValue(term);
+	},
+	/*
+	 * Handler when an abbreviation or acronym is selected
+	 */
+	onAbbrSelect: function (combo, record, index) {
+		var tab = combo.findParentByType('container');
+		var term = record.get('term');
+		var language = record.get('language');
+			// Update the term selector
+		var termSelector = tab.find('itemId', 'termSelector')[0];
+		termSelector.setValue(term);
+			// Update the language selector
+		var languageSelector = tab.find('itemId', 'language');
+		if (!Ext.isEmpty(languageSelector)) {
+			if (language) {
+				languageSelector[0].setValue(language);
+			} else {
+				languageSelector[0].setValue('none');
+			}
+		}
+			// Update the term to use
+		tab.find('itemId', 'useTerm')[0].setValue(term);
+	},
+	/*
+	 * This function builds the configuration object for the Abbreviation or Acronym to use fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildUseTermFieldsetConfig: function (element, type) {
+		var itemsConfig = [];
+		itemsConfig.push({
+			fieldLabel: this.localize('Use_this_term'),
+			labelSeparator: '',
+			itemId: 'useTerm',
+			value: element ? element.title : '',
+			width: 300,
+			helpTitle: this.localize('Use_this_term_explain')
+		});
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Term_to_abridge'),
+			defaultType: 'textfield',
+			defaults: {
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * Handler when the ok button is pressed
+	 */
+	okHandler: function (button, event) {
+		this.restoreSelection();
+		var tab = this.dialog.findByType('tabpanel')[0].getActiveTab();
+		var type = tab.getItemId();
+		var languageSelector = tab.find('itemId', 'language');
+		var language = !Ext.isEmpty(languageSelector) ? languageSelector[0].getValue() : '';
+		var term = tab.find('itemId', 'termSelector')[0].getValue();
+		if (!this.params.abbr) {
+			var abbr = this.editor.document.createElement(type);
+			abbr.title = tab.find('itemId', 'useTerm')[0].getValue();
+			if (term == abbr.title) {
+				abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue();
+			} else {
+				abbr.innerHTML = this.params.text;
+			}
+			if (language) {
+				this.getPluginInstance('Language').setLanguageAttributes(abbr, language);
+			}
+			this.editor.insertNodeAtSelection(abbr);
+		} else {
+			var abbr = this.params.abbr;
+			abbr.title = tab.find('itemId', 'useTerm')[0].getValue();
+			if (language) {
+				this.getPluginInstance('Language').setLanguageAttributes(abbr, language);
+			}
+			if (term == abbr.title) {
+				abbr.innerHTML = tab.find('itemId', 'abbrSelector')[0].getValue();
+			}
+		}
+		this.close();
+		event.stopEvent();
+	},
+	/*
+	 * Handler when the delete button is pressed
+	 */
+	deleteHandler: function (button, event) {
+		this.restoreSelection();
+		var abbr = this.params.abbr;
+		if (abbr) {
+			this.editor.removeMarkup(abbr);
+		}
+		this.close();
+		event.stopEvent();
+	},
+	/*
+	 * This function gets called when the toolbar is updated
+	 */
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if ((mode === 'wysiwyg') && this.editor.isEditable()) {
+			var el = this.editor.getParentElement();
+			if (el) {
+				button.setDisabled(((el.nodeName.toLowerCase() == 'acronym' && this.pageTSConfiguration.noAcronym) || (el.nodeName.toLowerCase() == 'abbr' && this.pageTSConfiguration.noAbbr)));
+				button.setInactive(!(el.nodeName.toLowerCase() == 'acronym' && !this.pageTSConfiguration.noAcronym) && !(el.nodeName.toLowerCase() == 'abbr' && !this.pageTSConfiguration.noAbbr));
+			}
+			if (this.dialog) {
+				this.dialog.focus();
+			}
+		}
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Acronym/locallang.xml	(copie de travail)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<!-- TYPO3 SVN ID: $Id:$ -->
+<!-- TYPO3 SVN ID: $Id$ -->
 <T3locallang>
 	<meta type="array">
 		<description>Labels for Acronym plugin of htmlArea RTE</description>
@@ -8,6 +8,24 @@
 	<data type="array">
 		<languageKey index="default" type="array">
 			<label index="Insert/Modify Acronym">Insert/Modify Acronym or Abbreviation</label>
+			<label index="Acronym-contextMenuTitle">Insert/modify abbreviation</label>
+			<label index="Term_to_abridge">Term to abridge</label>
+			<label index="Defined_acronym">Pre-defined acronyms</label>
+			<label index="Defined_abbr">Pre-defined abbreviations</label>
+			<label index="Term">Term</label>
+			<label index="Unabridged_term">Unabridged Term</label>
+			<label index="Select_a_term">Select a term</label>
+			<label index="Abridged_term">Abridged Term</label>
+			<label index="Acronym">Acronym</label>
+			<label index="Abbreviation">Abbreviation</label>
+			<label index="Select_an_acronym">Select an acronym</label>
+			<label index="Select_an_abbr">Select an abbreviation</label>
+			<label index="Use_this_term">Use this term</label>
+			<label index="Use_this_term_explain">Associate this term to the current selection</label>
+			<label index="Delete">Delete</label>
+			<label index="Select_a_language">Select a language</label>
+			<label index="Language_abbr_helpText">This is the language for which the abbreviation is defined</label>
+			<label index="Language_acronym_helpText">This is the language for which the acronym is defined</label>
 		</languageKey>
 	</data>
 	<orig_hash type="array">
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -106,7 +106,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.3",
+			version		: "1.4",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -121,48 +121,48 @@
 		 */
 		var buttonId = "FormatBlock";
 		var dropDownConfiguration = {
-			id		: buttonId,
-			tooltip		: this.localize(buttonId + "-Tooltip"),
-			options		: ((this.editorConfiguration.buttons.formatblock && this.editorConfiguration.buttons.formatblock.dropDownOptions) ? this.editorConfiguration.buttons.formatblock.dropDownOptions : null),
-			action		: "onChange",
-			refresh		: null,
-			context		: null
+			id: buttonId,
+			tooltip: this.localize(buttonId + "-Tooltip"),
+			width: (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.width) ? this.buttonsConfiguration.formatblock.width : 200,
+			listWidth:  (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.listWidth) ? this.buttonsConfiguration.formatblock.listWidth : 200,
+			maxHeight: (this.buttonsConfiguration.formatblock && this.buttonsConfiguration.formatblock.maxHeight) ? this.buttonsConfiguration.formatblock.maxHeight : 300,
+			options: (this.buttonsConfiguration.formatblock ? this.buttonsConfiguration.formatblock.data : null),
+			action: "onChange"
 		};
 		this.registerDropDown(dropDownConfiguration);
-		
+
 		/*
 		 * Establishing the list of allowed block elements
 		 */
 		var blockElements = new Array();
-		for (var option in dropDownConfiguration.options) {
-			if (dropDownConfiguration.options.hasOwnProperty(option)) {
-				blockElements.push(dropDownConfiguration.options[option]);
+		Ext.each(dropDownConfiguration.options, function (option) {
+			if (option[1] != 'none') {
+				blockElements.push(option[1]);
 			}
-		}
+		});
 		this.allowedBlockElements = new RegExp( "^(" + blockElements.join("|") + ")$", "i");
-		
+
 		/*
-		 * Registering hot keys
+		 * Registering hot keys for the dropdown list items
 		 */
-		for (var i = 0; i < blockElements.length; ++i) {
-			var configuredHotKey = this.defaultHotKeys[blockElements[i]];
+		Ext.each(blockElements, function (blockElement) {
+			var configuredHotKey = this.defaultHotKeys[blockElement];
 			if (this.editorConfiguration.buttons.formatblock
 					&& this.editorConfiguration.buttons.formatblock.items
-					&& this.editorConfiguration.buttons.formatblock.items[blockElements[i]]
-					&& this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey) {
-				configuredHotKey = this.editorConfiguration.buttons.formatblock.items[blockElements[i]].hotKey;
+					&& this.editorConfiguration.buttons.formatblock.items[blockElement]
+					&& this.editorConfiguration.buttons.formatblock.items[blockElement].hotKey) {
+				configuredHotKey = this.editorConfiguration.buttons.formatblock.items[blockElement].hotKey;
 			}
 			if (configuredHotKey) {
 				var hotKeyConfiguration = {
 					id		: configuredHotKey,
 					cmd		: buttonId,
-					action		: "onHotKey",
-					element		: blockElements[i]
+					element		: blockElement
 				};
 				this.registerHotKey(hotKeyConfiguration);
 			}
-		}
-		
+		}, this);
+
 		/*
 		 * Registering the buttons
 		 */
@@ -171,22 +171,21 @@
 				var button = this.buttonList[buttonId];
 				var buttonConfiguration = {
 					id		: buttonId,
-					tooltip		: this.localize(buttonId + "-Tooltip"),
+					tooltip		: this.localize(buttonId + '-Tooltip') || this.localize(button[2]),
+					contextMenuTitle: this.localize(buttonId + '-contextMenuTitle'),
 					action		: "onButtonPress",
-					context		: button[0],
 					hotKey		: (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null))
 				};
 				this.registerButton(buttonConfiguration);
 			}
 		}
-		
 		return true;
 	 },
 	 
 	/*
 	 * The list of buttons added by this plugin
 	 */
-	buttonList : {
+	buttonList: {
 		Indent			: [null, "TAB", "indent"],
 		Outdent			: [null, "SHIFT-TAB", "outdent"],
 		Blockquote		: [null, null, "blockquote"],
@@ -197,7 +196,8 @@
 		JustifyRight		: [null, "r", "right"],
 		JustifyFull		: [null, "j", "justifyfull"],
 		InsertOrderedList	: [null, null, "orderedlist"],
-		InsertUnorderedList	: [null, null, "unorderedlist"]
+		InsertUnorderedList	: [null, null, "unorderedlist"],
+		InsertHorizontalRule	: [null, null, "inserthorizontalrule"]
 	},
 	
 	/*
@@ -234,10 +234,8 @@
 	/*
 	 * This function gets called when some block element was selected in the drop-down list
 	 */
-	onChange : function (editor, buttonId) {
-		var tbobj = this.editor._toolbarObjects[buttonId];
-		var blockElement = document.getElementById(tbobj.elementId).value;
-		this.applyBlockElement(buttonId, blockElement);
+	onChange : function (editor, combo, record, index) {
+		this.applyBlockElement(combo.itemId, combo.getValue());
 	},
 	
 	applyBlockElement : function(buttonId, blockElement) {
@@ -297,7 +295,7 @@
 		this.editor.focusEditor();
 		var selection = editor._getSelection();
 		var range = editor._createRange(selection);
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(selection, range);
 		if (target) {
 			parentElement = target;
@@ -307,7 +305,6 @@
 		}
 		var blockAncestors = this.getBlockAncestors(parentElement);
 		var tableCell = null;
-		
 		if (id === "TAB" || id === "SHIFT-TAB") {
 			for (var i = blockAncestors.length; --i >= 0;) {
 				if (/^(td|th)$/i.test(blockAncestors[i].nodeName)) {
@@ -317,7 +314,6 @@
 			}
 		}
 		var fullNodeTextSelected = (HTMLArea.is_gecko && parentElement.textContent === range.toString()) || (HTMLArea.is_ie && parentElement.innerText === range.text);
-
 		switch (buttonId) {
 			case "Indent" :
 				if (/^(ol|ul)$/i.test(parentElement.nodeName) && !(fullNodeTextSelected && !/^(li)$/i.test(parentElement.parentNode.nodeName))) {
@@ -334,6 +330,7 @@
 						this.indentSelectedListElements(parentElement, range);
 					}
 				} else if (tableCell) {
+	
 					var tablePart = tableCell.parentNode.parentNode;
 						// Get next cell in same table part
 					var nextCell = tableCell.nextSibling ? tableCell.nextSibling : (tableCell.parentNode.nextSibling ? tableCell.parentNode.nextSibling.cells[0] : null);
@@ -349,7 +346,6 @@
 						    case "tfoot":
 							this.editor.selectNodeContents(tablePart.parentNode.lastChild.lastChild.lastChild, true);
 						}
-	
 					}
 					if (!nextCell) {
 						if (this.editor.plugins.TableOperations) {
@@ -359,6 +355,9 @@
 						}
 					}
 					if (nextCell) {
+						if (Ext.isOpera && !nextCell.hasChildNodes()) {
+							nextCell.appendChild(this.editor.document.createElement('br'));
+						}
 						this.editor.selectNodeContents(nextCell, true);
 					}
 				} else  if (this.useBlockquote) {
@@ -415,6 +414,9 @@
 						}
 					}
 					if (previousCell) {
+						if (Ext.isOpera && !previousCell.hasChildNodes()) {
+							previousCell.appendChild(this.editor.document.createElement('br'));
+						}
 						this.editor.selectNodeContents(previousCell, true);
 					}
 				} else  if (this.useBlockquote) {
@@ -535,6 +537,9 @@
 			case "InsertUnorderedList":
 				this.insertList(buttonId, parentElement);
 				break;
+			case "InsertHorizontalRule":
+				this.editor.execCommand('InsertHorizontalRule');
+				break;
 			case "none" :
 				if (this.isAllowedBlockElement(parentElement.nodeName)) {
 					this.removeElement(parentElement);
@@ -919,44 +924,61 @@
 			this.editor.selectNodeContents(paragraph, true);
 		}
 	},
-	
 	/*
-	 * This function gets called by the main editor event handler when a key was pressed.
+	 * This function gets called when the plugin is generated
+	 */
+	onGenerate: function () {
+			// Register the enter key handler for IE when the cursor is at the end of a dt or a dd element
+		if (Ext.isIE) {
+			this.editor.iframe.keyMap.addBinding({
+				key: Ext.EventObject.ENTER,
+				shift: false,
+				handler: this.onKey,
+				scope: this
+			});
+		}
+	},
+	/*
+	 * This function gets called when the enter key was pressed in IE
 	 * It will process the enter key for IE when the cursor is at the end of a dt or a dd element
+	 *
+	 * @param	string		key: the key code
+	 * @param	object		event: the Ext event object (keydown)
+	 *
+	 * @return	boolean		false, if the event was taken care of
 	 */
-	onKeyPress : function (ev) {
-		if (HTMLArea.is_ie && ev.keyCode == 13 && !ev.shiftKey) {
-			var selection = this.editor._getSelection();
-			if (this.editor._selectionEmpty(selection)) {
-				var range = this.editor._createRange(selection);
-				var parentElement = this.editor.getParentElement(selection, range);
-				while (parentElement && !HTMLArea.isBlockElement(parentElement)) {
-					parentElement = parentElement.parentNode;
-				}
-				if (/^(dt|dd)$/i.test(parentElement.nodeName)) {
-					var nodeRange = this.editor._createRange();
-					nodeRange.moveToElementText(parentElement);
-					range.setEndPoint("EndToEnd", nodeRange);
-					if (!range.text || range.text == "\x20") {
-						var item = parentElement.parentNode.insertBefore(this.editor._doc.createElement((parentElement.nodeName.toLowerCase() === "dt") ? "dd" : "dt"), parentElement.nextSibling);
-						item.innerHTML = "\x20";
-						this.editor.selectNodeContents(item, true);
-						return false;
-					}
-				} else if (/^(li)$/i.test(parentElement.nodeName)
-						&& !parentElement.innerText
-						&& parentElement.parentNode.parentNode
-						&& /^(dd|td|th)$/i.test(parentElement.parentNode.parentNode.nodeName)) {
-					var item = parentElement.parentNode.parentNode.insertBefore(this.editor._doc.createTextNode("\x20"), parentElement.parentNode.nextSibling);
-					this.editor.selectNodeContents(parentElement.parentNode.parentNode, false);
-					parentElement.parentNode.removeChild(parentElement);
+	onKey: function (key, event) {
+		var selection = this.editor._getSelection();
+		if (this.editor._selectionEmpty(selection)) {
+			var range = this.editor._createRange(selection);
+			var parentElement = this.editor.getParentElement(selection, range);
+			while (parentElement && !HTMLArea.isBlockElement(parentElement)) {
+				parentElement = parentElement.parentNode;
+			}
+			if (/^(dt|dd)$/i.test(parentElement.nodeName)) {
+				var nodeRange = this.editor._createRange();
+				nodeRange.moveToElementText(parentElement);
+				range.setEndPoint("EndToEnd", nodeRange);
+				if (!range.text || range.text == "\x20") {
+					var item = parentElement.parentNode.insertBefore(this.editor._doc.createElement((parentElement.nodeName.toLowerCase() === "dt") ? "dd" : "dt"), parentElement.nextSibling);
+					item.innerHTML = "\x20";
+					this.editor.selectNodeContents(item, true);
+					event.stopEvent();
 					return false;
 				}
+			} else if (/^(li)$/i.test(parentElement.nodeName)
+					&& !parentElement.innerText
+					&& parentElement.parentNode.parentNode
+					&& /^(dd|td|th)$/i.test(parentElement.parentNode.parentNode.nodeName)) {
+				var item = parentElement.parentNode.parentNode.insertBefore(this.editor._doc.createTextNode("\x20"), parentElement.parentNode.nextSibling);
+				this.editor.selectNodeContents(parentElement.parentNode.parentNode, false);
+				parentElement.parentNode.removeChild(parentElement);
+				event.stopEvent();
+				return false;
 			}
 		}
 		return true;
 	},
-	
 	/*
 	 * This function removes any disallowed class or mutually exclusive classes from the class attribute of the node
 	 */
@@ -984,39 +1006,30 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		if (this.getEditorMode() === "textmode" || !this.editor.isEditable()) {
-			return false;
-		}
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
-		var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement();
-		if (parentElement.nodeName.toLowerCase() === "body") return false;
-		while (parentElement && !HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName)) {
-			parentElement = parentElement.parentNode;
-		}
-		var blockAncestors = this.getBlockAncestors(parentElement);
-		
-		var selection = this.editor._getSelection();
-		var endBlocks = this.editor.getEndBlocks(selection);
-		var startAncestors = this.getBlockAncestors(endBlocks.start);
-		var endAncestors = this.getBlockAncestors(endBlocks.end);
-		var index = 0;
-		while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) {
-			++index;
-		}
-		if (endBlocks.start === endBlocks.end || !startAncestors[index]) {
-			--index;
-		}
-		var dropDownConfiguration = this.getDropDownConfiguration("FormatBlock");
-		if ((typeof(dropDownConfiguration) !== "undefined") && this.isButtonInToolbar(dropDownConfiguration.id)) {
-			this.updateDropDown(dropDownConfiguration, blockAncestors[blockAncestors.length-1], startAncestors[index]);
-		}
-		
-		var commandState;
-		for (var buttonId in this.buttonList) {
-			commandState = false;
-			if (this.buttonList.hasOwnProperty(buttonId) && this.isButtonInToolbar(buttonId)) {
-				switch (buttonId) {
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
+			var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement();
+			if (!/^body$/i.test(parentElement.nodeName)) {
+				while (parentElement && !HTMLArea.isBlockElement(parentElement) || /^li$/i.test(parentElement.nodeName)) {
+					parentElement = parentElement.parentNode;
+				}
+				var blockAncestors = this.getBlockAncestors(parentElement);
+				var endBlocks = this.editor.getEndBlocks(this.editor._getSelection());
+				var startAncestors = this.getBlockAncestors(endBlocks.start);
+				var endAncestors = this.getBlockAncestors(endBlocks.end);
+				var index = 0;
+				while (index < startAncestors.length && index < endAncestors.length && startAncestors[index] === endAncestors[index]) {
+					++index;
+				}
+				if (endBlocks.start === endBlocks.end || !startAncestors[index]) {
+					--index;
+				}
+				var commandState = false;
+				switch (button.itemId) {
+					case 'FormatBlock':
+						this.updateDropDown(button, blockAncestors[blockAncestors.length-1], startAncestors[index]);
+						break;
 					case "Outdent" :
 						if (this.useBlockquote) {
 							for (var j = blockAncestors.length; --j >= 0;) {
@@ -1029,19 +1042,19 @@
 							commandState = true;
 						} else {
 							for (var j = blockAncestors.length; --j >= 0;) {
-								if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent)) {
+								if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) {
 									commandState = true;
 									break;
 								}
 							}
 						}
-						this.editor._toolbarObjects[buttonId].state("enabled", commandState);
+						button.setDisabled(!commandState);
 						break;
 					case "Indent" :
 						break;
 					case "InsertParagraphBefore" :
 					case "InsertParagraphAfter"  :
-						this.editor._toolbarObjects[buttonId].state("enabled", !(/^(body)$/i.test(startAncestors[index].nodeName)));
+						button.setDisabled(/^(body)$/i.test(startAncestors[index].nodeName));
 						break;
 					case "Blockquote" :
 						for (var j = blockAncestors.length; --j >= 0;) {
@@ -1050,7 +1063,7 @@
 								break;
 							}
 						}
-						this.editor._toolbarObjects[buttonId].state("active", commandState);
+						button.setInactive(!commandState);
 						break;
 					case "JustifyLeft"   :
 					case "JustifyCenter" :
@@ -1058,37 +1071,38 @@
 					case "JustifyFull"   :
 						if (this.useAlignAttribute) {
 							try {
-								commandState = this.editor._doc.queryCommandState(buttonId);
+								commandState = this.editor._doc.queryCommandState(button.itemId);
 							} catch(e) {
 								commandState = false;
 							}
 						} else {
 							if (/^(body)$/i.test(startAncestors[index].nodeName)) {
-								this.editor._toolbarObjects[buttonId].state("enabled", false);
+								button.setDisabled(true);
 							} else {
-								this.editor._toolbarObjects[buttonId].state("enabled", true);
+								button.setDisabled(false);
 								commandState = true;
 								for (var block = startAncestors[index]; block; block = block.nextSibling) {
-									commandState = commandState && HTMLArea._hasClass(block, this.useClass[buttonId]);
+									commandState = commandState && HTMLArea._hasClass(block, this.useClass[button.itemId]);
 									if (block == endAncestors[index]) {
 										break;
 									}
 								}
 							}
 						}
-						this.editor._toolbarObjects[buttonId].state("active", commandState);
+						button.setInactive(!commandState);
 						break;
 					case "InsertOrderedList":
 					case "InsertUnorderedList":
 						try {
-							commandState = this.editor._doc.queryCommandState(buttonId);
+							commandState = this.editor._doc.queryCommandState(button.itemId);
 						} catch(e) {
 							commandState = false;
 						}
-						this.editor._toolbarObjects[buttonId].state("active", commandState);
+						button.setInactive(!commandState);
 						break;
 					default	:
 						break;
+		
 				}
 			}
 		}
@@ -1097,40 +1111,35 @@
 	/*
 	 * This function updates the drop-down list of block elements
 	 */
-	updateDropDown : function(dropDownConfiguration, deepestBlockAncestor, startAncestor) {
-		
-		var select = document.getElementById(this.editor._toolbarObjects[dropDownConfiguration.id].elementId);
-		var options = select.options;
-		for (var i = options.length; --i >= 0;) {
-			options[i].selected = false;
-		}
-		select.selectedIndex = 0;
-		options[0].selected = true;
-		options[0].style.display = "list-item";
-		options[0].text = this.localize("No block");
-		
+	updateDropDown : function(select, deepestBlockAncestor, startAncestor) {
+		var store = select.getStore();
+		store.removeAt(0);
+		var index = -1;
 		if (deepestBlockAncestor) {
 			var nodeName = deepestBlockAncestor.nodeName.toLowerCase();
-			for (i = options.length; --i >= 0;) {
-				var item = this.formatBlockItems[options[i].value];
-				if (item && item.tagName == nodeName && item.addClass && HTMLArea._hasClass(deepestBlockAncestor, item.addClass)) {
-					options[i].selected = true;
-					select.selectedIndex = i;
-					options[0].text = this.localize("Remove block");
-					break;
-				}
+				// Could be a custom item ...
+			index = store.findBy(function(record, id) {
+				var item = this.formatBlockItems[record.get('value')];
+				return item && item.tagName == nodeName && item.addClass && HTMLArea._hasClass(deepestBlockAncestor, item.addClass);
+			}, this);
+			if (index == -1) {
+					// ... or a standard one
+				index = store.findExact('value', nodeName);
 			}
-			if (!select.selectedIndex) {
-				for (i = options.length; --i >= 0;) {
-					if (nodeName === options[i].value.toLowerCase()) {
-						options[i].selected = true;
-						select.selectedIndex = i;
-						options[0].text = this.localize("Remove block");
-						break;
-					}
-				}
-			}
 		}
+		if (index == -1) {
+			store.insert(0, new store.recordType({
+				text: this.localize('No block'),
+				value: 'none'
+			}));
+			select.setValue('none');
+		} else {
+			store.insert(0, new store.recordType({
+				text: this.localize('Remove block'),
+				value: 'none'
+			}));
+			select.setValue(store.getAt(index+1).get('value'));
+		}
 	},
 	
 	/*
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/locallang.xml	(copie de travail)
@@ -13,6 +13,8 @@
 			<label index="FormatBlock-Tooltip">Type of block</label>
 			<label index="InsertParagraphBefore-Tooltip">Insert a paragraph before the current block</label>
 			<label index="InsertParagraphAfter-Tooltip">Insert a paragraph after the current block</label>
+			<label index="InsertParagraphBefore-contextMenuTitle">Insert paragraph before</label>
+			<label index="InsertParagraphAfter-contextMenuTitle">Insert paragraph after</label>
 			<label index="JustifyLeft-Tooltip">Justify left</label>
 			<label index="JustifyCenter-Tooltip">Center</label>
 			<label index="JustifyRight-Tooltip">Justify right</label>
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-* (c) 2007-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+* (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -100,7 +100,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.3",
+			version		: "1.4",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -111,30 +111,34 @@
 		this.registerPluginInformation(pluginInformation);
 		
 		/*
-		 * Registeringthe drop-down list
+		 * Registering the drop-down list
 		 */
-		var dropDownId = "BlockStyle";
+		var dropDownId = 'BlockStyle';
+		var fieldLabel = this.pageTSconfiguration.fieldLabel;
+		if (Ext.isEmpty(fieldLabel) && this.isButtonInToolbar('I[Block style label]')) {
+			fieldLabel = this.localize('Block style label');
+		}
 		var dropDownConfiguration = {
-			id		: dropDownId,
-			tooltip		: this.localize(dropDownId + "-Tooltip"),
-			textMode	: false,
-			options		: {"":""},
-			action		: "onChange",
-			refresh		: "generate",
-			context		: null
+			id: dropDownId,
+			tooltip: this.localize(dropDownId + '-Tooltip'),
+			fieldLabel: fieldLabel,
+			width: this.pageTSconfiguration.width ? this.pageTSconfiguration.width : 'auto',
+			listWidth:  this.pageTSconfiguration.listWidth ? this.pageTSconfiguration.listWidth : 250,
+			maxHeight: this.pageTSconfiguration.maxHeight ? this.pageTSconfiguration.maxHeight : 300,
+			options: [[this.localize('No style'), 'none']],
+			action: 'onChange',
+			storeFields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ],
+			tpl: '<tpl for="."><div ext:qtip="{value}" style="{style}text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
 		};
 		this.registerDropDown(dropDownConfiguration);
-		
 		return true;
 	},
 	
 	/*
 	 * This function gets called when some block style was selected in the drop-down list
 	 */
-	onChange : function(editor, dropDownId) {
-		var dropDown = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId);
-		var className = dropDown.value;
-		
+	onChange : function (editor, combo, record, index) {
+		var className = combo.getValue();
 		this.editor.focusEditor();
 		var blocks = this.getSelectedBlocks();
 		for (var k = 0; k < blocks.length; ++k) {
@@ -160,9 +164,9 @@
 			for (var i = classNames.length; --i >= 0;) {
 				if (!HTMLArea.reservedClassNames.test(classNames[i])) {
 					HTMLArea._removeClass(node, classNames[i]);
-					if (node.nodeName.toLowerCase() === "table" && this.editor.plugins.TableOperations) {
-						this.editor.plugins.TableOperations.instance.removeAlternatingClasses(node, classNames[i]);
-						this.editor.plugins.TableOperations.instance.removeCountingClasses(node, classNames[i]);
+					if (node.nodeName.toLowerCase() === "table" && this.getPluginInstance('TableOperations')) {
+						this.getPluginInstance('TableOperations').removeAlternatingClasses(node, classNames[i]);
+						this.getPluginInstance('TableOperations').removeCountingClasses(node, classNames[i]);
 					}
 					break;
 				}
@@ -180,8 +184,8 @@
 			} else {
 				HTMLArea._addClass(node, className);
 			}
-			if (nodeName === "table" && this.editor.plugins.TableOperations) {
-				this.editor.plugins.TableOperations.instance.reStyleTable(node);
+			if (nodeName === "table" && this.getPluginInstance('TableOperations')) {
+				this.getPluginInstance('TableOperations').reStyleTable(node);
 			}
 		}
 	},
@@ -191,7 +195,7 @@
 	 */
 	getSelectedBlocks : function() {
 		var block, range, i = 0, blocks = [];
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
 			var selection = this.editor._getSelection();
 			try {
@@ -207,34 +211,32 @@
 		}
 		return blocks;
 	},
-	
 	/*
 	 * This function gets called when the editor is generated
 	 */
-	onGenerate : function() {
+	onGenerate: function() {
+			// Monitor editor changing mode
+		this.editor.iframe.mon(this.editor, 'modeChange', this.onModeChange, this);
 		if (HTMLArea.is_gecko) {
-			this.generate(this.editor, "BlockStyle");
+			this.generate(this.editor, 'BlockStyle');
 		}
 	},
-	
 	/*
 	 * This function gets called when the toolbar is being updated
 	 */
-	onUpdateToolbar : function() {
-		if (this.getEditorMode() === "wysiwyg") {
-			this.generate(this.editor, "BlockStyle");
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg') {
+			this.generate(this.editor, button.itemId);
 		}
 	},
-	
 	/*
 	 * This function gets called when the editor has changed its mode to "wysiwyg"
 	 */
-	onMode : function(mode) {
+	onModeChange: function(mode) {
 		if (this.getEditorMode() === "wysiwyg") {
 			this.generate(this.editor, "BlockStyle");
 		}
 	},
-	
 	/*
 	 * This function gets called on plugin generation, on toolbar update and on change mode
 	 * Re-initiate the parsing of the style sheets, if not yet completed, and refresh our toolbar components
@@ -244,11 +246,7 @@
 			this.updateValue(dropDownId);
 		} else {
 			if (this.cssTimeout) {
-				if (this.editor._iframe.contentWindow) {
-					this.editor._iframe.contentWindow.clearTimeout(this.cssTimeout);
-				} else {
-					window.clearTimeout(this.cssTimeout);
-				}
+				window.clearTimeout(this.cssTimeout);
 				this.cssTimeout = null;
 			}
 			if (this.classesUrl && (typeof(HTMLArea.classesLabels) === "undefined")) {
@@ -262,30 +260,27 @@
 	 * This function updates the current value of the dropdown list
 	 */
 	updateValue : function(dropDownId) {
-		var dropDown = document.getElementById(this.editor._toolbarObjects[dropDownId].elementId);
-		dropDown.disabled = true;
-		
-		var classNames = new Array();
-		var tagName = null;
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
-		var parent = statusBarSelection ? statusBarSelection : this.editor.getParentElement();
-		while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") {
-			parent = parent.parentNode;
+		var dropDown = this.getButton(dropDownId);
+		if (dropDown) {
+			var classNames = new Array();
+			var tagName = null;
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
+			var parent = statusBarSelection ? statusBarSelection : this.editor.getParentElement();
+			while (parent && !HTMLArea.isBlockElement(parent) && parent.nodeName.toLowerCase() != "img") {
+				parent = parent.parentNode;
+			}
+			if (parent) {
+				tagName = parent.nodeName.toLowerCase();
+				classNames = this.getClassNames(parent);
+			}
+			if (tagName && tagName !== "body"){
+				this.buildDropDownOptions(dropDown, tagName);
+				this.setSelectedOption(dropDown, classNames);
+			} else {
+				this.initializeDropDown(dropDown);
+				dropDown.setDisabled(true);
+			}
 		}
-		if (parent) {
-			tagName = parent.nodeName.toLowerCase();
-			classNames = this.getClassNames(parent);
-		}
-		if (tagName && tagName !== "body"){
-			this.buildDropDownOptions(dropDown, tagName);
-			this.setSelectedOption(dropDown, classNames);
-		} else {
-			this.initializeDropDown(dropDown);
-		}
-		dropDown.className = "";
-		if (dropDown.disabled) {
-			dropDown.className = "buttonDisabled";
-		}
 	},
 	
 	/*
@@ -315,29 +310,20 @@
 	 * This function reinitializes the options of the dropdown
 	 */
 	initializeDropDown : function (dropDown) {
-		if (HTMLArea.is_gecko) {
-			while (dropDown.options.length > 0) {
-				dropDown.remove(dropDown.options.length-1);
-			}
-		} else {
-			while (dropDown.firstChild) {
-				dropDown.removeChild(dropDown.firstChild);
-			}
-		}
-		var owner = dropDown.ownerDocument;
-		if (!owner) { // IE5.5 does not report any ownerDocument
-			owner = window.document;
-		}
-		var styleOption = owner.createElement("option");
-		styleOption = dropDown.appendChild(styleOption);
-		styleOption.value = "none";
-		styleOption.text = this.localize("No style");
+		var store = dropDown.getStore();
+		store.removeAll(true);
+		store.insert(0, new store.recordType({
+			text: this.localize('No style'),
+			value: 'none'
+		}));
+		dropDown.setValue('none');
 	},
 	
 	/*
 	 * This function builds the options to be displayed in the dropDown box
 	 */
 	buildDropDownOptions : function (dropDown, tagName) {
+		var store = dropDown.getStore();
 		var cssArray = new Array();
 		this.initializeDropDown(dropDown);
 			// Get classes allowed for all tags
@@ -393,22 +379,16 @@
 			}
 			cssArray = sortedCssArray;
 		}
-		var doc = dropDown.ownerDocument;
-		if (!doc) { // IE5.5 does not report any ownerDocument
-			doc = window.document;
-		}
 		for (var cssClass in cssArray) {
 			if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
-				if (cssClass == "none") {
-					dropDown.options[0].text = cssArray[cssClass];
+				if (cssClass == 'none') {
+					store.getAt(0).set('text', cssArray[cssClass]);
 				} else {
-					var styleOption = doc.createElement("option");
-					styleOption = dropDown.appendChild(styleOption);
-					styleOption.value = cssClass;
-					styleOption.text = cssArray[cssClass];
-					if (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
-						dropDown.options[dropDown.options.length-1].setAttribute("style", HTMLArea.classesValues[cssClass]);
-					}
+					store.add(new store.recordType({
+						text: cssArray[cssClass],
+						value: cssClass,
+						style: (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) ? HTMLArea.classesValues[cssClass] : null
+					}));
 				}
 			}
 		}
@@ -418,36 +398,35 @@
 	 * This function sets the selected option of the dropDown box
 	 */
 	setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) {
-		dropDown.selectedIndex = 0;
+		var store = dropDown.getStore();
+		dropDown.setValue('none');
 		if (classNames.length) {
-			for (var i = dropDown.options.length; --i >= 0;) {
-				if (classNames[classNames.length-1] == dropDown.options[i].value) {
-					dropDown.options[i].selected = true;
-					dropDown.selectedIndex = i;
-					if (!defaultClass) {
-						dropDown.options[0].text = this.localize("Remove style");
-					}
-					break;
+			var index = store.findExact('value', classNames[classNames.length-1]);
+			if (index != -1) {
+				dropDown.setValue(classNames[classNames.length-1]);
+				if (!defaultClass) {
+					store.getAt(0).set('text', this.localize('Remove style'));
 				}
 			}
-			if (dropDown.selectedIndex == 0 && !noUnknown) {
-				dropDown.options[dropDown.options.length] = new Option(this.localize("Unknown style"), classNames[classNames.length-1]);
-				dropDown.options[dropDown.options.length-1].selected = true;
-				dropDown.selectedIndex = dropDown.options.length-1;
-			}
-			for (var i = dropDown.options.length; --i >= 0;) {
-				if (("," + classNames.join(",") + ",").indexOf("," + dropDown.options[i].value + ",") !== -1) {
-					if (dropDown.selectedIndex != i) {
-						dropDown.options[i] = null;
-					}
+			if (index == -1 && !noUnknown) {
+				store.add(new store.recordType({
+					text: this.localize('Unknown style'),
+					value: classNames[classNames.length-1]
+				}));
+				index = store.getCount()-1;
+				dropDown.setValue(classNames[classNames.length-1]);
+				if (!defaultClass) {
+					store.getAt(0).set('text', this.localize('Remove style'));
 				}
 			}
+			store.each(function (option) {
+				if (store.indexOf(option) != index && (',' + classNames.join(',') + ',').indexOf(',' + option.get('value') + ',') != -1) {
+					store.removeAt(store.indexOf(option));
+				}
+				return true;
+			});
 		}
-		if (dropDown.options.length > 1) {
-			dropDown.disabled = false;
-		} else {
-			dropDown.disabled = true;
-		}
+		dropDown.setDisabled(!(store.getCount()>1));
 	},
 	
 	/*
@@ -456,8 +435,7 @@
 	buildCssArray : function(editor, dropDownId) {
 		this.cssArray = this.parseStyleSheet();
 		if (!this.cssLoaded && (this.cssParseCount < 17)) {
-			var buildCssArrayLaterFunctRef = this.makeFunctionReference("buildCssArray");
-			this.cssTimeout = editor._iframe.contentWindow ? editor._iframe.contentWindow.setTimeout(buildCssArrayLaterFunctRef, 200) : window.setTimeout(buildCssArrayLaterFunctRef, 200);
+			this.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]);
 			this.cssParseCount++;
 		} else {
 			this.cssTimeout = null;
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/CharacterMap/character-map.js	(copie de travail)
@@ -3,7 +3,7 @@
 *
 *  (c) 2004 Bernhard Pfeifer novocaine@gmx.net
 *  (c) 2004 systemconcept.de. Authored by Holger Hees based on HTMLArea XTD 1.5 (http://mosforge.net/projects/htmlarea3xtd/).
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -106,7 +106,7 @@
 	 *
 	 * @return	void
 	 */
-	onUpdateToolbar : function () {
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
 			// Reclaim focus
 		if (this.dialog) {
 			this.dialog.focus();
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/context-menu.js	(copie de travail)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  Copyright (c) 2003 dynarch.com. Authored by Mihai Bazon. Sponsored by www.americanbible.org.
-*  Copyright (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  Copyright (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -32,26 +32,28 @@
  *
  * TYPO3 SVN ID: $Id$
  */
-
 ContextMenu = HTMLArea.Plugin.extend({
-	
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-	
 	/*
 	 * This function gets called by the class constructor
 	 */
 	configurePlugin : function(editor) {
-		this.currentMenu = null;
-		this.keys = [];
-		this.eventHandlers = {};
-		
+		this.pageTSConfiguration = this.editorConfiguration.contextMenu;
+		if (this.pageTSConfiguration) {
+			if (this.pageTSConfiguration.showButtons) {
+				this.showButtons = this.pageTSConfiguration.showButtons;
+			}
+			if (this.pageTSConfiguration.hideButtons) {
+				this.hideButtons = this.pageTSConfiguration.hideButtons;
+			}
+		}
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "2.0",
+			version		: "3.0",
 			developer	: "Mihai Bazon & Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "dynarch.com & Stanislas Rolland",
@@ -60,541 +62,201 @@
 			license		: "GPL"
 		};
 		this.registerPluginInformation(pluginInformation);
-		
 		return true;
 	},
-	
 	/*
 	 * This function gets called when the editor gets generated
 	 */
-	onGenerate : function() {
-		this.editor.eventHandlers["contextMenu"] = this.makeFunctionReference("popupMenu");
-		HTMLArea._addEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), (HTMLArea.is_opera ? "mousedown" : "contextmenu"), this.editor.eventHandlers["contextMenu"]);
+	onGenerate: function() {
+			// Build the context menu
+		this.menu = new Ext.menu.Menu({
+			cls: 'htmlarea-context-menu',
+			height: 800,
+			defaultType: 'menuitem',
+			listeners: {
+				itemClick: {
+					fn: this.onItemClick,
+					scope: this
+				},
+				show: {
+					fn: this.onShow,
+					scope: this
+				},
+				hide: {
+					fn: this.onHide,
+					scope: this
+				}
+			},
+			items: this.buildItemsConfig()
+		});
+			// Monitor contextmenu clicks on the iframe
+		this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this, {single: true});
 	},
-	
-	popupMenu : function(ev, target) {
-		if (HTMLArea.is_opera && ev.button < 2) {
-			return false;
-		}
-		var editor = this.editor;
-		if (!ev) var ev = window.event;
-		if (!target) var target = (ev.target) ? ev.target : ev.srcElement;
-		if (this.currentMenu) this.currentMenu.parentNode.removeChild(this.currentMenu);
-		this.keys = [];
-		var ifpos = ContextMenu.getPos(this.editor._iframe);
-		var x = ev.clientX + ifpos.x;
-		var y = ev.clientY + ifpos.y;
-	
-		var doc, list, separator = false;
-	
-		if (!HTMLArea.is_ie) {
-			doc = document;
-		} else {
-			var popup = this.iePopup = window.createPopup();
-			doc = popup.document;
-			var head = doc.getElementsByTagName("head")[0];
-			var link = doc.createElement("link");
-			link.rel = "stylesheet";
-			link.type = "text/css";
-			if ( _editor_CSS.indexOf("http") == -1 ) link.href = _typo3_host_url + _editor_CSS;
-				else link.href = _editor_CSS;
-			head.appendChild(link);
-		}
-	
-		list = doc.createElement("ul");
-		list.className = "htmlarea-context-menu";
-		doc.body.appendChild(list);
-	
-		var options = this.getContextMenu(target);
-		var n = options.length;
-		for (var i=0; i < n; ++i) {
-			var option = options[i];
-			if (!option){
-				separator = true;
-			} else {
-				var item = doc.createElement("li");
-				list.appendChild(item);
-				var label = option[0];
-				if (separator) {
-					HTMLArea._addClass(item, "separator");
-					separator = false;
+	/*
+	 * Create the menu items config
+	 */
+	buildItemsConfig: function () {
+		var itemsConfig = [];
+			// Walk through the editor toolbar configuration nested arrays: [ toolbar [ row [ group ] ] ]
+		var firstInGroup = true, convertedItemId;
+		Ext.each(this.editor.config.toolbar, function (row) {
+				// Add the groups
+			firstInGroup = true;
+			Ext.each(row, function (group) {
+				if (!firstInGroup) {
+					// If a visible item was added to the line
+					itemsConfig.push({
+							xtype: 'menuseparator',
+							cls: 'separator'
+					});
 				}
-				item.__msh = {
-					item:		item,
-					label:		label,
-					action:		option[1],
-					tooltip:	option[2] || null,
-					icon:		option[3] || null,
-					activate:	ContextMenu.activateHandler(item, this),
-					cmd:		option[4] || null,
-					dialog:		option[5] || null
-				};
-				label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
-				if (label != option[0]) this.keys.push([ RegExp.$1, item ]);
-				label = label.replace(/__/, "_");
-				var button = doc.createElement("button");
-				HTMLArea._addClass(button,  "button");
-				if (item.__msh.cmd) {
-					HTMLArea._addClass(button,  item.__msh.cmd);
-					if (editor._toolbarObjects[item.__msh.cmd]  && editor._toolbarObjects[item.__msh.cmd].active) {
-						HTMLArea._addClass(button,  "buttonActive");
+				firstInGroup = true;
+					// Add each item
+				Ext.each(group, function (itemId) {
+					convertedItemId = this.editorConfiguration.convertButtonId[itemId];
+					if ((!this.showButtons  || this.showButtons.indexOf(convertedItemId) !== -1)
+						&& (!this.hideButtons || this.hideButtons.indexOf(convertedItemId) === -1)) {
+						var button = this.getButton(itemId);
+						if (button && button.getXType() === 'htmlareabutton' && !button.hideInContextMenu) {
+							var itemId = button.getItemId();
+							itemsConfig.push({
+								itemId: itemId,
+								cls: 'button',
+								overCls: 'hover',
+								text: (button.contextMenuTitle || button.tooltip.title),
+								iconCls: button.iconCls,
+								helpText: this.localize(itemId + '-helpText') || this.localize(itemId + '-tooltip'),
+								hidden: true
+							});
+							firstInGroup = false;
+						}
 					}
-				} else if (item.__msh.icon) {
-					button.innerHTML = "<img src='" + item.__msh.icon + "' />";
-				}
-				item.appendChild(button);
-				item.innerHTML = item.innerHTML + label;
-					// Setting event handlers on the menu items
-				item.__msh.mouseover = ContextMenu.mouseOverHandler(editor, item);
-				HTMLArea._addEvent(item, "mouseover", item.__msh.mouseover);
-				item.__msh.mouseout = ContextMenu.mouseOutHandler(item);
-				HTMLArea._addEvent(item, "mouseout", item.__msh.mouseout);
-				item.__msh.contextmenu = ContextMenu.itemContextMenuHandler(item);
-				HTMLArea._addEvent(item, "contextmenu", item.__msh.contextmenu);
-				if (!HTMLArea.is_ie) {
-					item.__msh.mousedown = ContextMenu.mouseDownHandler(item);
-					HTMLArea._addEvent(item, "mousedown", item.__msh.mousedown);
-				}
-				item.__msh.mouseup = ContextMenu.mouseUpHandler(item, this);
-				HTMLArea._addEvent(item, "mouseup", item.__msh.mouseup);
-			}
+					return true;
+				}, this);
+				return true;
+			}, this);
+			return true;
+		}, this);
+			// If a visible item was added
+		if (!firstInGroup) {
+			itemsConfig.push({
+					xtype: 'menuseparator',
+					cls: 'separator'
+			});
 		}
-		if (n) {
-			if(!HTMLArea.is_ie) {
-				var dx = x + list.offsetWidth - window.innerWidth - window.pageXOffset + 4;
-				var dy = y + list.offsetHeight - window.innerHeight - window.pageYOffset + 4;
-				if(dx > 0) x -= dx;
-				if(dy > 0) y -= dy;
-				list.style.left = x + "px";
-				list.style.top = y + "px";
-			} else {
-					// determine the size
-				list.style.left = "0px";
-				list.style.top = "0px";
-				var foobar = document.createElement("ul");
-				foobar.className = "htmlarea-context-menu";
-				foobar.innerHTML = list.innerHTML;
-				editor._iframe.contentWindow.parent.document.body.appendChild(foobar);
-				this.iePopup.show(ev.screenX, ev.screenY, foobar.clientWidth+2, foobar.clientHeight+2);
-				editor._iframe.contentWindow.parent.document.body.removeChild(foobar);
-			}
-			this.currentMenu = list;
-			this.timeStamp = (new Date()).getTime();
-			this.eventHandlers["documentClick"] = this.makeFunctionReference("documentClickHandler");
-			HTMLArea._addEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
-			HTMLArea._addEvent((HTMLArea.is_ie ? editor._doc.body : editor._doc), "mousedown", this.eventHandlers["documentClick"]);
-			if (this.keys.length > 0) {
-				this.eventHandlers["keyPress"] = ContextMenu.keyPressHandler(this);
-				HTMLArea._addEvents((HTMLArea.is_ie ? editor._doc.body : editor._doc), ["keypress", "keydown"], this.eventHandlers["keyPress"]);
-			}
-		}
-		HTMLArea._stopEvent(ev);
+		 	// Add special target delete item
+		var itemId = 'DeleteTarget';
+		itemsConfig.push({
+			itemId: itemId,
+			cls: 'button',
+			overCls: 'hover',
+			iconCls: itemId,
+			helpText: this.localize('Remove this node from the document')
+		});
+		return itemsConfig;
+	},
+	/*
+	 * Handler when the menu gets shown
+	 */
+	onShow: function () {
+		this.menu.mun(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this);
+		this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu, {single: true});
+	},
+	/*
+	 * Handler when the menu gets hidden
+	 */
+	onHide: function () {
+		this.menu.mon(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'contextmenu', this.show, this);
+		this.menu.mun(Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement), 'mousedown', this.menu.hide, this.menu);
+	},
+	/*
+	 * Handler to show the context menu
+	 */
+	show: function (event, target) {
+			// Need to wait a while for the toolbar state to be updated
+		this.showMenu.defer(150, this, [event, target]);
+		event.stopEvent();
 		return false;
 	},
-	
-	pushOperations : function (opcodes, elmenus, pluginId) {
-		var editor = this.editor;
-		var pluginInstance = this.editor.plugins[pluginId];
-		if (pluginInstance) {
-			pluginInstance = pluginInstance.instance;
-		}
-		var toolbarObjects = editor._toolbarObjects;
-		var btnList = editor.config.btnList;
-		var enabled = false, opcode, opEnabled = [], i = opcodes.length;
-		for (i; i > 0;) {
-			opcode = opcodes[--i];
-			opEnabled[opcode] = toolbarObjects[opcode]  && toolbarObjects[opcode].enabled;
-			enabled = enabled || opEnabled[opcode];
-		}
-		if (enabled && elmenus.length) {
-			elmenus.push(null);
-		}
-		for (i = opcodes.length; i > 0;) {
-			opcode = opcodes[--i];
-			if (opEnabled[opcode]) {
-				switch (pluginId) {
-					case "TableOperations" :
-						elmenus.push([
-							this.localize(opcode + "-title"),
-							ContextMenu.tableOperationsHandler(editor, pluginInstance, opcode),
-							this.localize(opcode + "-tooltip"),
-							btnList[opcode][1],
-							opcode,
-							btnList[opcode][7]
-							]);
-						break;
-					case "BlockElements" :
-						elmenus.push([this.localize(opcode + "-title"),
-							ContextMenu.blockElementsHandler(editor, null, opcode),
-							this.localize(opcode + "-tooltip"),
-							btnList[opcode][1], opcode]);
-						break;
-					default :
-						elmenus.push([this.localize(opcode + "-title"),
-							ContextMenu.execCommandHandler(editor, opcode),
-							this.localize(opcode + "-tooltip"),
-							btnList[opcode][1], opcode]);
-						break;
-				}
-			}
-		}
+	/*
+	 * Show the context menu
+	 */
+	showMenu: function (event, target) {
+		this.showContextItems(target);
+		var iframeEl = this.editor.iframe.getEl();
+		this.menu.showAt([Ext.get(target).getX() + iframeEl.getX(), Ext.get(target).getY() + iframeEl.getY()]);
 	},
-	
-	getContextMenu : function(target) {
-		var editor = this.editor;
-		var toolbarObjects = editor._toolbarObjects;
-		var config = editor.config;
-		var btnList = config.btnList;
-		var menu = [], opcode;
-		var tbo = this.editor.plugins["TableOperations"];
-		if (tbo) tbo = "TableOperations";
-		
-		var selection = editor.hasSelectedText();
-		if(selection) {
-			if (toolbarObjects['Cut'] && toolbarObjects['Cut'].enabled)  {
-				opcode = "Cut";
-				menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
-			}
-			if (toolbarObjects['Copy'] && toolbarObjects['Copy'].enabled) {
-				opcode = "Copy";
-				menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
-			}
-		}
-		if (toolbarObjects['Paste'] && toolbarObjects['Paste'].enabled) {
-			opcode = "Paste";
-			menu.push([this.localize(opcode), ContextMenu.execCommandHandler(editor, opcode), null, btnList[opcode][1], opcode]);
-		}
-		
-		var currentTarget = target,
-			tmp, tag, link = false,
-			table = null, tr = null, td = null, img = null, list = null, div = null;
-		
-		for(; target; target = target.parentNode) {
-			tag = target.nodeName;
-			if(!tag) continue;
-			tag = tag.toLowerCase();
-			switch (tag) {
-			    case "img":
-				img = target;
-				if (toolbarObjects["InsertImage"] && toolbarObjects["InsertImage"].enabled)  {
-					if (menu.length) menu.push(null);
-					menu.push(
-						[this.localize("Image Properties"),
-							ContextMenu.imageHandler(editor, img),
-							this.localize("Show the image properties dialog"),
-							btnList["InsertImage"][1], "InsertImage"]
-					);
+	/*
+	 * Show items depending on context
+	 */
+	showContextItems: function (target) {
+		var lastIsSeparator = false, lastIsButton = false, xtype, lastVisible;
+		this.menu.cascade(function (menuItem) {
+			xtype = menuItem.getXType();
+			if (xtype === 'menuseparator') {
+				menuItem.setVisible(lastIsButton);
+				lastIsButton = false;
+			} else if (xtype === 'menuitem') {
+				var button = this.getButton(menuItem.getItemId());
+				if (button) {
+					menuItem.setVisible(!button.disabled);
+					lastIsButton = lastIsButton || !button.disabled;
+				} else {
+						// Special target delete item
+					this.deleteTarget = Ext.get(target);
+					if (/^(html|body)$/i.test(target.nodeName)) {
+						this.deleteTarget = null;
+					} else if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(target.nodeName)) {
+						var targetAncestor = this.deleteTarget.findParent('table');
+					} else if (/^(ul|ol|dl|li|dd|dt)$/i.test(target.nodeName)) {
+						var targetAncestor = this.deleteTarget.findParent('ul') || this.deleteTarget.findParent('ol') || this.deleteTarget.findParent('dl');
+					}
+					if (targetAncestor) {
+						this.deleteTarget = Ext.get(targetAncestor);
+					}
+					if (this.deleteTarget) {
+						menuItem.setVisible(true);
+						menuItem.setText(this.localize('Remove the') + ' &lt;' + this.deleteTarget.dom.nodeName.toLowerCase() + '&gt; ');
+						lastIsButton = true;
+					} else {
+						menuItem.setVisible(false);
+					}
 				}
-				break;
-			    case "a":
-				link = target;
-				if (toolbarObjects["CreateLink"])  {
-					if (menu.length) menu.push(null);
-					menu.push(
-						[this.localize("Modify Link"),
-							this.linkHandler(link, "ModifyLink"),
-							this.localize("Current URL is") + ': ' + link.href,
-							btnList["CreateLink"][1], "CreateLink"],
-						[this.localize("Check Link"),
-							this.linkHandler(link, "CheckLink"),
-							this.localize("Opens this link in a new window"),
-							null, null],
-						[this.localize("Remove Link"),
-							this.linkHandler(link, "RemoveLink"),
-							this.localize("Unlink the current element"),
-							editor.imgURL("ed_unlink.gif"), "UnLink"]
-					);
-				}
-				break;
-			    case "td":
-			    case "th":
-				td = target;
-				if(!tbo) break;
-				this.pushOperations(["TO-cell-split", "TO-cell-delete", "TO-cell-insert-after", "TO-cell-insert-before", "TO-cell-prop"], menu, tbo);
-				break;
-			    case "tr":
-				tr = target;
-				if(!tbo) break;
-				opcode = "TO-cell-merge";
-				if (toolbarObjects[opcode]  && toolbarObjects[opcode].enabled) {
-					menu.push([this.localize(opcode + "-title"),
-					ContextMenu.tableOperationsHandler(editor, this.editor.plugins.TableOperations.instance, opcode),
-					this.localize(opcode + "-tooltip"),
-					btnList[opcode][1], opcode]);
-				}
-				this.pushOperations(["TO-row-split", "TO-row-delete", "TO-row-insert-under", "TO-row-insert-above", "TO-row-prop"], menu, tbo);
-				break;
-			    case "table":
-				table = target;
-				if(!tbo) break;
-				this.pushOperations(["TO-col-split", "TO-col-delete", "TO-col-insert-after", "TO-col-insert-before", "TO-col-prop"], menu, tbo);
-				this.pushOperations(["TO-toggle-borders", "TO-table-restyle", "TO-table-prop"], menu, tbo);
-				break;
-			    case "ol":
-			    case "ul":
-			    case "dl":
-				list = target;
-				break;
-			    case "div":
-				div = target;
-				break;
-			    case "body":
-				this.pushOperations(["JustifyFull", "JustifyRight", "JustifyCenter", "JustifyLeft"], menu, "BlockElements");
-				break;
 			}
-		}
-		
-		if (selection && !link && btnList.CreateLink) {
-			if (menu.length) menu.push(null);
-			menu.push([this.localize("Make link"),
-				this.linkHandler(link, "MakeLink"),
-				this.localize("Create a link"),
-				btnList["CreateLink"][1],"CreateLink"]);
-		}
-		
-		if (!/^(html|body)$/i.test(currentTarget.nodeName)) {
-			if (/^(table|thead|tbody|tr|td|th|tfoot)$/i.test(currentTarget.nodeName)) {
-				tmp = table;
-				table = null;
-			} else if(list) {
-				tmp = list;
-				list = null;
-			} else {
-				tmp = currentTarget;
+			if (!menuItem.hidden) {
+				lastVisible = menuItem;
 			}
-			if (menu.length) menu.push(null);
-			menu.push(
-			  [this.localize("Remove the") + " &lt;" + tmp.tagName.toLowerCase() + "&gt; " + this.localize("Element"),
-				this.deleteElementHandler(tmp, table), this.localize("Remove this node from the document")],
-			  [this.localize("Insert paragraph before"),
-				ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphBefore"), this.localize("Insert a paragraph before the current node"), null, "InsertParagraphBefore"],
-			  [this.localize("Insert paragraph after"),
-				ContextMenu.blockElementsHandler(editor, tmp, "InsertParagraphAfter"), this.localize("Insert a paragraph after the current node"), null, "InsertParagraphAfter"]
-			);
+		}, this);
+			// Hide the last item if it is a separator
+		if (!lastIsButton) {
+			lastVisible.setVisible(false);
 		}
-		return menu;
 	},
-	
-	closeMenu : function() {
-		HTMLArea._removeEvent((HTMLArea.is_ie ? document.body : document), "mousedown", this.eventHandlers["documentClick"]);
-		HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "mousedown", this.eventHandlers["documentClick"]);
-		if (this.keys.length > 0) HTMLArea._removeEvent((HTMLArea.is_ie ? this.editor._doc.body : this.editor._doc), "keypress", this.eventHandlers["keyPress"]);
-		for (var handler in this.eventHandlers) this.eventHandlers[handler] = null;
-		var e, items = document.getElementsByTagName("li");
-		if (HTMLArea.is_ie) items = this.iePopup.document.getElementsByTagName("li");;
-		for (var i = items.length; --i >= 0 ;) {
-			e = items[i];
-			if ( e.__msh ) {
-				HTMLArea._removeEvent(e, "mouseover", e.__msh.mouseover);
-				e.__msh.mouseover = null;
-				HTMLArea._removeEvent(e, "mouseout", e.__msh.mouseout);
-				e.__msh.mouseout = null;
-				HTMLArea._removeEvent(e, "contextmenu", e.__msh.contextmenu);
-				e.__msh.contextmenu = null;
-				if (!HTMLArea.is_ie) HTMLArea._removeEvent(e, "mousedown", e.__msh.mousedown);
-				e.__msh.mousedown = null;
-				HTMLArea._removeEvent(e, "mouseup", e.__msh.mouseup);
-				e.__msh.mouseup = null;
-				e.__msh.action = null;
-				e.__msh.activate = null;
-				e.__msh = null;
+	/*
+	 * Handler invoked when a menu item is clicked on
+	 */
+	onItemClick: function (item, event) {
+		var button = this.getButton(item.getItemId());
+		if (button) {
+			button.fireEvent('click', button, event);
+		} else if (item.getItemId() === 'DeleteTarget') {
+				// Do not leave a non-ie table cell empty
+			var parent = this.deleteTarget.parent().dom;
+			parent.normalize();
+			if (!Ext.isIE && /^(td|th)$/i.test(parent.nodeName) && parent.childNodes.length == 1) {
+					// Do not leave a non-ie table cell empty
+				this.deleteTarget.insertSibling(this.editor.document.createElement('br'));
 			}
-		}
-		this.currentMenu.parentNode.removeChild(this.currentMenu);
-		this.currentMenu = null;
-		this.keys = [];
-		if (HTMLArea.is_ie) this.iePopup.hide();
-	},
-	
-	linkHandler : function (link, opcode) {
-		var editor = this.editor;
-		var self = this;
-		switch (opcode) {
-			case "MakeLink":
-			case "ModifyLink":
-				return (function() {
-					var obj = editor._toolbarObjects.CreateLink;
-					obj.cmd(editor, "CreateLink", link);
-				});
-			case "CheckLink":
-				return (function() {
-					window.open(link.href);
-				});
-			case "RemoveLink":
-				return (function() {
-					if (confirm(self.localize("Please confirm unlink") + "\n" +
-						self.localize("Link points to:") + " " + link.href)) {
-							var obj = editor._toolbarObjects.CreateLink;
-							obj.cmd(editor, "UnLink", link);
-					}
-				});
-		}
-	},
-	
-	deleteElementHandler : function (tmp,table) {
-		var editor = this.editor;
-		var self = this;
-		return (function() {
-			if(confirm(self.localize("Please confirm remove") + " " + tmp.tagName.toLowerCase())) {
-				var el = tmp;
-				var p = el.parentNode;
-				p.removeChild(el);
-				if(HTMLArea.is_gecko) {
-					if(p.tagName.toLowerCase() == "td" && !p.hasChildNodes()) p.appendChild(editor._doc.createElement("br"));
-					editor.forceRedraw();
-					editor.focusEditor();
-					editor.updateToolbar();
-					if(table) {
-						var save_collapse = table.style.borderCollapse;
-						table.style.borderCollapse = "collapse";
-						table.style.borderCollapse = "separate";
-						table.style.borderCollapse = save_collapse;
-					}
-				}
+				// Try to find a reasonable replacement selection
+			var nextSibling = this.deleteTarget.dom.nextSibling;
+			var previousSibling = this.deleteTarget.dom.previousSibling;
+			if (nextSibling) {
+				this.editor.selectNode(nextSibling, true);
+			} else if (previousSibling) {
+				this.editor.selectNode(previousSibling, false);
 			}
-		});
-	},
-	
-	documentClickHandler : function (ev) {
-		if (!ev) var ev = window.event;
-		if (!this.currentMenu) {
-			alert(this.localize("How did you get here? (Please report!)"));
-			return false;
-		}
-		var el = (ev.target) ? ev.target : ev.srcElement;
-		for (; el != null && el != this.currentMenu; el = el.parentNode);
-		if (el == null) {
-			this.closeMenu();
+			this.deleteTarget.remove();
 			this.editor.updateToolbar();
 		}
 	}
 });
-
-ContextMenu.tableOperationsHandler = function(editor,tbo,opcode) {
-	return (function() {
-		tbo.onButtonPress(editor,opcode);
-	});
-};
-
-ContextMenu.imageHandler = function(editor, currentTarget) {
-	return (function() {
-		var obj = editor._toolbarObjects.InsertImage;
-		obj.cmd(editor, obj.name, currentTarget);
-		if (HTMLArea.is_opera) {
-			editor._iframe.focus();
-		}
-		if (!editor.config.btnList[obj.name][7]) {
-			editor.updateToolbar();
-		}
-	});
-};
-
-ContextMenu.execCommandHandler = function(editor,opcode) {
-	return (function() {
-		editor.execCommand(opcode);
-	});
-};
-
-ContextMenu.blockElementsHandler = function(editor, currentTarget, buttonId) {
-	return (function() {
-		var blockElements = editor.plugins.BlockElements;
-		if (blockElements) {
-			blockElements = blockElements.instance;
-			blockElements.onButtonPress(editor, buttonId, currentTarget);
-		} else {
-			var el = currentTarget;
-			var par = el.parentNode;
-			var p = editor._doc.createElement("p");
-			var after = (buttonId === "InsertParagraphAfter");
-			p.appendChild(editor._doc.createElement("br"));
-			par.insertBefore(p, after ? el.nextSibling : el);
-			var sel = editor._getSelection();
-			var range = editor._createRange(sel);
-			editor.selectNodeContents(p, true);
-		}
-	});
-};
-
-ContextMenu.mouseOverHandler = function(editor,item) {
-	return (function() {
-		item.className += " hover";
-		if (editor.getPluginInstance("StatusBar")) {
-			editor.getPluginInstance("StatusBar").setText(item.__msh.tooltip || "&nbsp;");
-		}
-	});
-};
-
-ContextMenu.mouseOutHandler = function(item) {
-	return (function() {
-		item.className = item.className.replace(/hover/,"");
-	});
-};
-
-ContextMenu.itemContextMenuHandler = function(item) {
-	return (function(ev) {
-		item.__msh.activate();
-		if(!HTMLArea.is_ie) HTMLArea._stopEvent(ev);
-		return false;
-	});
-};
-
-ContextMenu.mouseDownHandler = function(item) {
-	return (function(ev) {
-		HTMLArea._stopEvent(ev);
-		return false;
-	});
-};
-
-ContextMenu.mouseUpHandler = function(item,instance) {
-	return (function(ev) {
-		var timeStamp = (new Date()).getTime();
-		if (timeStamp - instance.timeStamp > 500) {
-			item.__msh.activate();
-		}
-		if (!HTMLArea.is_ie) {
-			HTMLArea._stopEvent(ev);
-		}
-		return false;
-	});
-};
-
-ContextMenu.activateHandler = function(item,instance) {
-	return (function() {
-		item.__msh.action();
-		if (!item.__msh.dialog) {
-			instance.editor.updateToolbar();
-		}
-		instance.closeMenu();
-	});
-};
-
-ContextMenu.keyPressHandler = function(instance) {
-	return (function(ev) {
-		if (!ev) var ev = window.event;
-		if (ev.keyCode == 27) {
-			instance.closeMenu();
-			return false;
-		}
-		if(ev.altKey && !ev.ctrlKey) {
-			var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
-			var keys = instance.keys;
-			for (var i = keys.length; --i >= 0;) {
-				var k = keys[i];
-				if (k[0].toLowerCase() == key) k[1].__msh.activate();
-			}
-			HTMLArea._stopEvent(ev);
-			return false;
-		}
-	});
-};
-
-ContextMenu.getPos = function(el) {
-	var r = { x: el.offsetLeft, y: el.offsetTop };
-	if (el.offsetParent) {
-		var tmp = ContextMenu.getPos(el.offsetParent);
-		r.x += tmp.x;
-		r.y += tmp.y;
-	}
-	return r;
-};
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/ContextMenu/locallang.xml	(copie de travail)
@@ -44,7 +44,7 @@
 			<label index="Remove the">Remove the</label>
 			<label index="Element">Element</label>
 			<label index="Please confirm remove">Please confirm that you want to remove this element:</label>
-			<label index="Remove this node from the document">Remove this node from the document</label>
+			<label index="Remove this node from the document">Removes this node from the document</label>
 			<label index="How did you get here? (Please report!)">How did you get here? (Please report!)</label>
 			<label index="Show the image properties dialog">Show the image properties dialog</label>
 			<label index="Modify URL">Modify URL</label>
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/CopyPaste/copy-paste.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -49,7 +49,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.0",
+			version		: "2.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -70,14 +70,14 @@
 					tooltip		: this.localize(buttonId.toLowerCase()),
 					action		: "onButtonPress",
 					context		: button[0],
+					selection	: button[3],
 					hotKey		: (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null))
 				};
 				this.registerButton(buttonConfiguration);
 				if (!this.isButtonInToolbar(buttonId)) {
 					var hotKeyConfiguration = {
 						id	: buttonConfiguration.hotKey,
-						cmd	: buttonConfiguration.id,
-						action	: buttonConfiguration.action
+						cmd	: buttonConfiguration.id
 					};
 					this.registerHotKey(hotKeyConfiguration);
 				}
@@ -90,9 +90,9 @@
 	 * The list of buttons added by this plugin
 	 */
 	buttonList : {
-		Copy	: [null, "c", "copy"],
-		Cut	: [null, "x", "cut"],
-		Paste	: [null, "v", "paste"]
+		Copy	: [null, "c", "copy", true],
+		Cut	: [null, "x", "cut", true],
+		Paste	: [null, "v", "paste", false]
 	},
 	
 	/*
@@ -119,8 +119,7 @@
 						this.applyBrowserCommand(buttonId);
 					} else if (buttonId == "Cut") {
 							// If we are handling the cut hotkey
-						var removeEmpyLinkLaterFunctRef = this.makeFunctionReference("removeEmptyLinkLater");
-						window.setTimeout(removeEmpyLinkLaterFunctRef, 50);
+						this.removeEmptyLinkLater.defer(50, this);
 					}
 					break;
 				case "Paste":
@@ -129,11 +128,14 @@
 						this.applyBrowserCommand(buttonId);
 					}
 						// In FF3, the paste operation will indeed trigger the onPaste event not in FF2; nor in Opera
-					if (HTMLArea.is_opera || (HTMLArea.is_gecko && navigator.productSub < 20080514) || HTMLArea.is_safari) {
-						var cleanLaterFunctRef = this.getPluginInstance("DefaultClean") ? this.getPluginInstance("DefaultClean").cleanLaterFunctRef : (this.getPluginInstance("TYPO3HtmlParser") ? this.getPluginInstance("TYPO3HtmlParser").cleanLaterFunctRef : null);
-						if (cleanLaterFunctRef) {
-							window.setTimeout(cleanLaterFunctRef, 50);
+					if (Ext.isOpera || Ext.isGecko2 || Ext.isWebKit) {
+						var cleaner = this.getPluginInstance('DefaultClean');
+						if (!cleaner) {
+							cleaner = this.getPluginInstance('TYPO3HtmlParser');
 						}
+						if (cleaner) {
+							cleaner.clean.defer(50, cleaner);
+						}
 					}
 					break;
 				default:
@@ -150,7 +152,7 @@
 		try {
 			this.editor._doc.execCommand(buttonId, false, null);
 		} catch (e) {
-			if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+			if (Ext.isGecko) {
 				this.mozillaClipboardAccessException();
 			}
 		}
@@ -172,11 +174,11 @@
 		if (/^(a)$/i.test(parent.nodeName)) {
 			parent.normalize();
 			if (!parent.innerHTML || (parent.childNodes.length == 1 && /^(br)$/i.test(parent.firstChild.nodeName))) {
-				if (HTMLArea.is_gecko) {
+				if (!Ext.isIE) {
 					var container = parent.parentNode;
 					this.editor.removeMarkup(parent);
 						// Opera does not render empty list items
-					if (HTMLArea.is_opera && /^(li)$/i.test(container.nodeName) && !container.firstChild) {
+					if (Ext.isOpera && /^(li)$/i.test(container.nodeName) && !container.firstChild) {
 						container.innerHTML = "<br />";
 						this.editor.selectNodeContents(container, true);
 					}
@@ -185,7 +187,7 @@
 				}
 			}
 		}
-		if (HTMLArea.is_safari) {
+		if (Ext.isWebKit) {
 				// Remove Apple's span and font tags
 			this.editor.cleanAppleStyleSpans(this.editor._doc.body);
 				// Reset Safari selection in order to prevent insertion of span and/or font tags on next text input
@@ -215,7 +217,7 @@
 			case "Cut" :
 				HTMLArea.copiedCells = null;
 				var endBlocks = this.editor.getEndBlocks(selection);
-				if ((/^(tr)$/i.test(parent.nodeName) && HTMLArea.is_gecko) || (/^(td|th)$/i.test(endBlocks.start.nodeName) && /^(td|th)$/i.test(endBlocks.end.nodeName) && (HTMLArea.is_ie || HTMLArea.is_safari || HTMLArea.is_opera) && endBlocks.start != endBlocks.end)) {
+				if ((/^(tr)$/i.test(parent.nodeName) && !Ext.isIE) || (/^(td|th)$/i.test(endBlocks.start.nodeName) && /^(td|th)$/i.test(endBlocks.end.nodeName) && !Ext.isGecko && endBlocks.start != endBlocks.end)) {
 					HTMLArea.copiedCells = this.collectCells(buttonId, selection, endBlocks);
 					if (buttonId === "Cut") return true;
 				}
@@ -231,7 +233,7 @@
 	
 	pasteCells : function (selection, endBlocks) {
 		var cell = null;
-		if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+		if (Ext.isGecko) {
 			range = selection.getRangeAt(0);
 			cell = range.startContainer.childNodes[range.startOffset];
 			while (cell && !HTMLArea.isBlockElement(cell)) {
@@ -289,7 +291,7 @@
 		}
 		var row = null;
 		var cutRows = [];
-		if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {  // Firefox
+		if (Ext.isGecko) {
 			if (selection.rangeCount == 1) { // Collect the cells in the selected row
 				cells = [];
 				for (var i = 0, n = endBlocks.start.cells.length; i < n; ++i) {
@@ -389,19 +391,16 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		if (this.getEditorMode() === "wysiwyg" || this.editor.isEditable()) {
-			var buttonId = "Paste";
-			if (typeof(this.editor._toolbarObjects[buttonId]) !== "undefined") {
-				try {
-					this.editor._toolbarObjects[buttonId].state("enabled", this.editor._doc.queryCommandEnabled(buttonId));
-				} catch(e) {
-					this.editor._toolbarObjects[buttonId].state("enabled", false);
-				}
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'Paste') {
+			try {
+				button.setDisabled(!this.editor._doc.queryCommandEnabled(button.itemId));
+			} catch(e) {
+				button.setDisabled(true);
 			}
 		}
 	},
-
+	
 	/*
 	 * Mozilla clipboard access exception handler
 	 */
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultClean/default-clean.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -63,7 +63,8 @@
 			id		: buttonId,
 			tooltip		: this.localize(buttonId + "-Tooltip"),
 			action		: "onButtonPress",
-			hide		: true
+			hide		: true,
+			hideInContextMenu: true
 		};
 		this.registerButton(buttonConfiguration);
 	},
@@ -84,14 +85,16 @@
 		this.clean();
 		return false;
 	},
-	
-	onGenerate : function () {
-		var doc = this.editor._doc;
-			// Function reference used on paste with older versions of Mozilla/Firefox in which onPaste is not fired
-		this.cleanLaterFunctRef = this.makeFunctionReference("clean");
-		HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], DefaultClean.wordCleanHandler, true);
+	/*
+	 * This function gets called when the editor is generated
+	 */
+	onGenerate: function () {
+		var documentElement = Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement);
+		this.editor.iframe.mon(documentElement, 'paste', this.wordCleanHandler, this);
+		this.editor.iframe.mon(documentElement, 'dragdrop', this.wordCleanHandler, this);
+		this.editor.iframe.mon(documentElement, 'drop', this.wordCleanHandler, this);
 	},
-	
+
 	clean : function () {
 		function clearClass(node) {
 			var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig,' ');
@@ -167,34 +170,16 @@
 		if (HTMLArea.is_safari) {
 			this.editor.cleanAppleStyleSpans(this.editor._doc.body);
 		}
+	},
+	/*
+	 * Handler for paste, dragdrop and drop events
+	 */
+	wordCleanHandler: function (event) {
+			// If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window
+		if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) {
+			HTMLArea.Dialog.TYPO3Image.close();
+		} else {
+			this.clean.defer(250, this);
+		}
 	}
 });
-
-/*
- * Closure avoidance for IE
- */
-DefaultClean.cleanLater = function (editorNumber) {
-	var editor = RTEarea[editorNumber].editor;
-	editor.getPluginInstance("DefaultClean").clean();
-};
-
-/*
- * Handler for paste, dragdrop and drop events
- */
-DefaultClean.wordCleanHandler = function (ev) {
-	if (!ev) var ev = window.event;
-	var target = ev.target ? ev.target : ev.srcElement;
-	var owner = target.ownerDocument ? target.ownerDocument : target;
-	if (HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument
-		while (owner.parentElement) { owner = owner.parentElement; }
-	}
-	var editor = RTEarea[owner._editorNo].editor;
-
-		// If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window
-	if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) {
-		HTMLArea.Dialog.TYPO3Image.close();
-	} else {
-		window.setTimeout("DefaultClean.cleanLater(\'" + editor._editorNumber + "\');", 250);
-	}
-};
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefaultInline/default-inline.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2009 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -44,7 +44,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.0",
+			version		: "1.1",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.fructifor.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -57,11 +57,8 @@
 		/*
 		 * Registering the buttons
 		 */
-		var buttonList = DefaultInline.buttonList, buttonId;
-		var n = buttonList.length;
-		for (var i = 0; i < n; ++i) {
-			var button = buttonList[i];
-			buttonId = button[0];
+		Ext.each(this.buttonList, function (button) {
+			var buttonId = button[0];
 			var buttonConfiguration = {
 				id		: buttonId,
 				tooltip		: this.localize(buttonId + "-Tooltip"),
@@ -71,11 +68,19 @@
 				hotKey		: (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:null)
 			};
 			this.registerButton(buttonConfiguration);
-		}
-		
+			return true;
+		}, this);
 		return true;
-	 },
-	 
+	},
+	/* The list of buttons added by this plugin */
+	buttonList: [
+		["Bold", null],
+		["Italic", null],
+		["StrikeThrough", null],
+		["Subscript", null],
+		["Superscript", null],
+		["Underline", null]
+	],
 	/*
 	 * This function gets called when some inline element button was pressed.
 	 */
@@ -96,34 +101,16 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		var editor = this.editor;
-		var buttonList = DefaultInline.buttonList;
-		var buttonId, n = buttonList.length, commandState;
-		if (editor.getMode() === "wysiwyg" && editor.isEditable()) {
-			for (var i = 0; i < n; ++i) {
-				buttonId = buttonList[i][0];
-				if (this.isButtonInToolbar(buttonId)) {
-					commandState = false;
-					try {
-						commandState = editor._doc.queryCommandState(buttonId);
-					} catch(e) {
-						commandState = false;
-					}
-					editor._toolbarObjects[buttonId].state("active", commandState);
-				}
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			var commandState = false;
+			try {
+				commandState = this.editor._doc.queryCommandState(button.itemId);
+			} catch(e) {
+				commandState = false;
 			}
+			button.setInactive(!commandState);
 		}
 	}
 });
 
-/* The list of buttons added by this plugin */
-DefaultInline.buttonList = [
-	["Bold", null],
-	["Italic", null],
-	["StrikeThrough", null],
-	["Subscript", null],
-	["Superscript", null],
-	["Underline", null]
-];
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/DefinitionList/definition-list.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -71,34 +71,36 @@
 		/*
 		 * Registering the buttons
 		 */
-		for (var buttonId in this.buttonList) {
-			if (this.buttonList.hasOwnProperty(buttonId)) {
-				var button = this.buttonList[buttonId];
-				var buttonConfiguration = {
-					id		: buttonId,
-					tooltip		: this.localize(buttonId + "-Tooltip"),
-					action		: "onButtonPress",
-					context		: button[0],
-					hotKey		: (this.buttonsConfiguration[button[2]] ? this.buttonsConfiguration[button[2]].hotKey : (button[1] ? button[1] : null))
-				};
-				this.registerButton(buttonConfiguration);
-			}
-		}
-		
+		Ext.each(this.buttonList, function (button) {
+			var buttonId = button[0];
+			var buttonConfiguration = {
+				id		: buttonId,
+				tooltip		: this.localize(buttonId + "-Tooltip"),
+				action		: "onButtonPress",
+				context		: button[1],
+				hotKey		: (this.buttonsConfiguration[button[3]] ? this.buttonsConfiguration[button[3]].hotKey : (button[2] ? button[2] : null)),
+				noAutoUpdate	: button[4]
+			};
+			this.registerButton(buttonConfiguration);
+		}, this);
 		return true;
 	 },
 	 
 	/*
 	 * The list of buttons added by this plugin
 	 */
-	buttonList : {
-		Indent			: [null, "TAB", "indent"],
-		Outdent			: [null, "SHIFT-TAB", "outdent"],
-		DefinitionList		: [null, null, "definitionlist"],
-		DefinitionItem		: ["dd,dt", null, "definitionitem"]
-	},
-	
+	buttonList : [
+		['Indent', null, 'TAB', 'indent', false],
+		['Outdent', null, 'SHIFT-TAB', 'outdent', false],
+		['DefinitionList', null, null, 'definitionlist', true],
+		['DefinitionItem', 'dd,dt', null, 'definitionitem', false]
+	 ],
 	/*
+	 * This function gets called when the plugin is generated
+	 * Avoid re-execution of the base function
+	 */
+	onGenerate: Ext.emptyFn,
+	/*
 	 * This function gets called when a button was pressed.
 	 *
 	 * @param	object		editor: the editor instance
@@ -115,7 +117,7 @@
 		this.editor.focusEditor();
 		var selection = editor._getSelection();
 		var range = editor._createRange(selection);
-		var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(selection, range);
 		if (target) {
 			parentElement = target;
@@ -311,36 +313,27 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		if (this.getEditorMode() === "textmode" || !this.editor.isEditable()) {
-			return false;
-		}
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
-		var parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement();
-		if (parentElement.nodeName.toLowerCase() === "body") return false;
-		while (parentElement && (!HTMLArea.isBlockElement(parentElement) || /^(li)$/i.test(parentElement.nodeName))) {
-			parentElement = parentElement.parentNode;
-		}
-		var blockAncestors = this.getBlockAncestors(parentElement);
-		var selection = this.editor._getSelection();
-		var endBlocks = this.editor.getEndBlocks(selection);
-		for (var buttonId in this.buttonList) {
-			commandState = false;
-			if (this.buttonList.hasOwnProperty(buttonId) && this.isButtonInToolbar(buttonId)) {
-				switch (buttonId) {
-					case "Outdent" :
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		var editor = this.editor;
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
+			var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement();
+			if (!/^(body)$/i.test(parentElement.nodeName)) {
+				var endBlocks = editor.getEndBlocks(editor._getSelection());
+				switch (button.itemId) {
+					case 'Outdent':
 						if (/^(dt)$/i.test(endBlocks.start.nodeName)
 								&& /^(dl)$/i.test(endBlocks.start.parentNode.nodeName)
 								&& /^(dd)$/i.test(endBlocks.start.parentNode.parentNode.nodeName)
 								&& !endBlocks.end.nextSibling) {
-							this.editor._toolbarObjects[buttonId].state("enabled", true);
+							button.setDisabled(false);
 						} else {
-							this.base();
+							this.base(button, mode, selectionEmpty, ancestors);
 						}
 						break;
-					case "DefinitionList" :
-						this.editor._toolbarObjects[buttonId].state("enabled", (this.editor._selectionEmpty() && /^(p|div|address|pre|blockquote|h[1-6]|li|td|dd)$/i.test(endBlocks.start.nodeName))
-													|| (endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName)));
+					case 'DefinitionList':
+						button.setDisabled(!(selectionEmpty && /^(p|div|address|pre|blockquote|h[1-6]|li|td|dd)$/i.test(endBlocks.start.nodeName))
+													&& !(endBlocks.start != endBlocks.end && /^(p|h[1-6])$/i.test(endBlocks.start.nodeName)));
 						break;
 				}
 			}
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/EditorMode/editor-mode.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2009-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -30,21 +30,18 @@
  * TYPO3 SVN ID: $Id$
  */
 EditorMode = HTMLArea.Plugin.extend({
-
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-
 	/*
 	 * This function gets called by the class constructor
 	 */
 	configurePlugin : function (editor) {
-
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "0.1",
+			version		: "2.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -53,7 +50,6 @@
 			license		: "GPL"
 		};
 		this.registerPluginInformation(pluginInformation);
-
 		/*
 		 * Registering the buttons
 		 */
@@ -71,64 +67,13 @@
 			this.registerButton(buttonConfiguration);
 		}
 		return true;
-	 },
-
-	/* The list of buttons added by this plugin */
-	buttonList : [
-		["TextMode", null]
-	],
-
-	/*
-	 * This function gets called during the editor generation and initializes the editor mode
-	 *
-	 * @return	void
-	 */
-	init : function () {
-		var doc = this.editor._doc;
-			// Catch error if html content is invalid
-		var documentIsWellFormed = true;
-		try {
-			doc.body.innerHTML = this.editor._textArea.value;
-		} catch(e) {
-			this.appendToLog("init", "The HTML document is not well-formed.");
-			alert(this.localize("HTML-document-not-well-formed"));
-			documentIsWellFormed = false;
-		}
-			// Set contents editable
-		if (documentIsWellFormed) {
-			if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera && !this.editor._initEditMode()) {
-				return false;
-			}
-			if (HTMLArea.is_ie || HTMLArea.is_safari) {
-				doc.body.contentEditable = true;
-			}
-			if (HTMLArea.is_opera || HTMLArea.is_safari) {
-				doc.designMode = "on";
-				this.setGeckoOptions();
-			}
-			this.editorMode = "wysiwyg";
-			if (doc.body.contentEditable || doc.designMode == "on") {
-				this.appendToLog("init", "Design mode successfully set.");
-			}
-		} else {
-			this.editorMode = "textmode";
-			this.setEditorMode("docnotwellformedmode");
-			this.appendToLog("init", "Design mode could not be set.");
-		}
-		return true;
 	},
-
-	/*
-	 * This function gets called when the editor is generated
-	 *
-	 * @return 	void
+	/**
+	 * The list of buttons added by this plugin
 	 */
-	onGenerate : function () {
-			// Set some references
-		this.textArea = this.editor._textArea;
-		this.editorBody = this.editor._doc.body;
-	},
-
+	buttonList: [
+		['TextMode', null]
+	],
 	/*
 	 * This function gets called when a button was pressed.
 	 *
@@ -137,173 +82,19 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function (editor, id, target) {
+	onButtonPress: function (editor, id, target) {
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
-		this.setEditorMode((this.getEditorMode() == buttonId.toLowerCase()) ? "wysiwyg" : buttonId.toLowerCase());
+		this.editor.setMode((this.editor.getMode() == buttonId.toLowerCase()) ? 'wysiwyg' : buttonId.toLowerCase());
 		return false;
 	},
-
 	/*
-	 * Switch editor mode
-	 *
-	 * @param	string	"textmode" or "wysiwyg"; if no parameter was passed, toggle between modes.
-	 * @return	void
-	 */
-	setEditorMode : function (mode) {
-		var editor = this.editor;
-		switch (mode) {
-			case "textmode":
-			case "docnotwellformedmode":
-				this.textArea.value = this.getHTML();
-				editor._iframe.style.display = "none";
-				var dimensions = editor.getDimensions();
-				editor.htmlArea.setStyle('height', (dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
-				editor.htmlArea.removeClass('resizable');
-				this.textArea.style.display = "block";
-				this.editorMode = "textmode";
-				break;
-			case "wysiwyg":
-				if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-					editor._doc.designMode = "off";
-				}
-				try {
-					this.editorBody.innerHTML = this.getHTML();
-				} catch(e) {
-					alert(HTMLArea.I18N.msg["HTML-document-not-well-formed"]);
-					break;
-				}
-				this.textArea.style.display = "none";
-				editor._iframe.style.display = "block";
-				var dimensions = editor.getDimensions();
-				editor.htmlArea.setStyle('height', (parseInt(editor.iframe.getStyle('height')) + dimensions.toolbar.height + dimensions.statusbar.height) + 'px');
-				editor.htmlArea.addClass('resizable');
-				if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
-					editor._doc.designMode = "on";
-				}
-				this.editorMode = "wysiwyg";
-				this.setGeckoOptions();
-				break;
-			case "htmlmode":
-				this.editorMode = "htmlmode";
-				break;
-			default:
-				return false;
-		}
-		if (mode !== "docnotwellformedmode") {
-			editor.focusEditor();
-		}
-		for (var pluginId in editor.plugins) {
-			if (editor.plugins.hasOwnProperty(pluginId)) {
-				var pluginInstance = this.getPluginInstance(pluginId);
-				if (typeof(pluginInstance.onMode) === "function") {
-					pluginInstance.onMode(mode);
-				}
-			}
-		}
-	},
-
-	/*
-	 * Set gecko editing mode options (if we can... raises exception in Firefox 3)
-	 *
-	 * @return	void
-	 */
-	setGeckoOptions : function () {
-		if (HTMLArea.is_gecko) {
-			var doc = this.editor._doc;
-			var config = this.editor.config;
-			try {
-				if (doc.queryCommandEnabled("insertbronreturn")) {
-					doc.execCommand("insertbronreturn", false, config.disableEnterParagraphs);
-				}
-				if (doc.queryCommandEnabled("styleWithCSS")) {
-					doc.execCommand("styleWithCSS", false, config.useCSS);
-				} else if (!HTMLArea.is_opera && !HTMLArea.is_safari && doc.queryCommandEnabled("useCSS")) {
-					doc.execCommand("useCSS", false, !config.useCSS);
-				}
-				if (!HTMLArea.is_opera && !HTMLArea.is_safari) {
-					if (doc.queryCommandEnabled("enableObjectResizing")) {
-						doc.execCommand("enableObjectResizing", false, !config.disableObjectResizing);
-					}
-					if (doc.queryCommandEnabled("enableInlineTableEditing")) {
-						doc.execCommand("enableInlineTableEditing", false, (config.buttons.table && config.buttons.table.enableHandles) ? true : false);
-					}
-				}
-			} catch(e) {}
-		}
-	},
-
-	/*
-	 * Get editor mode
-	 *
-	 * @return	string	the current editor mode
-	 */
-	getEditorMode : function() {
-		return this.editorMode;
-	},
-
-	/*
 	 * This function gets called when the toolbar is updated
 	 *
 	 * @return	void
 	 */
-	onUpdateToolbar : function () {
-		var buttonList = this.buttonList, buttonId;
-		for (var i = 0, n = buttonList.length; i < n; ++i) {
-			buttonId = buttonList[i][0];
-			if (this.isButtonInToolbar(buttonId)) {
-				this.editor._toolbarObjects[buttonId].state("active", (this.getEditorMode() == buttonId.toLowerCase()));
-			}
-		}
-	},
-
-	/*
-	 * Retrieve the HTML
-	 * In the case of the wysiwyg mode, the html content is parsed
-	 *
-	 * @return	string	the textual html content from the current editing mode
-	 */
-	getHTML : function () {
-		switch (this.editorMode) {
-			case "wysiwyg":
-				return HTMLArea.getHTML(this.editorBody, false, this.editor);
-			case "textmode":
-				return this.textArea.value;
-		}
-		return "";
-	},
-
-	/*
-	 * Retrieve raw HTML
-	 *
-	 * @return	string	the textual html content from the current editing mode
-	 */
-	getInnerHTML : function () {
-		switch (this.editorMode) {
-			case "wysiwyg":
-				return this.editorBody.innerHTML;
-			case "textmode":
-				return this.textArea.value;
-		}
-		return "";
-	},
-
-	/*
-	 * Replace the HTML inside
-	 *
-	 * @param	string	html: the textual html
-	 * @return	boolean	false
-	 */
-	setHTML : function (html) {
-		switch (this.editorMode) {
-			case "wysiwyg":
-				this.editorBody.innerHTML = html;
-				break;
-			case "textmode":
-				this.textArea.value = html;
-				break;
-		}
-		return false;
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		button.setInactive(mode !== button.itemId.toLowerCase());
 	}
 });
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/FindReplace/find-replace.js	(copie de travail)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  (c) 2004 Cau guanabara <caugb@ibest.com.br>
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -96,10 +96,9 @@
 		if (/\w/.test(sel)) {
 			param = { fr_pattern: sel };
 		}
-		if (HTMLArea.is_opera) {
-			this.cleanUpFunctionReference = this.makeFunctionReference("cleanUp");
+		if (Ext.isOpera) {
 			this.cleanUpRegularExpression = /(<span\s+[^>]*id=.?frmark[^>]*>)([^<>]*)(<\/span>)/gi;
-			this.editor._iframe.contentWindow.setTimeout(this.cleanUpFunctionReference, 200);
+			this.cleanUp.defer(200, this);
 		}
 		this.dialog = this.openDialog("FindReplace", this.makeUrlFromPopupName("find_replace"), null, param, {width:this.popupWidth, height:this.popupHeight});
 		return false;
@@ -112,10 +111,10 @@
 	 */
 	cleanUp : function () {
 		if (this.dialog && (!this.dialog.dialogWindow || (this.dialog.dialogWindow && this.dialog.dialogWindow.closed))) {
-			this.getPluginInstance("EditorMode").setHTML(this.getPluginInstance("EditorMode").getInnerHTML().replace(this.cleanUpRegularExpression,"$2"));
+			this.editor.setHTML(this.editor.getInnerHTML().replace(this.cleanUpRegularExpression,"$2"));
 			this.dialog.close();
 		} else {
-			this.editor._iframe.contentWindow.setTimeout(this.cleanUpFunctionReference, 200);
+			this.cleanUp.defer(200, this);
 		}
 	}
 });
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -63,7 +63,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.1",
+			version		: "2.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -80,9 +80,8 @@
 		var dropDownConfiguration = {
 			id		: buttonId,
 			tooltip		: this.localize(buttonId + "-Tooltip"),
-			options		: (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()]["dropDownOptions"]:null),
-			action		: "onChange",
-			refresh		: null
+			options		: (this.editorConfiguration.buttons[buttonId.toLowerCase()] ? this.editorConfiguration.buttons[buttonId.toLowerCase()].data : null),
+			action		: "onChange"
 		};
 		this.registerDropDown(dropDownConfiguration);
 		
@@ -193,7 +192,6 @@
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
-		var obj = editor._toolbarObjects[buttonId];
 		var element = this.convertBtn[buttonId];
 		if (element) {
 			this.applyInlineElement(editor, element);
@@ -206,9 +204,8 @@
 	/*
 	 * This function gets called when some inline element was selected in the drop-down list
 	 */
-	onChange : function (editor, buttonId) {
-		var tbobj = editor._toolbarObjects[buttonId];
-		var element = document.getElementById(tbobj.elementId).value;
+	onChange : function (editor, combo, record, index) {
+		var element = combo.getValue();
 		this.applyInlineElement(editor, element, false);
 	},
 	
@@ -235,7 +232,7 @@
 			}
 		}
 		if (!selectionEmpty) {
-			var statusBarSelection = (editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null);
+			var statusBarSelection = (editor.statusBar ? editor.statusBar.getSelection() : null);
 				// The selection is not empty.
 			for (var i = 0; i < ancestors.length; ++i) {
 				fullNodeSelected = (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text)))
@@ -374,22 +371,19 @@
 	/*
 	* This function gets called when the toolbar is updated
 	*/
-	onUpdateToolbar : function () {
+	onUpdateToolbar : function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) {
 		var editor = this.editor;
-		if (this.getEditorMode() === "wysiwyg" && editor.isEditable()) {
-			var id, activeButton;
-			var tagName = false, endPointsInSameBlock = true, fullNodeSelected = false;
+		if (mode === "wysiwyg" && editor.isEditable()) {
+			var tagName = false, fullNodeSelected = false;
 			var sel = editor._getSelection();
 			var range = editor._createRange(sel);
 			var parent = editor.getParentElement(sel);
 			if (parent && !HTMLArea.isBlockElement(parent)) {
 				tagName = parent.nodeName.toLowerCase();
 			}
-			var selectionEmpty = editor._selectionEmpty(sel);
 			if (!selectionEmpty) {
-				var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
-				var ancestors = editor.getAllAncestors();
-				for (var i = 0; i < ancestors.length; ++i) {
+				var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null;
+				for (var i = 0, n = ancestors.length; i < n; ++i) {
 					fullNodeSelected = (statusBarSelection === ancestors[i])
 						&& ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((sel.type !== "Control" && ancestors[i].innerText === range.text) || (sel.type === "Control" && ancestors[i].innerText === range.item(0).text))));
 					if (fullNodeSelected) {
@@ -406,31 +400,24 @@
 				}
 			}
 			var selectionInInlineElement = tagName && this.REInlineElements.test(tagName);
-			var disabled = !editor.endPointsInSameBlock() || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
-			
-			var obj = editor.config.customSelects["FormatText"];
-			if ((typeof(obj) !== "undefined") && (typeof(editor._toolbarObjects[obj.id]) !== "undefined")) {
-				this.updateValue(editor, obj, tagName, selectionEmpty, fullNodeSelected, disabled);
-			}
-			
-			var ancestors = editor.getAllAncestors();
-			var bl = this.buttonList;
-			for (var i = 0; i < bl.length; ++i) {
-				var btn = bl[i];
-				id = btn[0];
-				var obj = editor._toolbarObjects[id];
-				if ((typeof(obj) !== "undefined")) {
-					activeButton = false;
-					for (var j = ancestors.length; --j >= 0;) {
-						var el = ancestors[j];
-						if (!el) { continue; }
-						if (this.convertBtn[id] === el.nodeName.toLowerCase()) {
+			var disabled = !endPointsInSameBlock || (fullNodeSelected && !tagName) || (selectionEmpty && !selectionInInlineElement);
+			switch (button.itemId) {
+				case 'FormatText':
+					this.updateValue(editor, button, tagName, selectionEmpty, fullNodeSelected, disabled);
+					break;
+				default:
+					var activeButton = false;
+					Ext.each(ancestors, function (ancestor) {
+						if (ancestor && this.convertBtn[button.itemId] === ancestor.nodeName.toLowerCase()) {
 							activeButton = true;
+							return false;
+						} else {
+							return true;
 						}
-					}
-					obj.state("active", activeButton);
-					obj.state("enabled", !disabled);
-				}
+					}, this);
+					button.setInactive(!activeButton);
+					button.setDisabled(disabled);
+					break;
 			}
 		}
 	},
@@ -438,31 +425,23 @@
 	/*
 	* This function updates the drop-down list of inline elemenents
 	*/
-	updateValue : function (editor, obj, tagName, selectionEmpty, fullNodeSelected, disabled) {
-		var select = document.getElementById(editor._toolbarObjects[obj.id]["elementId"]);
-		var options = select.options;
-		for (var i = options.length; --i >= 0;) {
-			options[i].selected = false;
+	updateValue: function (editor, select, tagName, selectionEmpty, fullNodeSelected, disabled) {
+		var store = select.getStore();
+		store.removeAt(0);
+		if ((store.findExact('value', tagName) != -1) && (selectionEmpty || fullNodeSelected)) {
+			select.setValue(tagName);
+			store.insert(0, new store.recordType({
+				text: this.localize('Remove markup'),
+				value: 'none'
+			}));
+		} else {
+			store.insert(0, new store.recordType({
+				text: this.localize('No markup'),
+				value: 'none'
+			}));
+			select.setValue('none');
 		}
-		select.selectedIndex = 0;
-		options[0].selected = true;
-		select.options[0].text = this.localize("No markup");
-		for (i = options.length; --i >= 0;) {
-			if (tagName === options[i].value) {
-				if (selectionEmpty || fullNodeSelected) {
-					options[i].selected = true;
-					select.selectedIndex = i;
-					select.options[0].text = this.localize("Remove markup");
-				}
-				break;
-			}
-		}
-		
-		select.disabled = !(options.length>1) || disabled;
-		select.className = "";
-		if (select.disabled) {
-			select.className = "buttonDisabled";
-		}
+		select.setDisabled(!(store.getCount()>1) || disabled);
 	}
 });
 
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InsertSmiley/insert-smiley.js	(copie de travail)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  (c) 2004 Ki Master George <kimastergeorge@gmail.com>
-*  (c) 2005-2009 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -34,32 +34,31 @@
  */
 
 InsertSmiley = HTMLArea.Plugin.extend({
-
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-
 	/*
 	 * This function gets called by the class constructor
 	 */
 	configurePlugin : function(editor) {
-
 		this.pageTSConfiguration = this.editorConfiguration.buttons.emoticon;
-
+		this.editor_url = _typo3_host_url + _editor_url;
+		if (this.editor_url == '../') {
+			this.editor_url = document.URL.replace(/^(.*\/).*\/.*$/g, "$1");
+		}
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.2",
+			version		: "2.0",
 			developer	: "Ki Master George & Stanislas Rolland",
-			developerUrl	: "http://www.fructifor.ca/",
+			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Ki Master George & Stanislas Rolland",
-			sponsor		: "Ki Master George & Fructifor Inc.",
-			sponsorUrl	: "http://www.fructifor.ca/",
+			sponsor		: "Ki Master George & SJBR",
+			sponsorUrl	: "http://www.sjbr.ca/",
 			license		: "GPL"
 		};
 		this.registerPluginInformation(pluginInformation);
-
 		/*
 		 * Registering the button
 		 */
@@ -72,10 +71,8 @@
 			dialog		: true
 		};
 		this.registerButton(buttonConfiguration);
-
 		return true;
 	},
-
 	/*
 	 * This function gets called when the button was pressed.
 	 *
@@ -84,31 +81,77 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function (editor, id) {
-
-		var sel = this.editor.getSelectedHTML().replace(/(<[^>]*>|&nbsp;|\n|\r)/g,"");
-		var param = new Object();
-		param.editor_url = _typo3_host_url + _editor_url;
-		if (param.editor_url == "../") {
-			param.editor_url = document.URL;
-			param.editor_url = param.editor_url.replace(/^(.*\/).*\/.*$/g, "$1");
+	onButtonPress: function (editor, id) {
+			// Could be a button or its hotkey
+		var buttonId = this.translateHotKey(id);
+		buttonId = buttonId ? buttonId : id;
+		var dimensions = this.getWindowDimensions({width:175, height:230}, buttonId);
+		this.dialog = new Ext.Window({
+			title: this.localize('Insert Smiley'),
+			cls: 'htmlarea-window',
+			border: false,
+			width: dimensions.width,
+			height: 'auto',
+			iconCls: buttonId,
+			listeners: {
+				close: {
+					fn: this.onClose,
+					scope: this
+				}
+			},
+			items: {
+				xtype: 'box',
+				cls: 'emoticon-array',
+				tpl: new Ext.XTemplate(
+					'<tpl for="."><a href="#" class="emoticon" hidefocus="on"><img alt="" title="" src="{.}" /></a></tpl>'
+				),
+				listeners: {
+					render: {
+						fn: this.render,
+						scope: this
+					}
+				}
+			},
+			buttons: [this.buildButtonConfig('Cancel', this.onCancel)]
+		});
+		this.show();
+	},
+	/*
+	 * Render the array of emoticon
+	 *
+	 * @param	object		component: the box containing the emoticons
+	 *
+	 * @return	void
+	 */
+	render: function (component) {
+		this.icons = [];
+		var numberOfIcons = 20, inum;
+		for (var i = 1; i <= numberOfIcons; i++) {
+			inum = i;
+			if (i < 10) {
+				inum = '000' + i;
+			} else if (i < 100) {
+				inum = '00' + i;
+			} else if (i < 1000) {
+				inum = '0' + i;
+			}
+			this.icons.push(this.editor_url + 'plugins/InsertSmiley/smileys/' + inum + '.gif');
 		}
-		this.dialog = this.openDialog("InsertSmiley", this.makeUrlFromPopupName("insertsmiley"), "insertImageTag", param, {width:250, height:230});
+		component.tpl.overwrite(component.el, this.icons);
+		component.mon(component.el, 'click', this.insertImageTag, this, {delegate: 'a'});
 	},
-
 	/*
-	 * Insert the selected smiley
+	 * Insert the selected emoticon
 	 *
-	 * @param	object		param: the selected smiley
+	 * @param	object		event: the Ext event
+	 * @param	HTMLelement	target: the html element target
 	 *
-	 * @return	boolean		false
+	 * @return	void
 	 */
-	insertImageTag : function (param) {
-		if (param && typeof(param.imgURL) != "undefined") {
-			this.editor.focusEditor();
-			this.editor.insertHTML('<img src="' + param.imgURL + '" alt="Smiley" />');
-		}
-		return false;
+	insertImageTag: function (event, target) {
+		this.editor.focus();
+		this.restoreSelection();
+		this.editor.insertHTML('<img src="' + Ext.get(target).first().getAttribute('src') + '" alt="" />');
+		this.close();
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -52,14 +52,14 @@
 		}
 
 			// Importing list of allowed attributes
-		if (this.editor.getPluginInstance("TextStyle")) {
-			this.allowedAttributes = this.editor.getPluginInstance("TextStyle").allowedAttributes;
+		if (this.getPluginInstance("TextStyle")) {
+			this.allowedAttributes = this.getPluginInstance("TextStyle").allowedAttributes;
 		}			
-		if (!this.allowedAttributes && this.editor.getPluginInstance("InlineElements")) {
-			this.allowedAttributes = this.editor.getPluginInstance("InlineElements").allowedAttributes;
+		if (!this.allowedAttributes && this.getPluginInstance("InlineElements")) {
+			this.allowedAttributes = this.getPluginInstance("InlineElements").allowedAttributes;
 		}
-		if (!this.allowedAttributes && this.editor.getPluginInstance("BlockElements")) {
-			this.allowedAttributes = this.editor.getPluginInstance("BlockElements").allowedAttributes;
+		if (!this.allowedAttributes && this.getPluginInstance("BlockElements")) {
+			this.allowedAttributes = this.getPluginInstance("BlockElements").allowedAttributes;
 		}
 		if (!this.allowedAttributes) {
 			this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class");
@@ -72,7 +72,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "0.1",
+			version		: "1.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -101,21 +101,20 @@
 		/*
 		 * Registering the dropdown list
 		 */
-		if (this.buttonsConfiguration.language && this.buttonsConfiguration.language.languagesUrl) {
-				// Load the options into HTMLArea.languageOptions
-			var languagesData = this.getJavascriptFile(this.buttonsConfiguration.language.languagesUrl, "noEval");
-			if (languagesData) {
-				eval(languagesData);
+		var buttonId = 'Language';
+		if (this.buttonsConfiguration[buttonId.toLowerCase()] && this.buttonsConfiguration[buttonId.toLowerCase()].dataUrl) {
+				// Load the options var
+			var optionsData = this.getJavascriptFile(this.buttonsConfiguration[buttonId.toLowerCase()].dataUrl, "noEval");
+			if (optionsData) {
+				eval(optionsData);
 			}
 		}
-		var buttonId = "Language";
 		var dropDownConfiguration = {
 			id		: buttonId,
 			tooltip		: this.localize(buttonId + "-Tooltip"),
-			options		: (HTMLArea.languageOptions ? HTMLArea.languageOptions : null),
+			options		: options,
 			action		: "onChange",
-			refresh		: null,
-			context		: null
+			listWidth	: 200
 		};
 		this.registerDropDown(dropDownConfiguration);
 
@@ -136,16 +135,13 @@
 			// Add rules to the stylesheet for language mark highlighting
 			// Model: body.htmlarea-show-language-marks *[lang=en]:before { content: "en: "; }
 			// Works in IE8, but not in earlier versions of IE
-		var obj = this.getDropDownConfiguration("Language");
-		if ((typeof(obj) !== "undefined") && (typeof(this.editor._toolbarObjects[obj.id]) !== "undefined")) {
+		var select = this.getButton('Language');
+		if (select) {
 			var styleSheet = this.editor._doc.styleSheets[0];
-			var select = document.getElementById(this.editor._toolbarObjects[obj.id].elementId);
-			var options = select.options;
-			var rule, selector, style;
-			for (var i = options.length; --i >= 0;) {
-				selector = 'body.htmlarea-show-language-marks *[' + 'lang="' + options[i].value + '"]:before';
-				style = 'content: "' + options[i].value + ': ";';
-				rule = selector + ' { ' + style + ' }';
+			select.getStore().each(function (option) {
+				var selector = 'body.htmlarea-show-language-marks *[' + 'lang="' + option.get('value') + '"]:before';
+				var style = 'content: "' + option.get('value') + ': ";';
+				var rule = selector + ' { ' + style + ' }';
 				if (HTMLArea.is_gecko) {
 					try {
 						styleSheet.insertRule(rule, styleSheet.cssRules.length);
@@ -155,7 +151,8 @@
 				} else {
 					styleSheet.addRule(selector, style);
 				}
-			}
+				return true;
+			});
 		}
 	},
 
@@ -225,10 +222,8 @@
 	/*
 	 * This function gets called when some language was selected in the drop-down list
 	 */
-	onChange : function (editor, buttonId) {
-		var tbobj = this.editor._toolbarObjects[buttonId];
-		var language = document.getElementById(tbobj.elementId).value;
-		this.applyLanguageMark(language);
+	onChange : function (editor, combo, record, index) {
+		this.applyLanguageMark(combo.getValue());
 	},
 
 	/*
@@ -236,7 +231,7 @@
 	 */
 	applyLanguageMark : function (language) {
 		var selection = this.editor._getSelection();
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		var range = this.editor._createRange(selection);
 		var parent = this.editor.getParentElement(selection, range);
 		var selectionEmpty = this.editor._selectionEmpty(selection);
@@ -391,94 +386,74 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) {
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
 			var selection = this.editor._getSelection();
-			var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 			var range = this.editor._createRange(selection);
 			var parent = this.editor.getParentElement(selection);
-				// Updating the direction buttons
-			var buttonList = this.buttonList, buttonId;
-			for (var i = 0, n = buttonList.length; i < n; ++i) {
-				buttonId = buttonList[i][0];
-				if (this.isButtonInToolbar(buttonId)) {
-					switch (buttonId) {
-						case "RightToLeft" :
-						case "LeftToRight" :
-							if (parent) {
-								var direction = (buttonId === "RightToLeft") ? "rtl" : "ltr";
-								this.editor._toolbarObjects[buttonId].state("active",(parent.dir == direction || parent.style.direction == direction));
-							}
-							break;
-						case "ShowLanguageMarks":
-							this.editor._toolbarObjects[buttonId].state("active", HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-show-language-marks'));
-							break;
-						default	:
-							break;
+			switch (button.itemId) {
+				case 'RightToLeft':
+				case 'LeftToRight':
+					if (parent) {
+						var direction = (button.itemId === 'RightToLeft') ? 'rtl' : 'ltr';
+						button.setInactive(parent.dir != direction && parent.style.direction != direction);
 					}
-				}
-			}
-				// Updating the language drop-down
-			var fullNodeSelected = false;
-			var language = this.getLanguageAttribute(parent);
-			var selectionEmpty = this.editor._selectionEmpty(selection);
-			var endPointsInSameBlock = this.editor.endPointsInSameBlock();
-			if (!selectionEmpty) {
-				if (endPointsInSameBlock) {
-					var ancestors = this.editor.getAllAncestors();
-					for (var i = 0; i < ancestors.length; ++i) {
-						fullNodeSelected = (statusBarSelection === ancestors[i])
-							&& ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text))));
-						if (fullNodeSelected) {
-							parent = ancestors[i];
-							break;
+					break;
+				case 'ShowLanguageMarks':
+					button.setInactive(!HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-show-language-marks'));
+					break;
+				case 'Language':
+						// Updating the language drop-down
+					var fullNodeSelected = false;
+					var language = this.getLanguageAttribute(parent);
+					if (!selectionEmpty) {
+						if (endPointsInSameBlock) {
+							for (var i = 0; i < ancestors.length; ++i) {
+								fullNodeSelected = (statusBarSelection === ancestors[i])
+									&& ((HTMLArea.is_gecko && ancestors[i].textContent === range.toString()) || (HTMLArea.is_ie && ((selection.type !== "Control" && ancestors[i].innerText === range.text) || (selection.type === "Control" && ancestors[i].innerText === range.item(0).text))));
+								if (fullNodeSelected) {
+									parent = ancestors[i];
+									break;
+								}
+							}
+								// Working around bug in Safari selectNodeContents
+							if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && statusBarSelection.textContent === range.toString()) {
+								fullNodeSelected = true;
+								parent = statusBarSelection;
+							}
+							language = this.getLanguageAttribute(parent);
+						} else {
+							language = this.getLanguageAttributeFromBlockElements();
 						}
 					}
-						// Working around bug in Safari selectNodeContents
-					if (!fullNodeSelected && HTMLArea.is_safari && statusBarSelection && statusBarSelection.textContent === range.toString()) {
-						fullNodeSelected = true;
-						parent = statusBarSelection;
-					}
-					language = this.getLanguageAttribute(parent);
-				} else {
-					language = this.getLanguageAttributeFromBlockElements();
-				}
+					this.updateValue(button, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock);
+					break;
+				default:
+					break;
 			}
-			var obj = this.getDropDownConfiguration("Language");
-			if ((typeof(obj) !== "undefined") && (typeof(this.editor._toolbarObjects[obj.id]) !== "undefined")) {
-				this.updateValue(obj, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock);
-			}
 		}
 	},
 
 	/*
 	* This function updates the language drop-down list
 	*/
-	updateValue : function (obj, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock) {
-		var select = document.getElementById(this.editor._toolbarObjects[obj.id]["elementId"]);
-		var options = select.options;
-		for (var i = options.length; --i >= 0;) {
-			options[i].selected = false;
+	updateValue : function (select, language, selectionEmpty, fullNodeSelected, endPointsInSameBlock) {
+		var store = select.getStore();
+		store.removeAt(0);
+		if ((store.findExact('value', language) != -1) && (selectionEmpty || fullNodeSelected || !endPointsInSameBlock)) {
+			select.setValue(language);
+			store.insert(0, new store.recordType({
+				text: this.localize('Remove language mark'),
+				value: 'none'
+			}));
+		} else {
+			store.insert(0, new store.recordType({
+				text: this.localize('No language mark'),
+				value: 'none'
+			}));
+			select.setValue('none');
 		}
-		select.selectedIndex = 0;
-		options[0].selected = true;
-		select.options[0].text = this.localize("No language mark");
-		if (language != "none") {
-			for (i = options.length; --i >= 0;) {
-				if (language == options[i].value) {
-					if (selectionEmpty || fullNodeSelected || !endPointsInSameBlock) {
-						options[i].selected = true;
-						select.selectedIndex = i;
-						select.options[0].text = this.localize("Remove language mark");
-					}
-					break;
-				}
-			}
-		}
-		select.disabled = !(options.length>1) || (selectionEmpty && this.editor.getParentElement().nodeName.toLowerCase() === "body");
-		select.className = "";
-		if (select.disabled) {
-			select.className = "buttonDisabled";
-		}
+		select.setDisabled(!(store.getCount()>1) || (selectionEmpty && this.editor.getParentElement().nodeName.toLowerCase() === 'body'));
 	}
 });
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/locallang.xml	(copie de travail)
@@ -12,9 +12,9 @@
 			<label index="There are some unclosed quote">There are some unclosed quotes</label>
 			<label index="This attribute already exists in the TAG">This attribute already exists in the TAG</label>
 			<label index="No CSS class avaiable">No CSS classes available</label>
-			<label index="OPTIONS">OPTIONS</label>
-			<label index="ATTRIBUTES">ATTRIBUTES</label>
-			<label index="TAGs">TAGs</label>
+			<label index="OPTIONS">Options</label>
+			<label index="ATTRIBUTES">Attributes</label>
+			<label index="TAGs">Tags</label>
 			<label index="Colors">Colors</label>
 			<label index="Ok">Ok</label>
 			<label index="Cancel">Cancel</label>
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/QuickTag/quick-tag.js	(copie de travail)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  (c) 2004 Cau guanabara <caugb@ibest.com.br>
-*  (c) 2005-2009 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -33,52 +33,61 @@
  * TYPO3 SVN ID: $Id$
  */
 QuickTag = HTMLArea.Plugin.extend({
-
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-
 	/*
 	 * This function gets called by the class constructor
 	 */
 	configurePlugin : function(editor) {
-
 		this.pageTSConfiguration = this.editorConfiguration.buttons.inserttag;
-		this.tags = (this.pageTSConfiguration && this.pageTSConfiguration.tags) ? this.pageTSConfiguration.tags : null;
+		this.allowedTags = (this.pageTSConfiguration && this.pageTSConfiguration.tags) ? this.pageTSConfiguration.tags : null;
 		this.denyTags = (this.pageTSConfiguration && this.pageTSConfiguration.denyTags) ? this.pageTSConfiguration.denyTags : null;
 		this.allowedAttribs =  (this.pageTSConfiguration && this.pageTSConfiguration.allowedAttribs) ? this.pageTSConfiguration.allowedAttribs : null;
-
+		this.quotes = new RegExp('^\w+\s*([a-zA-Z_0-9:;]+=\"[^\"]*\"\s*|[a-zA-Z_0-9:;]+=\'[^\']*\'\s*)*$');
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.3",
-			developer	: "Cau Guanabara & Stanislas Rolland",
-			developerUrl	: "mailto:caugb@ibest.com.br",
-			copyrightOwner	: "Cau Guanabara & Stanislas Rolland",
-			sponsor		: "Independent production & SJBR",
-			sponsorUrl	: "http://www.netflash.com.br/gb/HA3-rc1/examples/quick-tag.html",
-			license		: "GPL"
+			version		: '2.0',
+			developer	: 'Cau Guanabara & Stanislas Rolland',
+			developerUrl	: 'http://www.sjbr.ca',
+			copyrightOwner	: 'Cau Guanabara & Stanislas Rolland',
+			sponsor		: 'Independent production & SJBR',
+			sponsorUrl	: 'http://www.sjbr.ca',
+			license		: 'GPL'
 		};
 		this.registerPluginInformation(pluginInformation);
-
 		/*
 		 * Registering the button
 		 */
-		var buttonId = "InsertTag";
+		var buttonId = 'InsertTag';
 		var buttonConfiguration = {
 			id		: buttonId,
-			tooltip		: this.localize("Quick Tag Editor"),
-			action		: "onButtonPress",
+			tooltip		: this.localize('Quick Tag Editor'),
+			action		: 'onButtonPress',
 			selection	: true,
 			dialog		: true
 		};
 		this.registerButton(buttonConfiguration);
-
 		return true;
 	 },
-
 	/*
+	 * Sets of default configuration values for dialogue form fields
+	 */
+	configDefaults: {
+		combo: {
+			editable: true,
+			typeAhead: true,
+			triggerAction: 'all',
+			forceSelection: true,
+			mode: 'local',
+			valueField: 'value',
+			displayField: 'text',
+			helpIcon: true
+		}
+	},
+	/*
 	 * This function gets called when the button was pressed.
 	 *
 	 * @param	object		editor: the editor instance
@@ -87,22 +96,678 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function(editor, id, target) {
-		this.dialog = this.openDialog("InsertTag", this.makeUrlFromPopupName("quicktag"), "setTag", null, {width:470, height:115});
+	onButtonPress: function(editor, id, target) {
+			// Could be a button or its hotkey
+		var buttonId = this.translateHotKey(id);
+		buttonId = buttonId ? buttonId : id;
+		this.openDialogue(
+			'Quick Tag Editor',
+			{
+				buttonId: buttonId
+			},
+			this.getWindowDimensions({ width: 570}, buttonId),
+			this.buildItemsConfig(),
+			this.setTag
+		);
+		this.insertedTag = this.dialog.find('itemId', 'insertedTag')[0];
+		this.tagCombo = this.dialog.find('itemId', 'tags')[0];
+		this.attributeCombo = this.dialog.find('itemId', 'attributes')[0];
+		this.valueCombo = this.dialog.find('itemId', 'values')[0];
+		this.colorCombo = this.dialog.find('itemId', 'colors')[0];
 	},
-
 	/*
-	 * Insert the tag
+	 * Build the window items config
+	 */
+	buildItemsConfig: function (element, buttonId) {
+		var tagStore = new Ext.data.ArrayStore({
+			autoDestroy:  true,
+			fields: [ { name: 'text'}, { name: 'value'}],
+			data: this.tags
+		});
+		if (this.denyTags) {
+			var denyTags = new RegExp('^(' + this.denyTags.split(',').join('|').replace(/ /g, '') + ')$', 'i');
+			tagStore.filterBy(function (record) {
+				return !denyTags.test(record.get('value'));
+			});
+				// Make sure the combo list is filtered
+			tagStore.snapshot = tagStore.data;
+		}
+		var attributeStore = new Ext.data.ArrayStore({
+			autoDestroy:  true,
+			fields: [ {name: 'tag'}, { name: 'text'}, { name: 'value'}],
+			data: this.attributes
+		});
+		this.valueRecord = Ext.data.Record.create([{name: 'attribute'}, { name: 'text'}, { name: 'value'}]);
+		var valueStore = new Ext.data.ArrayStore({
+			autoDestroy:  true,
+			fields: [ {name: 'attribute'}, { name: 'text'}, { name: 'value'}],
+			data: this.values,
+			listeners: {
+				load: {
+					fn: this.captureClasses,
+					scope: this
+				}
+			}
+		});
+		var itemsConfig = [{
+				xtype: 'textarea',
+				itemId: 'tagopen',
+				width: 400,
+				itemId: 'insertedTag',
+				fieldLabel: '<',
+				labelSeparator: '',
+				grow: true,
+				listeners: {
+					change: {
+						fn: this.filterAttributes,
+						scope: this
+					},
+					focus: {
+						fn: this.filterAttributes,
+						scope: this
+					}
+				}
+			},{
+				xtype: 'displayfield',
+				text: '>'
+			}, Ext.apply({
+				xtype: 'combo',
+				itemId: 'tags',
+				fieldLabel: this.localize('TAGs'),
+				store: tagStore,
+				listeners: {
+					select: {
+						fn: this.onTagSelect,
+						scope: this
+					}
+				}
+			}, this.configDefaults['combo'])
+			, Ext.apply({
+				xtype: 'combo',
+				itemId: 'attributes',
+				fieldLabel: this.localize('ATTRIBUTES'),
+				store: attributeStore,
+				hidden: true,
+				listeners: {
+					select: {
+						fn: this.onAttributeSelect,
+						scope: this
+					}
+				}
+			}, this.configDefaults['combo'])
+			, Ext.apply({
+				xtype: 'combo',
+				itemId: 'values',
+				fieldLabel: this.localize('OPTIONS'),
+				store: valueStore,
+				hidden: true,
+				listeners: {
+					select: {
+						fn: this.onValueSelect,
+						scope: this
+					}
+				}
+			}, this.configDefaults['combo'])
+			,{
+				xtype: 'colorpalettefield',
+				fieldLabel: this.localize('Colors'),
+				itemId: 'colors',
+				colorsConfiguration: this.editorConfiguration.colors,
+				hidden: true,
+				listeners: {
+					select: {
+						fn: this.onColorSelect,
+						scope: this
+					}
+				}
+			}
+		];
+	 	return {
+			xtype: 'fieldset',
+			title: this.localize('Quick Tag Editor'),
+			defaultType: 'textfield',
+			labelWidth: 100,
+			defaults: {
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * Add a record for each class selector found in the stylesheets
+	 */
+	captureClasses: function (valueStore) {
+		this.parseCssRule(this.editor.document.styleSheets, valueStore);
+	},
+	parseCssRule: function (rules, valueStore) {
+		Ext.each(rules, function (rule) {
+			if (rule.selectorText) {
+				if (/^(\w*)\.(\w+)$/.test(rule.selectorText)) {
+					valueStore.add(new this.valueRecord({
+						attribute: 'class',
+						text: rule.selectorText,
+						value: RegExp.$2 + '"'
+					}));
+				}
+			} else {
+					// ImportRule (Mozilla)
+				if (rule.styleSheet) {
+					this.parseCssRule(rule.styleSheet.cssRules, valueStore);
+				}
+					// MediaRule (Mozilla)
+				if (rule.cssRules) {
+					this.parseCssRule(rule.cssRules, valueStore);
+				}
+					// IE imports
+				if (rule.imports) {
+					this.parseCssRule(rule.imports, valueStore);
+				}
+				if (rule.rules) {
+					this.parseCssRule(rule.rules, valueStore);
+				}
+			}
+		}, this);
+	},
+	/*
+	 * Handler invoked when a tag is selected
+	 * Update the attributes combo and the inserted tag field
+	 */
+	onTagSelect: function (tagCombo, tagRecord) {
+		var tag = tagRecord.get('value');
+		this.filterAttributes();
+		this.attributeCombo.clearValue();
+		this.attributeCombo.show();
+		this.valueCombo.hide();
+		this.insertedTag.setValue(tag);
+		this.insertedTag.focus(false, 50);
+	},
+	/*
+	 * Filter out attributes not applicable to the tag, already present in the tag or not allowed
+	 */
+	filterAttributes: function () {
+		var tag = this.tagCombo.getValue();
+		var insertedTag = this.insertedTag.getValue();
+		var attributeStore = this.attributeCombo.getStore();
+		if (attributeStore.realSnapshot) {
+			attributeStore.snapshot = attributeStore.realSnapshot;
+			delete attributeStore.realSnapshot;
+			attributeStore.clearFilter(true);
+		}
+		var allowedAttribs = '';
+		if (this.allowedAttribs) {
+			allowedAttribs = this.allowedAttribs.split(',').join('|').replace(/ /g, '');
+		}
+		if (this.tags && this.tags[tag] && this.tags[tag].allowedAttribs) {
+			allowedAttribs += allowedAttribs ? '|' : '';
+			allowedAttribs += this.tags[tag].allowedAttribs.split(',').join('|').replace(/ /g, '');
+		}
+		if (allowedAttribs) {
+			var allowedAttribs = new RegExp('^(' + allowedAttribs + ')$');
+		}
+		attributeStore.filterBy(function (attributeRecord) {
+				// Filter out attributes already used in the tag, not applucable to tag or not allowed
+			var testAttrib = new RegExp('(' + attributeRecord.get('value') + ')', 'ig');
+			var tagValue = attributeRecord.get('tag');
+			return (tagValue == 'all' || tagValue == tag) && !testAttrib.test(insertedTag) && (!allowedAttribs || allowedAttribs.test(attributeRecord.get('text')));
+		});
+			// Make sure the combo list is filtered
+		attributeStore.realSnapshot = attributeStore.snapshot;
+		attributeStore.snapshot = attributeStore.data;
+	},
+	/*
+	 * Filter out not applicable to the attribute or style values already present in the tag
+	 * Filter out classes not applicable to the current tag
+	 */
+	filterValues: function (attribute) {
+		var tag = this.tagCombo.getValue();
+		var insertedTag = this.insertedTag.getValue();
+		var valueStore = this.valueCombo.getStore();
+		if (valueStore.realSnapshot) {
+			valueStore.snapshot = valueStore.realSnapshot;
+			delete valueStore.realSnapshot;
+			valueStore.clearFilter(true);
+		}
+		var expr = new RegExp('(^' + tag + '[\.])|(^[\.])', 'i');
+		valueStore.filterBy(function (valueRecord) {
+			var value = valueRecord.get('value');
+			if (attribute === 'style') {
+				expr = new RegExp('(' + ((value.charAt(0) == '+' || value.charAt(0) == '-') ? '\\' : '') + value + ')', 'ig');
+			}
+			return valueRecord.get('attribute') == attribute && (attribute !== 'style' || !expr.test(insertedTag)) && (attribute !== 'class' || expr.test(valueRecord.get('text')));
+		});
+			// Make sure the combo list is filtered
+		valueStore.realSnapshot = valueStore.snapshot;
+		valueStore.snapshot = valueStore.data;
+		this.valueCombo.setVisible(valueStore.getCount() ? true : false);
+	},
+	/*
+	 * Handler invoked when an attribute is selected
+	 * Update the values combo and the inserted tag field
+	 */
+	onAttributeSelect: function (attributeCombo, attributeRecord) {
+		var insertedTag = this.insertedTag.getValue();
+		var attribute = attributeRecord.get('text');
+		this.valueCombo.clearValue();
+		if (/color/.test(attribute)) {
+			this.valueCombo.hide();
+			this.colorCombo.show();
+		} else {
+			this.filterValues(attribute);
+		}
+		this.insertedTag.setValue(insertedTag + ((/\"/.test(insertedTag) && (!/\"$/.test(insertedTag) || /=\"$/.test(insertedTag))) ? '" ' : ' ') + attributeRecord.get('value'));
+		this.insertedTag.focus(false, 50);
+	},
+	/*
+	 * Handler invoked when a value is selected
+	 * Update the inserted tag field
+	 */
+	onValueSelect: function (combo, record) {
+		var style = this.attributeCombo.getValue() === 'style="';
+		this.insertedTag.setValue(this.insertedTag.getValue() + (style && !/="$/.test(this.insertedTag.getValue()) ? '; ' : '') + combo.getValue());
+		this.insertedTag.focus(false, 50);
+		combo.clearValue();
+		if (style) {
+			if (/color/.test(record.get('text'))) {
+				this.colorCombo.show();
+			}
+		} else {
+			combo.hide();
+			this.attributeCombo.clearValue();
+		}
+	},
+	/*
+	 * Handler invoked when a color is selected
+	 * Update the inserted tag field
+	 */
+	onColorSelect: function (combo, record) {
+		var style = this.attributeCombo.getValue() === 'style="';
+		this.insertedTag.setValue(this.insertedTag.getValue() + '#' + combo.getValue() + (style ? '' : '"'));
+		this.insertedTag.focus(false, 50);
+		combo.setValue('');
+		combo.hide();
+		if (!style) {
+			this.attributeCombo.clearValue();
+		}
+	},
+	/*
+	 * Handler invoked when a OK button is pressed
+	 */
+	setTag: function (button, event) {
+		this.restoreSelection();
+		var insertedTag = this.insertedTag.getValue();
+		var currentTag = this.tagCombo.getValue();
+		if (!insertedTag) {
+			Ext.MessageBox.alert('', this.localize("Enter the TAG you want to insert"));
+			this.insertedTag.focus();
+			event.stopEvent();
+			return false;
+		}
+		if (this.quotes.test(insertedTag)) {
+			if (this.quotes.test(insertedTag + '"')) {
+				Ext.MessageBox.alert('', this.localize("There are some unclosed quote"));
+				this.insertedTag.focus();
+				this.insertedTag.select();
+				event.stopEvent();
+				return false;
+			} else {
+				this.insertedTag.setValue(insertedTag + '"');
+			}
+		}
+		insertedTag = insertedTag.replace(/(<|>)/g, '');
+		var tagOpen = '<' + insertedTag + '>';
+		var tagClose = tagOpen.replace(/^<(\w+) ?.*>/, '</$1>');
+		var subTags = this.subTags[currentTag];
+		if (subTags) {
+			tagOpen = tagOpen + this.subTags.open;
+			tagClose = this.subTags.close + tagClose;
+		}
+		this.editor.focus();
+		this.editor.surroundHTML(tagOpen, tagClose);
+		this.close();
+		event.stopEvent();
+	},
+	/*
+	 * Open the dialogue window
 	 *
-	 * @param	object		param: the constructed tag
+	 * @param	string		title: the window title
+	 * @param	object		arguments: some arguments for the handler
+	 * @param	integer		dimensions: the opening dimensions of the window
+	 * @param	object		items: the configuration of the window items
+	 * @param	function	handler: handler when the OK button if clicked
 	 *
-	 * @return	boolean		false
+	 * @return	void
 	 */
-	setTag : function(param) {
-		if(param && typeof(param.tagopen) != "undefined") {
-			this.editor.focusEditor();
-			this.editor.surroundHTML(param.tagopen, param.tagclose);
+	openDialogue: function (title, arguments, dimensions, items, handler) {
+		if (this.dialog) {
+			this.dialog.close();
 		}
+		this.dialog = new Ext.Window({
+			title: this.localize(title),
+			arguments: arguments,
+			cls: 'htmlarea-window',
+			border: false,
+			width: dimensions.width,
+			height: 'auto',
+			iconCls: arguments.buttonId,
+			listeners: {
+				close: {
+					fn: this.onClose,
+					scope: this
+				}
+			},
+			items: {
+				xtype: 'container',
+				layout: 'form',
+				defaults: {
+					labelWidth: 150
+				},
+				items: items
+			},
+			buttons: [
+				this.buildButtonConfig('Cancel', this.onCancel),
+				this.buildButtonConfig('OK', handler)
+			]
+		});
+		this.show();
+	},
+	tags: [
+		['a', 'a'],
+		['abbr', 'abbr'],
+		['acronym', 'acronym'],
+		['address', 'address'],
+		['b', 'b'],
+		['big', 'big'],
+		['blockquote', 'blockquote'],
+		['cite', 'cite'],
+		['code', 'code'],
+		['div', 'div'],
+		['em', 'em'],
+		['fieldset', 'fieldset'],
+		['font', 'font'],
+		['h1', 'h1'],
+		['h2', 'h2'],
+		['h3', 'h3'],
+		['h4', 'h4'],
+		['h5', 'h5'],
+		['h6', 'h6'],
+		['i', 'i'],
+		['legend', 'legend'],
+		['li', 'li'],
+		['ol', 'ol'],
+		['ul', 'ul'],
+		['p', 'p'],
+		['pre', 'pre'],
+		['q', 'q'],
+		['small', 'small'],
+		['span', 'span'],
+		['strike', 'strike'],
+		['strong', 'strong'],
+		['sub', 'sub'],
+		['sup', 'sup'],
+		['table', 'table'],
+		['tt', 'tt'],
+		['u', 'u']
+	],
+	attributes: [
+		['all', 'class', 'class="'],
+		['all', 'dir', 'dir="'],
+		['all', 'id', 'id="'],
+		['all', 'lang', 'lang="'],
+		['all', 'onFocus', 'onFocus="'],
+		['all', 'onBlur', 'onBlur="'],
+		['all', 'onClick', 'onClick="'],
+		['all', 'onDblClick', 'onDblClick="'],
+		['all', 'onMouseDown', 'onMouseDown="'],
+		['all', 'onMouseUp', 'onMouseUp="'],
+		['all', 'onMouseOver', 'onMouseOver="'],
+		['all', 'onMouseMove', 'onMouseMove="'],
+		['all', 'onMouseOut', 'onMouseOut="'],
+		['all', 'onKeyPress', 'onKeyPress="'],
+		['all', 'onKeyDown', 'onKeyDown="'],
+		['all', 'onKeyUp', 'onKeyUp="'],
+		['all', 'style', 'style="'],
+		['all', 'title', 'title="'],
+		['all', 'xml:lang', 'xml:lang="'],
+		['a', 'href', 'href="'],
+		['a', 'name', 'name="'],
+		['a', 'target', 'target="'],
+		['font', 'face', 'face="'],
+		['font', 'size', 'size="'],
+		['font', 'color', 'color="'],
+		['div', 'align', 'align="'],
+		['h1', 'align', 'align="'],
+		['h2', 'align', 'align="'],
+		['h3', 'align', 'align="'],
+		['h4', 'align', 'align="'],
+		['h5', 'align', 'align="'],
+		['h6', 'align', 'align="'],
+		['p', 'align', 'align="'],
+		['table', 'align', 'align="'],
+		['table', 'width', 'width="'],
+		['table', 'height', 'height="'],
+		['table', 'cellpadding', 'cellpadding="'],
+		['table', 'cellspacing', 'cellspacing="'],
+		['table', 'background', 'background="'],
+		['table', 'bgcolor', 'bgcolor="'],
+		['table', 'border', 'border="'],
+		['table', 'bordercolor', 'bordercolor="']
+	],
+	values: [
+		['href', 'http://', 'http://'],
+		['href', 'https://', 'https://'],
+		['href', 'ftp://', 'ftp://'],
+		['href', 'mailto:', 'mailto:'],
+		['href', '#', '#"'],
+		['target', '_top', '_top"'],
+		['target', '_self', '_self"'],
+		['target', '_parent', '_parent"'],
+		['target', '_blank', '_blank"'],
+		['face', 'Verdana', 'Verdana"'],
+		['face', 'Arial', 'Arial"'],
+		['face', 'Tahoma', 'Tahoma"'],
+		['face', 'Courier New', 'Courier New"'],
+		['face', 'Times New Roman', 'Times New Roman"'],
+		['size', '1', '1"'],
+		['size', '2', '2"'],
+		['size', '3', '3"'],
+		['size', '4', '4"'],
+		['size', '5', '5"'],
+		['size', '6', '6"'],
+		['size', '+1', '+1"'],
+		['size', '+2', '+2"'],
+		['size', '+3', '+3"'],
+		['size', '+4', '+4"'],
+		['size', '+5', '+5"'],
+		['size', '+6', '+6"'],
+		['size', '-1', '-1"'],
+		['size', '-2', '-2"'],
+		['size', '-3', '-3"'],
+		['size', '-4', '-4"'],
+		['size', '-5', '-5"'],
+		['size', '-6', '-6"'],
+		['align', 'center', 'center"'],
+		['align', 'left', 'left"'],
+		['align', 'right', 'right"'],
+		['align', 'justify', 'justify"'],
+		['dir', 'rtl', 'rtl"'],
+		['dir', 'ltr', 'ltr"'],
+		['lang', 'Afrikaans ', 'af"'],
+		['lang', 'Albanian ', 'sq"'],
+		['lang', 'Arabic ', 'ar"'],
+		['lang', 'Basque ', 'eu"'],
+		['lang', 'Breton ', 'br"'],
+		['lang', 'Bulgarian ', 'bg"'],
+		['lang', 'Belarusian ', 'be"'],
+		['lang', 'Catalan ', 'ca"'],
+		['lang', 'Chinese ', 'zh"'],
+		['lang', 'Croatian ', 'hr"'],
+		['lang', 'Czech ', 'cs"'],
+		['lang', 'Danish ', 'da"'],
+		['lang', 'Dutch ', 'nl"'],
+		['lang', 'English ', 'en"'],
+		['lang', 'Estonian ', 'et"'],
+		['lang', 'Faeroese ', 'fo"'],
+		['lang', 'Farsi ', 'fa"'],
+		['lang', 'Finnish ', 'fi"'],
+		['lang', 'French ', 'fr"'],
+		['lang', 'Gaelic ', 'gd"'],
+		['lang', 'German ', 'de"'],
+		['lang', 'Greek ', 'el"'],
+		['lang', 'Hebrew ', 'he"'],
+		['lang', 'Hindi ', 'hi"'],
+		['lang', 'Hungarian ', 'hu"'],
+		['lang', 'Icelandic ', 'is"'],
+		['lang', 'Indonesian ', 'id"'],
+		['lang', 'Italian ', 'it"'],
+		['lang', 'Japanese ', 'ja"'],
+		['lang', 'Korean ', 'ko"'],
+		['lang', 'Latvian ', 'lv"'],
+		['lang', 'Lithuanian ', 'lt"'],
+		['lang', 'Macedonian ', 'mk"'],
+		['lang', 'Malaysian ', 'ms"'],
+		['lang', 'Maltese ', 'mt"'],
+		['lang', 'Norwegian ', 'no"'],
+		['lang', 'Polish ', 'pl"'],
+		['lang', 'Portuguese ', 'pt"'],
+		['lang', 'Rhaeto-Romanic ', 'rm"'],
+		['lang', 'Romanian ', 'ro"'],
+		['lang', 'Russian ', 'ru"'],
+		['lang', 'Sami ', 'sz"'],
+		['lang', 'Serbian ', 'sr"'],
+		['lang', 'Setswana ', 'tn"'],
+		['lang', 'Slovak ', 'sk"'],
+		['lang', 'Slovenian ', 'sl"'],
+		['lang', 'Spanish ', 'es"'],
+		['lang', 'Sutu ', 'sx"'],
+		['lang', 'Swedish ', 'sv"'],
+		['lang', 'Thai ', 'th"'],
+		['lang', 'Tsonga ', 'ts"'],
+		['lang', 'Turkish ', 'tr"'],
+		['lang', 'Ukrainian ', 'uk"'],
+		['lang', 'Urdu ', 'ur"'],
+		['lang', 'Vietnamese ', 'vi"'],
+		['lang', 'Xhosa ', 'xh"'],
+		['lang', 'Yiddish ', 'yi"'],
+		['lang', 'Zulu', 'zu"'],
+		['style', 'azimuth', 'azimuth: '],
+		['style', 'background', 'background: '],
+		['style', 'background-attachment', 'background-attachment: '],
+		['style', 'background-color', 'background-color: '],
+		['style', 'background-image', 'background-image: '],
+		['style', 'background-position', 'background-position: '],
+		['style', 'background-repeat', 'background-repeat: '],
+		['style', 'border', 'border: '],
+		['style', 'border-bottom', 'border-bottom: '],
+		['style', 'border-left', 'border-left: '],
+		['style', 'border-right', 'border-right: '],
+		['style', 'border-top', 'border-top: '],
+		['style', 'border-bottom-color', 'border-bottom-color: '],
+		['style', 'border-left-color', 'border-left-color: '],
+		['style', 'border-right-color', 'border-right-color: '],
+		['style', 'border-top-color', 'border-top-color: '],
+		['style', 'border-bottom-style', 'border-bottom-style: '],
+		['style', 'border-left-style', 'border-left-style: '],
+		['style', 'border-right-style', 'border-right-style: '],
+		['style', 'border-top-style', 'border-top-style: '],
+		['style', 'border-bottom-width', 'border-bottom-width: '],
+		['style', 'border-left-width', 'border-left-width: '],
+		['style', 'border-right-width', 'border-right-width: '],
+		['style', 'border-top-width', 'border-top-width: '],
+		['style', 'border-collapse', 'border-collapse: '],
+		['style', 'border-color', 'border-color: '],
+		['style', 'border-style', 'border-style: '],
+		['style', 'border-width', 'border-width: '],
+		['style', 'bottom', 'bottom: '],
+		['style', 'caption-side', 'caption-side: '],
+		['style', 'cell-spacing', 'cell-spacing: '],
+		['style', 'clear', 'clear: '],
+		['style', 'clip', 'clip: '],
+		['style', 'color', 'color: '],
+		['style', 'column-span', 'column-span: '],
+		['style', 'content', 'content: '],
+		['style', 'cue', 'cue: '],
+		['style', 'cue-after', 'cue-after: '],
+		['style', 'cue-before', 'cue-before: '],
+		['style', 'cursor', 'cursor: '],
+		['style', 'direction', 'direction: '],
+		['style', 'display', 'display: '],
+		['style', 'elevation', 'elevation: '],
+		['style', 'filter', 'filter: '],
+		['style', 'float', 'float: '],
+		['style', 'font-family', 'font-family: '],
+		['style', 'font-size', 'font-size: '],
+		['style', 'font-size-adjust', 'font-size-adjust: '],
+		['style', 'font-style', 'font-style: '],
+		['style', 'font-variant', 'font-variant: '],
+		['style', 'font-weight', 'font-weight: '],
+		['style', 'height', 'height: '],
+		['style', '!important', '!important: '],
+		['style', 'left', 'left: '],
+		['style', 'letter-spacing', 'letter-spacing: '],
+		['style', 'line-height', 'line-height: '],
+		['style', 'list-style', 'list-style: '],
+		['style', 'list-style-image', 'list-style-image: '],
+		['style', 'list-style-position', 'list-style-position: '],
+		['style', 'list-style-type', 'list-style-type: '],
+		['style', 'margin', 'margin: '],
+		['style', 'margin-bottom', 'margin-bottom: '],
+		['style', 'margin-left', 'margin-left: '],
+		['style', 'margin-right', 'margin-right: '],
+		['style', 'margin-top', 'margin-top: '],
+		['style', 'marks', 'marks: '],
+		['style', 'max-height', 'max-height: '],
+		['style', 'min-height', 'min-height: '],
+		['style', 'max-width', 'max-width: '],
+		['style', 'min-width', 'min-width: '],
+		['style', 'orphans', 'orphans: '],
+		['style', 'overflow', 'overflow: '],
+		['style', 'padding', 'padding: '],
+		['style', 'padding-bottom', 'padding-bottom: '],
+		['style', 'padding-left', 'padding-left: '],
+		['style', 'padding-right', 'padding-right: '],
+		['style', 'padding-top', 'padding-top: '],
+		['style', 'page-break-after', 'page-break-after: '],
+		['style', 'page-break-before', 'page-break-before: '],
+		['style', 'pause', 'pause: '],
+		['style', 'pause-after', 'pause-after: '],
+		['style', 'pause-before', 'pause-before: '],
+		['style', 'pitch', 'pitch: '],
+		['style', 'pitch-range', 'pitch-range: '],
+		['style', 'play-during', 'play-during: '],
+		['style', 'position', 'position: '],
+		['style', 'richness', 'richness: '],
+		['style', 'right', 'right: '],
+		['style', 'row-span', 'row-span: '],
+		['style', 'size', 'size: '],
+		['style', 'speak', 'speak: '],
+		['style', 'speak-date', 'speak-date: '],
+		['style', 'speak-header', 'speak-header: '],
+		['style', 'speak-numeral', 'speak-numeral: '],
+		['style', 'speak-punctuation', 'speak-punctuation: '],
+		['style', 'speak-time', 'speak-time: '],
+		['style', 'speech-rate', 'speech-rate: '],
+		['style', 'stress', 'stress: '],
+		['style', 'table-layout', 'table-layout: '],
+		['style', 'text-align', 'text-align: '],
+		['style', 'text-decoration', 'text-decoration: '],
+		['style', 'text-indent', 'text-indent: '],
+		['style', 'text-shadow', 'text-shadow: '],
+		['style', 'text-transform', 'text-transform: '],
+		['style', 'top', 'top: '],
+		['style', 'vertical-align', 'vertical-align: '],
+		['style', 'visibility', 'visibility: '],
+		['style', 'voice-family', 'voice-family: '],
+		['style', 'volume', 'volume: '],
+		['style', 'white-space', 'white-space: '],
+		['style', 'widows', 'widows: '],
+		['style', 'width', 'width: '],
+		['style', 'word-spacing', 'word-spacing: '],
+		['style', 'z-index', 'z-index: ']
+	],
+	subTags: {
+		'table': {
+			'open': '<tbody><tr><td>',
+			'close': '</td></tr></tbody>'
+		}
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/RemoveFormat/remove-format.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -44,12 +44,12 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.6",
+			version		: "1.7",
 			developer	: "Stanislas Rolland",
-			developerUrl	: "http://www.fructifor.ca/",
+			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
-			sponsor		: "Fructifor Inc.",
-			sponsorUrl	: "http://www.fructifor.ca/",
+			sponsor		: "SJBR",
+			sponsorUrl	: "http://www.sjbr.ca/",
 			license		: "GPL"
 		};
 		this.registerPluginInformation(pluginInformation);
@@ -172,7 +172,7 @@
 				}
 
 				if (param["cleaning_area"] == "all") {
-					editor._doc.body.innerHTML = html;
+					editor.setHTML(html);
 				} else {
 					editor.insertHTML(html);
 				}
@@ -182,4 +182,3 @@
 		}
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SelectFont/select-font.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -40,35 +40,22 @@
 	 */
 	configurePlugin : function (editor) {
 
-		this.options = new Object();
-		this.defaultValue = new Object();
-		if (this.editorConfiguration.buttons.fontstyle) {
-			this.options.FontName = this.editorConfiguration.buttons.fontstyle.options;
-			if (this.editorConfiguration.buttons.fontstyle.defaultItem) {
-				this.defaultValue.FontName = this.editorConfiguration.buttons.fontstyle.options[this.editorConfiguration.buttons.fontstyle.defaultItem];
-			}
-		}
-		if (this.editorConfiguration.buttons.fontsize) {
-			this.options.FontSize = this.editorConfiguration.buttons.fontsize.options;
-			if (this.editorConfiguration.buttons.fontsize.defaultItem) {
-				this.defaultValue.FontSize = this.editorConfiguration.buttons.fontsize.options[this.editorConfiguration.buttons.fontsize.defaultItem];
-			}
-		}
+		this.buttonsConfiguration = this.editorConfiguration.buttons;
 		this.disablePCexamples = this.editorConfiguration.disablePCexamples;
 
 			// Font formating will use the style attribute
-		if (this.editor.getPluginInstance("TextStyle")) {
-			this.editor.getPluginInstance("TextStyle").addAllowedAttribute("style");
-			this.allowedAttributes = this.editor.getPluginInstance("TextStyle").allowedAttributes;
+		if (this.getPluginInstance("TextStyle")) {
+			this.getPluginInstance("TextStyle").addAllowedAttribute("style");
+			this.allowedAttributes = this.getPluginInstance("TextStyle").allowedAttributes;
 		}
-		if (this.editor.getPluginInstance("InlineElements")) {
-			this.editor.getPluginInstance("InlineElements").addAllowedAttribute("style");
+		if (this.getPluginInstance("InlineElements")) {
+			this.getPluginInstance("InlineElements").addAllowedAttribute("style");
 			if (!this.allowedAllowedAttributes) {
-				this.allowedAttributes = this.editor.getPluginInstance("InlineElements").allowedAttributes;
+				this.allowedAttributes = this.getPluginInstance("InlineElements").allowedAttributes;
 			}
 		}
-		if (this.editor.getPluginInstance("BlockElements")) {
-			this.editor.getPluginInstance("BlockElements").addAllowedAttribute("style");
+		if (this.getPluginInstance("BlockElements")) {
+			this.getPluginInstance("BlockElements").addAllowedAttribute("style");
 		}
 		if (!this.allowedAttributes) {
 			this.allowedAttributes = new Array("id", "title", "lang", "xml:lang", "dir", "class", "style");
@@ -94,19 +81,25 @@
 		/*
 		 * Registering the dropdowns
 		 */
-		var buttonId;
-		for (var i = 0, n = this.dropDownList.length; i < n; ++i) {
-			var dropDown = this.dropDownList[i];
-			buttonId = dropDown[0];
+		Ext.each(this.dropDownList, function (dropDown) {
+			var buttonId = dropDown[0];
+				// Load the options var
+			if (this.buttonsConfiguration[dropDown[2]] && this.buttonsConfiguration[dropDown[2]].dataUrl) {
+				var optionsData = this.getJavascriptFile(this.buttonsConfiguration[dropDown[2]].dataUrl, "noEval");
+				if (optionsData) {
+					eval(optionsData);
+				}
+			}
 			var dropDownConfiguration = {
-				id		: buttonId,
-				tooltip		: this.localize(buttonId.toLowerCase()),
-				options		: this.options[buttonId],
-				action		: "onChange",
-				context		: null
+				id: buttonId,
+				tooltip: this.localize(buttonId.toLowerCase()),
+				options: options,
+				action: "onChange",
+				tpl: this.disablePCexamples ? '' : '<tpl for="."><div ext:qtip="{value}" style="' + dropDown[3] + '" class="x-combo-list-item">{text}</div></tpl>'
 			};
 			this.registerDropDown(dropDownConfiguration);
-		}
+			return true;
+		}, this);
 		return true;
 	 },
 	 
@@ -114,8 +107,8 @@
 	 * The list of buttons added by this plugin
 	 */
 	dropDownList : [
-		["FontName", null],
-		["FontSize", null]
+		['FontName', null, 'fontstyle', 'font-family:{value};text-align:left;font-size:11px;'],
+		['FontSize', null, 'fontsize', 'text-align:left;font-size:{value};']
 	],
 	
 	/*
@@ -137,21 +130,17 @@
 	/*
 	 * This function gets called when some font style or font size was selected from the dropdown lists
 	 */
-	onChange : function (editor, buttonId) {
-		var select = document.getElementById(this.editor._toolbarObjects[buttonId].elementId),
-			param = select.value;
-		if (!select.selectedIndex) {
-			param = "";
-		}
+	onChange : function (editor, combo, record, index) {
+		var param = combo.getValue();
 		editor.focusEditor();
 		var selection = editor._getSelection(),
 			range = editor._createRange(selection),
-			statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null,
+			statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null,
 			element;
 		if (editor._selectionEmpty(selection)) {
 			element = editor.getParentElement(selection, range);
 				// Set the style attribute
-			this.setStyle(element, buttonId, param);
+			this.setStyle(element, combo.itemId, param);
 				// Remove the span tag if it has no more attribute
 			if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
 				editor.removeMarkup(element);
@@ -159,7 +148,7 @@
 		} else if (statusBarSelection) {
 			element = statusBarSelection;
 				// Set the style attribute
-			this.setStyle(element, buttonId, param);
+			this.setStyle(element, combo.itemId, param);
 				// Remove the span tag if it has no more attribute
 			if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
 				editor.removeMarkup(element);
@@ -167,7 +156,7 @@
 		} else if (editor.endPointsInSameBlock()) {
 			element = editor._doc.createElement("span");
 				// Set the style attribute
-			this.setStyle(element, buttonId, param);
+			this.setStyle(element, combo.itemId, param);
 				// Wrap the selection with span tag with the style attribute
 			editor.wrapWithInlineElement(element, selection, range);
 			if (HTMLArea.is_gecko) {
@@ -187,9 +176,9 @@
 	 * @return	void
 	 */
 	setStyle : function (element, buttonId, value) {
-		element.style[this.styleProperty[buttonId]] = value;
+		element.style[this.styleProperty[buttonId]] = (value && value !== 'none') ? value : '';
 			// In IE, we need to remove the empty attribute in order to unset it
-		if (HTMLArea.is_ie && !value) {
+		if (HTMLArea.is_ie && (!value || value == 'none')) {
 			element.style.removeAttribute(this.styleProperty[buttonId], false);
 		}
 		if (HTMLArea.is_opera) {
@@ -207,62 +196,36 @@
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
+	onUpdateToolbar: function (select, mode, selectionEmpty, ancestors, endPointsInSameBlock) {
 		var editor = this.editor;
-		if (editor.getMode() === "wysiwyg" && this.editor.isEditable()) {
-			var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
-			var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement(),
-				enabled = editor.endPointsInSameBlock() && !(editor._selectionEmpty(editor._getSelection()) && parentElement.nodeName.toLowerCase() == "body"),
-				buttonId, value, k;
-			for (var i = this.dropDownList.length; --i >= 0;) {
-				buttonId = this.dropDownList[i][0];
-				if (this.isButtonInToolbar(buttonId)) {
-					var select = document.getElementById(editor._toolbarObjects[buttonId].elementId);
-					value = parentElement.style[this.styleProperty[buttonId]];
-					if (!value) {
-						if (HTMLArea.is_gecko) {
-							if (editor._doc.defaultView.getComputedStyle(parentElement, null)) {
-								value = editor._doc.defaultView.getComputedStyle(parentElement, null).getPropertyValue(this.cssProperty[buttonId]);
-							}
-						} else {
-							value = parentElement.currentStyle[this.styleProperty[buttonId]];
-						}
+		if (mode === 'wysiwyg' && editor.isEditable()) {
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
+			var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement();
+			var value = parentElement.style[this.styleProperty[select.itemId]];
+			if (!value) {
+				if (HTMLArea.is_gecko) {
+					if (editor._doc.defaultView.getComputedStyle(parentElement, null)) {
+						value = editor._doc.defaultView.getComputedStyle(parentElement, null).getPropertyValue(this.cssProperty[select.itemId]);
 					}
-					select.selectedIndex = 0;
-					if (value) {
-						var options = this.options[buttonId];
-						k = 0;
-						for (var option in options) {
-							if (options.hasOwnProperty(option)) {
-								if (options[option] == value
-										|| options[option].replace(/[\'\"]/g, "") == value.replace(/, /g, ",").replace(/[\'\"]/g, "")) {
-									select.selectedIndex = k;
-									break;
-								}
-								++k;
-							}
-						}
-					}
-					select.disabled = !enabled;
-					select.className = "";
-					if (select.disabled) {
-						select.className = "buttonDisabled";
-					}
+				} else {
+					value = parentElement.currentStyle[this.styleProperty[select.itemId]];
 				}
 			}
-		}
-	},
-	
-	/*
-	 * This function gets called when the plugin is generated
-	 */
-	onGenerate : function () {
-		if (!this.disablePCexamples && this.isButtonInToolbar("FontName")) {
-			var select = document.getElementById(this.editor._toolbarObjects.FontName.elementId);
-			for (var i = select.options.length; --i >= 0;) {
-				if (HTMLArea.is_gecko) select.options[i].setAttribute("style", "font-family:" + select.options[i].value + ";");
-					else select.options[i].style.cssText = "font-family:" + select.options[i].value + ";";
+			var store = select.getStore();
+			var index = -1;
+			if (value) {
+				index = store.findBy(
+					function (record, id) {
+						return record.get('value').replace(/[\"\']/g, "") == value.replace(/, /g, ",").replace(/[\"\']/g, "");
+					}
+				);
 			}
+			if (index != -1) {
+				select.setValue(store.getAt(index).get('value'));
+			} else {
+				select.setValue('none');
+			}
+			select.setDisabled(!endPointsInSameBlock || (selectionEmpty && /^body$/i.test(parentElement.nodeName)));
 		}
 	}
 });
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-check-ui.js	(copie de travail)
@@ -67,7 +67,7 @@
 
 function saveClicked() {
 	if (modified) {
-		dialog.plugin.editor.getPluginInstance("EditorMode").setHTML(makeCleanDoc(false));
+		dialog.plugin.editor.setHTML(makeCleanDoc(false));
 	}
 	if ((to_p_dict.length || to_r_list.length) && dialog.plugin.enablePersonalDicts) {
 		var data = {};
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js	(copie de travail)
@@ -2,7 +2,7 @@
 *  Copyright notice
 *
 *  (c) 2003 dynarch.com. Authored by Mihai Bazon, sponsored by www.americanbible.org.
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -92,8 +92,6 @@
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
-
-		var editorNumber = editor._editorNumber;
 		switch (buttonId) {
 			case "SpellCheck":
 				var charset = (this.contentCharset.toLowerCase() == 'iso-8859-1') ? "-iso-8859-1" : "";
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/locallang.xml	(copie de travail)
@@ -67,6 +67,7 @@
 			<label index="Character">Character</label>
 			<label index="Align on this character">Align text relative to this character</label>
 			<label index="Collapsed borders">Collapsed borders</label>
+			<label index="Detached borders">Detached borders</label>
 			<label index="Color:">Color:</label>
 			<label index="Description">Description</label>
 			<label index="FG Color:">FG Color:</label>
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js	(copie de travail)
@@ -3,7 +3,7 @@
 *
 *  (c) 2002 interactivetools.com, inc. Authored by Mihai Bazon, sponsored by http://www.bloki.com.
 *  (c) 2005 Xinha, http://xinha.gogo.co.nz/ for the original toggle borders function.
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -66,11 +66,9 @@
 				this.defaultClass = this.buttonsConfiguration.table.properties.tableClass.defaultValue;
 			}
 		}
-		
 		if (this.buttonsConfiguration.blockstyle) {
 			this.tags = this.editorConfiguration.buttons.blockstyle.tags;
 		}
-		
 		this.tableParts = ["tfoot", "thead", "tbody"];
 		this.convertAlignment = { "not set" : "none", "left" : "JustifyLeft", "center" : "JustifyCenter", "right" : "JustifyRight", "justify" : "JustifyFull" };
 		
@@ -78,7 +76,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "4.2",
+			version		: "5.0",
 			developer	: "Mihai Bazon & Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Mihai Bazon & Stanislas Rolland",
@@ -114,7 +112,7 @@
 	/*
 	 * The list of buttons added by this plugin
 	 */
-	buttonList : [
+	buttonList: [
 		["InsertTable",		null,				"table", true],
 		["toggle-borders",	null, 				"toggleborders", false],
 		["table-prop",		"table",			"tableproperties", true],
@@ -136,222 +134,430 @@
 		["cell-merge",		"tr",				"cellmerge", false],
 		["cell-split",		"td,th[colSpan!=1,rowSpan!=1]",	"cellsplit", false]
 	],
-	
 	/*
+	 * Sets of default configuration values for dialogue form fields
+	 */
+	configDefaults: {
+		combo: {
+			editable: true,
+			typeAhead: true,
+			triggerAction: 'all',
+			forceSelection: true,
+			mode: 'local',
+			valueField: 'value',
+			displayField: 'text',
+			helpIcon: true,
+			tpl: '<tpl for="."><div ext:qtip="{value}" style="text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+		}
+	},
+	/*
 	 * Retrieve the closest element having the specified nodeName in the list of
 	 * ancestors of the current selection/caret.
 	 */
-	getClosest : function (nodeName) {
-		var editor = this.editor;
-		var ancestors = editor.getAllAncestors();
-		var ret = null;
-		nodeName = ("" + nodeName).toLowerCase();
-		for (var i=0; i < ancestors.length; ++i) {
-			var el = ancestors[i];
-			if (el.nodeName.toLowerCase() == nodeName) {
-				ret = el;
-				break;
+	getClosest: function (nodeName) {
+		var ancestors = this.editor.getAllAncestors();
+		var element = null;
+		Ext.each(ancestors, function (ancestor) {
+			if (ancestor.nodeName.toLowerCase() === nodeName) {
+				element = ancestor;
+				return false;
 			}
+		});
+		return element;
+	},
+	/*
+	 * Get the integer value of a string or '' if the string is not a number
+	 *
+	 * @param	string		string: the input value
+	 *
+	 * @return	mixed		a number or ''
+	 */
+	getLength: function (string) {
+		var length = parseInt(string);
+		if (isNaN(length)) {
+			length = '';
 		}
-		return ret;
+		return length;
 	},
-	
 	/*
-	 * Open the table properties dialogue
+	 * Open properties dialogue
+	 *
+	 * @param	string		type: 'cell', 'column', 'row' or 'table'
+	 * @param	string		buttonId: the buttonId of the button that was pressed
+	 *
+	 * @return 	void
 	 */
-	dialogTableProperties : function (buttonId) {
-		var tablePropertiesInitFunctRef = this.makeFunctionReference("tablePropertiesInit");
-		var insert = (buttonId === "InsertTable");
-		var arguments = {
-			buttonId	: buttonId,
-			title 		: (insert ? "Insert Table" : "Table Properties"),
-			initialize	: tablePropertiesInitFunctRef,
-			element		: (insert ? null : this.getClosest("table"))
-		};
-		var dimensions = {
-			width	: 860,
-			height	: 620
-		};
-		this.dialog = this.openDialog((insert ? "InsertTable" : "TO-table-prop"), "", "tablePropertiesUpdate", arguments, dimensions);
+	openPropertiesDialogue: function (type, buttonId) {
+			// Retrieve the element being edited and set configuration according to type
+		switch (type) {
+			case 'cell':
+			case 'column':
+				var element = this.getClosest('td');
+				if (!element) {
+					var element = this.getClosest('th');
+				}
+				this.properties = this.buttonsConfiguration.cellproperties.properties;
+				var title = (type == 'column') ? 'Column Properties' : 'Cell Properties';
+				break;
+			case 'row':
+				var element = this.getClosest('tr');
+				this.properties = this.buttonsConfiguration.rowproperties.properties;
+				var title = 'Row Properties';
+				break;
+			case 'table':
+				var insert = (buttonId === 'InsertTable');
+				var element = insert ? null : this.getClosest('table');
+				this.properties = this.buttonsConfiguration.table.properties;
+				var title = insert ? 'Insert Table' : 'Table Properties';
+				break;
+		}
+		var propertySet = element ? type + 'properties' : 'table';
+		this.removedFieldsets = (this.buttonsConfiguration[propertySet] && this.buttonsConfiguration[propertySet].removeFieldsets) ? this.buttonsConfiguration[propertySet].removeFieldsets : '';
+		this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : '';
+			// Open the dialogue window
+		this.openDialogue(
+			title,
+			{
+				element: element,
+				cell: type == 'cell',
+				column: type == 'column',
+				buttonId: buttonId
+			},
+			type == 'table' ? this.getWindowDimensions({ width: 600}, buttonId) : this.getWindowDimensions({ width: 600}, buttonId),
+			this.buildTabItemsConfig(element, type, buttonId),
+			type == 'table' ? this.tablePropertiesUpdate : this.rowCellPropertiesUpdate
+		);
 	},
-	
 	/*
-	 * Initialize the table insertion or table properties dialog
+	 * Build the dialogue tab items config
+	 *
+	 * @param	object		element: the element being edited, if any
+	 * @param	string		type: 'cell', 'column', 'row' or 'table'
+	 * @param	string		buttonId: the buttonId of the button that was pressed
+	 *
+	 * @return	object		the tab items configuration
 	 */
-	tablePropertiesInit : function(dialog) {
-		var doc = dialog.document;
-		var content = dialog.content;
-		var table = dialog.arguments.element;
-		this.removedFieldsets = this.buttonsConfiguration[table?"tableproperties":"table"].removeFieldsets ? this.buttonsConfiguration[table?"tableproperties":"table"].removeFieldsets : "";
-		this.properties = this.buttonsConfiguration.table.properties;
-		this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : "";
-		TableOperations.buildTitle(doc, content, dialog.arguments.title);
-		TableOperations.insertSpace(doc, content);
-		if (this.removedFieldsets.indexOf("description") == -1) {
-			TableOperations.buildDescriptionFieldset(doc, table, content, "floating");
+	buildTabItemsConfig: function (element, type, buttonId) {
+		var tabItems = [];
+		var generalTabItems = [];
+		switch (type) {
+			case 'table':
+				if (this.removedFieldsets.indexOf('description') === -1) {
+					this.addConfigElement(this.buildDescriptionFieldsetConfig(element), generalTabItems);
+				}
+				if (Ext.isEmpty(element) || this.removedProperties.indexOf('headers') === -1) {
+					this.addConfigElement(this.buildSizeAndHeadersFieldsetConfig(element), generalTabItems);
+				}
+				break;
+			case 'column':
+				if (this.removedFieldsets.indexOf('columntype') == -1) {
+					this.addConfigElement(this.buildCellTypeFieldsetConfig(element, true), generalTabItems);
+				}
+				break;
+			case 'cell':
+				if (this.removedFieldsets.indexOf('celltype') == -1) {
+					this.addConfigElement(this.buildCellTypeFieldsetConfig(element, false), generalTabItems);
+				}
+				break;
+			case 'row':
+				if (this.removedFieldsets.indexOf('rowgroup') == -1) {
+					this.addConfigElement(this.buildRowGroupFieldsetConfig(element), generalTabItems);
+				}
+				break;
 		}
-		if (this.removedFieldsets.indexOf("spacing") == -1) TableOperations.buildSpacingFieldset(doc, table, content);
-		TableOperations.insertSpace(doc, content);
-		this.buildSizeAndHeadersFieldset(doc, table, content, "floating");
-		if (this.removedFieldsets.indexOf("style") == -1 && dialog.editor.config.customSelects.BlockStyle) {
-			var blockStyle = dialog.editor.plugins.BlockStyle.instance;
+		if (this.removedFieldsets.indexOf('style') == -1 && this.getButton('BlockStyle')) {
+			var blockStyle = this.getPluginInstance('BlockStyle');
 			if (blockStyle && blockStyle.cssLoaded) {
-				this.buildStylingFieldset(doc, table, content, null, dialog.arguments.buttonId);
-				TableOperations.insertSpace(doc, content);
+				this.addConfigElement(this.buildStylingFieldsetConfig(element, buttonId), generalTabItems);
 			}
 		}
-		this.buildLanguageFieldset(doc, table, content, "floating");
-		if (this.removedFieldsets.indexOf("layout") == -1) this.buildLayoutFieldset(doc, table, content, "floating");
-		if (this.removedFieldsets.indexOf("alignment") == -1) this.buildAlignmentFieldset(doc, table, content);
-		TableOperations.insertSpace(doc, content);
-		if (this.removedFieldsets.indexOf("borders") == -1) this.buildBordersFieldset(dialog.dialogWindow, doc, dialog.editor, table, content);
-		if (this.removedFieldsets.indexOf("color") == -1) TableOperations.buildColorsFieldset(dialog.dialogWindow, doc, dialog.editor, table, content);
-		dialog.addButtons("ok", "cancel");
+		if (!Ext.isEmpty(generalTabItems)) {
+			tabItems.push({
+				title: this.localize('General'),
+				items: generalTabItems
+			});
+		}
+		var layoutTabItems = [];
+		if (type === 'table' && this.removedFieldsets.indexOf('spacing') === -1) {
+			this.addConfigElement(this.buildSpacingFieldsetConfig(element), layoutTabItems);
+		}
+		if (this.removedFieldsets.indexOf('layout') == -1) {
+			this.addConfigElement(this.buildLayoutFieldsetConfig(element), layoutTabItems);
+		}
+		if (!Ext.isEmpty(layoutTabItems)) {
+			tabItems.push({
+				title: this.localize('Layout'),
+				items: layoutTabItems
+			});
+		}
+		var languageTabItems = [];
+		if (this.removedFieldsets.indexOf('language') === -1 && (this.removedProperties.indexOf('language') === -1 || this.removedProperties.indexOf('direction') === -1) && (this.getButton('Language') || this.getButton('LeftToRight') || this.getButton('RightToLeft'))) {
+			this.addConfigElement(this.buildLanguageFieldsetConfig(element), languageTabItems);
+		}
+		if (!Ext.isEmpty(languageTabItems)) {
+			tabItems.push({
+				title: this.localize('Language'),
+				items: languageTabItems
+			});
+		}
+		var alignmentAndBordersTabItems = [];
+		if (this.removedFieldsets.indexOf('alignment') === -1) {
+			this.addConfigElement(this.buildAlignmentFieldsetConfig(element), alignmentAndBordersTabItems);
+		}
+		if (this.removedFieldsets.indexOf('borders') === -1) {
+			this.addConfigElement(this.buildBordersFieldsetConfig(element), alignmentAndBordersTabItems);
+		}
+		if (!Ext.isEmpty(alignmentAndBordersTabItems)) {
+			tabItems.push({
+				title: this.localize('Alignment') + '/' + this.localize('Border'),
+				items: alignmentAndBordersTabItems
+			});
+		}
+		var colorTabItems = [];
+		if (this.removedFieldsets.indexOf('color') === -1) {
+			this.addConfigElement(this.buildColorsFieldsetConfig(element), colorTabItems);
+		}
+		if (!Ext.isEmpty(colorTabItems)) {
+			tabItems.push({
+				title: this.localize('Background and colors'),
+				items: colorTabItems
+			});
+		}
+		return tabItems;
 	},
-	
 	/*
+	 * Open the dialogue window
+	 *
+	 * @param	string		title: the window title
+	 * @param	object		arguments: some arguments for the handler
+	 * @param	integer		dimensions: the opening width of the window
+	 * @param	object		tabItems: the configuration of the tabbed panel
+	 * @param	function	handler: handler when the OK button if clicked
+	 *
+	 * @return	void
+	 */
+	openDialogue: function (title, arguments, dimensions, tabItems, handler) {
+		if (this.dialog) {
+			this.dialog.close();
+		}
+		this.dialog = new Ext.Window({
+			title: this.localize(title),
+			arguments: arguments,
+			cls: 'htmlarea-window',
+				// As of ExtJS 3.1, JS error with IE when the window is resizable
+			resizable: !Ext.isIE,
+			border: false,
+			width: dimensions.width,
+			height: 'auto',
+			iconCls: arguments.buttonId,
+			listeners: {
+				close: {
+					fn: this.onClose,
+					scope: this
+				}
+			},
+			items: {
+				xtype: 'tabpanel',
+				activeTab: 0,
+				defaults: {
+					xtype: 'container',
+					layout: 'form',
+					defaults: {
+						labelWidth: 150
+					}
+				},
+				listeners: {
+					tabchange: {
+						fn: this.syncHeight,
+						scope: this
+					}
+				},
+				items: tabItems
+			},
+			buttons: [
+				this.buildButtonConfig('Cancel', this.onCancel),
+				this.buildButtonConfig('OK', handler)
+			]
+		});
+		this.show();
+	},
+	/*
 	 * Insert the table or update the table properties and close the dialogue
 	 */
-	tablePropertiesUpdate : function(dialog, params) {
+	tablePropertiesUpdate: function () {
+		this.restoreSelection()
+		var params = {};
+		var fieldTypes = ['combo', 'textfield', 'numberfield', 'checkbox', 'colorpalettefield'];
+		this.dialog.findBy(function (item) {
+			if (fieldTypes.indexOf(item.getXType()) !== -1) {
+				params[item.getItemId()] = item.getValue();
+				return true;
+			}
+			return false;
+		});
+		var errorFlag = false;
 		if (this.buttonsConfiguration.table.properties && this.buttonsConfiguration.table.properties.required) {
-			if (this.buttonsConfiguration.table.properties.required.indexOf("captionOrSummary") != -1) {
+			if (this.buttonsConfiguration.table.properties.required.indexOf('captionOrSummary') != -1) {
 				if (!/\S/.test(params.f_caption) && !/\S/.test(params.f_summary)) {
-					dialog.dialogWindow.alert(this.localize("captionOrSummary" + "-required"));
-					var el = dialog.document.getElementById("f_caption");
-					el.focus();
+					Ext.MessageBox.alert(this.localize('Error'), this.localize('captionOrSummary' + '-required'));
+					var field = this.dialog.find('itemId', 'f_caption')[0];
+					var tab = field.findParentByType('container');
+					tab.ownerCt.activate(tab);
+					field.focus();
 					return false;
 				}
 			} else {
-				var required = { "f_caption": "caption", "f_summary": "summary" };
-				for (var i in required) {
-					if (required.hasOwnProperty(i)) {
-						var el = dialog.document.getElementById(i);
-						if (!el.value && this.buttonsConfiguration.table.properties.required.indexOf(required[i]) != -1) {
-							dialog.dialogWindow.alert(this.localize(required[i] + "-required"));
-							el.focus();
-							return false;
-						}
+				var required = {
+					f_caption: 'caption',
+					f_summary: 'summary'
+				};
+				Ext.iterate(required, function (item) {
+					if (!params[item] && this.buttonsConfiguration.table.properties.required.indexOf(required[item]) != -1) {
+						Ext.MessageBox.alert(this.localize('Error'), this.localize(required[item] + '-required'));
+						var field = this.dialog.find('itemId', item)[0];
+						var tab = field.findParentByType('container');
+						tab.ownerCt.activate(tab);
+						field.focus();
+						errorFlag = true;
+						return false;
 					}
+				}, this);
+				if (errorFlag) {
+					return false;
 				}
 			}
 		}
-		var doc = dialog.editor._doc;
-		if (dialog.buttonId === "InsertTable") {
-			var required = { "f_rows": "You must enter a number of rows", "f_cols": "You must enter a number of columns" };
-			for (var i in required) {
-				if (required.hasOwnProperty(i)) {
-					var el = dialog.document.getElementById(i);
-					if (!el.value) {
-						dialog.dialogWindow.alert(this.localize(required[i]));
-						el.focus();
-						return false;
-					}
+		var doc = this.editor._doc;
+		if (this.dialog.arguments.buttonId === 'InsertTable') {
+			var required = {
+				f_rows: 'You must enter a number of rows',
+				f_cols: 'You must enter a number of columns'
+			};
+			Ext.iterate(required, function (item) {
+				if (!params[item]) {
+					Ext.MessageBox.alert(this.localize('Error'), this.localize(required[item]));
+					var field = this.dialog.find('itemId', item)[0];
+					var tab = field.findParentByType('container');
+					tab.ownerCt.activate(tab);
+					field.focus();
+					errorFlag = true;
+					return false;
 				}
+			}, this);
+			if (errorFlag) {
+				return false;
 			}
-			var table = doc.createElement("table");
-			var tbody = doc.createElement("tbody");
+			var table = doc.createElement('table');
+			var tbody = doc.createElement('tbody');
 			table.appendChild(tbody);
 			for (var i = params.f_rows; --i >= 0;) {
-				var tr = doc.createElement("tr");
+				var tr = doc.createElement('tr');
 				tbody.appendChild(tr);
 				for (var j = params.f_cols; --j >= 0;) {
-					var td = doc.createElement("td");
-					if (HTMLArea.is_gecko) td.innerHTML = "<br />";
+					var td = doc.createElement('td');
+					if (HTMLArea.is_gecko) td.innerHTML = '<br />';
 					tr.appendChild(td);
 				}
 			}
 		} else {
-			var table = dialog.arguments.element;
+			var table = this.dialog.arguments.element;
 		}
-		table = this.setHeaders(table, params);
-		table = this.processStyle(table, params);
-		table.removeAttribute("border");
-		for (var i in params) {
-			if (params.hasOwnProperty(i)) {
-				var val = params[i];
-				switch (i) {
-				    case "f_caption":
-					if (/\S/.test(val)) {
-						// contains non white-space characters
-						var caption = table.getElementsByTagName("caption");
-						if (caption) {
-							caption = caption[0];
-						}
-						if (!caption) {
-							var caption = doc.createElement("caption");
-							table.insertBefore(caption, table.firstChild);
-						}
-						caption.innerHTML = val;
-					} else {
-						// delete the caption if found
-						if (table.caption) table.deleteCaption();
+		this.setHeaders(table, params);
+		this.processStyle(table, params);
+		table.removeAttribute('border');
+		Ext.iterate(params, function (item) {
+			var val = params[item];
+			switch (item) {
+			    case "f_caption":
+				if (/\S/.test(val)) {
+					// contains non white-space characters
+					var caption = table.getElementsByTagName("caption");
+					if (caption) {
+						caption = caption[0];
 					}
-					break;
-				    case "f_summary":
-					table.summary = val;
-					break;
-				    case "f_width":
-					table.style.width = ("" + val) + params.f_unit;
-					break;
-				    case "f_align":
-					table.align = val;
-					break;
-				    case "f_spacing":
-					table.cellSpacing = val;
-					break;
-				    case "f_padding":
-					table.cellPadding = val;
-					break;
-				    case "f_frames":
-					table.frame = (val != "not set") ? val : "";
-					break;
-				    case "f_rules":
-					if (val != "not set") table.rules = val;
-						else table.removeAttribute("rules");
-					break;
-				    case "f_st_float":
-					switch (val) {
-					    case "not set":
-						HTMLArea._removeClass(table, this.floatRight);
-						HTMLArea._removeClass(table, this.floatLeft);
-						break;
-					    case "right":
-						HTMLArea._removeClass(table, this.floatLeft);
-						HTMLArea._addClass(table, this.floatRight);
-						break;
-					    case "left":
-						HTMLArea._removeClass(table, this.floatRight);
-						HTMLArea._addClass(table, this.floatLeft);
-						break;
+					if (!caption) {
+						var caption = doc.createElement("caption");
+						table.insertBefore(caption, table.firstChild);
 					}
+					caption.innerHTML = val;
+				} else {
+					// delete the caption if found
+					if (table.caption) table.deleteCaption();
+				}
+				break;
+			    case "f_summary":
+				table.summary = val;
+				break;
+			    case "f_width":
+				table.style.width = ("" + val) + params.f_unit;
+				break;
+			    case "f_align":
+				table.align = val;
+				break;
+			    case "f_spacing":
+				table.cellSpacing = val;
+				break;
+			    case "f_padding":
+				table.cellPadding = val;
+				break;
+			    case "f_frames":
+			    	    if (val !== 'not set' && table.style.borderStyle !== 'none') {
+			    	    	    table.frame = val;
+			    	    } else {
+			    	    	    table.removeAttribute('rules');
+			    	    }
+				break;
+			    case "f_rules":
+			    	    if (val !== 'not set') {
+			    	    	    table.rules = val;
+			    	    } else {
+			    	    	    table.removeAttribute('rules');
+			    	    }
+				break;
+			    case "f_st_float":
+				switch (val) {
+				    case "not set":
+					HTMLArea._removeClass(table, this.floatRight);
+					HTMLArea._removeClass(table, this.floatLeft);
 					break;
-				    case "f_st_textAlign":
-					if (this.editor.plugins.BlockElements) {
-						this.editor.plugins.BlockElements.instance.toggleAlignmentClass(table, this.convertAlignment[val]);
-						table.style.textAlign = "";
-					}
+				    case "right":
+					HTMLArea._removeClass(table, this.floatLeft);
+					HTMLArea._addClass(table, this.floatRight);
 					break;
-				    case "f_class":
-				    case "f_class_tbody":
-				    case "f_class_thead":
-				    case "f_class_tfoot":
-					var tpart = table;
-					if (i.length > 7) tpart = table.getElementsByTagName(i.substring(8,13))[0];
-					if (tpart) {
-						this.editor.plugins.BlockStyle.instance.applyClassChange(tpart, val);
-					}
+				    case "left":
+					HTMLArea._removeClass(table, this.floatRight);
+					HTMLArea._addClass(table, this.floatLeft);
 					break;
-				    case "f_lang":
-					this.getPluginInstance("Language").setLanguageAttributes(table, val);
-					break;
-				    case "f_dir":
-					table.dir = (val != "not set") ? val : "";
-					break;
 				}
+				break;
+			    case "f_st_textAlign":
+				if (this.getPluginInstance('BlockElements')) {
+					this.getPluginInstance('BlockElements').toggleAlignmentClass(table, this.convertAlignment[val]);
+					table.style.textAlign = "";
+				}
+				break;
+			    case "f_class":
+			    case "f_class_tbody":
+			    case "f_class_thead":
+			    case "f_class_tfoot":
+				var tpart = table;
+				if (item.length > 7) {
+					tpart = table.getElementsByTagName(item.substring(8,13))[0];
+				}
+				if (tpart) {
+					this.getPluginInstance('BlockStyle').applyClassChange(tpart, val);
+				}
+				break;
+			    case "f_lang":
+				this.getPluginInstance('Language').setLanguageAttributes(table, val);
+				break;
+			    case "f_dir":
+				table.dir = (val != "not set") ? val : "";
+				break;
 			}
-		}
-		if (dialog.buttonId === "InsertTable") {
-			if (HTMLArea.is_gecko) {
+		}, this);
+		if (this.dialog.arguments.buttonId === "InsertTable") {
+			if (!Ext.isIE) {
 				this.editor.insertNodeAtSelection(table);
 			} else {
 				table.id = "htmlarea_table_insert";
@@ -364,94 +570,38 @@
 				this.toggleBorders(true);
 			}
 		}
-		dialog.close();
+		this.close();
 	},
-	
 	/*
-	 * Open the row/column/cell properties dialogue
+	 * Update the row/column/cell properties
 	 */
-	dialogRowCellProperties : function (cell, column) {
-			// retrieve existing values
-		if (cell) {
-			var element = this.getClosest("td");
-			if (!element) var element = this.getClosest("th");
-		} else {
-			var element = this.getClosest("tr");
-		}
-		if (element) {
-			var rowCellPropertiesInitFunctRef = this.makeFunctionReference("rowCellPropertiesInit");
-			var arguments = {
-				title 		: (cell ? (column ? "Column Properties" : "Cell Properties") : "Row Properties"),
-				initialize	: rowCellPropertiesInitFunctRef,
-				element		: element,
-				cell		: cell,
-				column		: column
-			};
-			this.dialog = this.openDialog("TO-" + (cell ? (column ? "col-prop" : "cell-prop") :"row-prop"), "", "rowCellPropertiesUpdate", arguments, { width : 660, height : 460 });
-		}
-	},
-	
-	/*
-	 * Initialize the row/column/cell properties dialogue
-	 */
-	rowCellPropertiesInit : function(dialog) {
-		var doc = dialog.document;
-		var content = dialog.content;
-		var element = dialog.arguments.element;
-		var cell = dialog.arguments.cell;
-		var column = dialog.arguments.column;
-		this.removedFieldsets = this.buttonsConfiguration[cell?(column?"columnproperties":"cellproperties"):"rowproperties"].removeFieldsets ? this.buttonsConfiguration[cell?(column?"columnproperties":"cellproperties"):"rowproperties"].removeFieldsets : "";
-		this.properties = this.buttonsConfiguration[(cell ||column)?"cellproperties":"rowproperties"].properties;
-		this.removedProperties = (this.properties && this.properties.removed) ? this.properties.removed : "";
-		TableOperations.buildTitle(doc, content, (cell ? (column ? "Column Properties" : "Cell Properties") : "Row Properties"));
-		TableOperations.insertSpace(doc, content);
-		if (column) {
-			if (this.removedFieldsets.indexOf("columntype") == -1) this.buildCellTypeFieldset(doc, element, content, true);
-		} else if (cell) {
-			if (this.removedFieldsets.indexOf("celltype") == -1) this.buildCellTypeFieldset(doc, element, content, false);
-		} else {
-			if (this.removedFieldsets.indexOf("rowgroup") == -1) TableOperations.buildRowGroupFieldset(dialog.dialogWindow, doc, dialog.editor, element, content);
-		}
-		if (this.removedFieldsets.indexOf("style") == -1 && this.editor.config.customSelects.BlockStyle) {
-			var blockStyle = this.editor.plugins.BlockStyle.instance;
-			if (blockStyle && blockStyle.cssLoaded) {
-				this.buildStylingFieldset(doc, element, content);
-				TableOperations.insertSpace(doc, content);
-			} else {
-				TableOperations.insertSpace(doc, content);
+	rowCellPropertiesUpdate: function() {
+		this.restoreSelection()
+			// Collect values from each form field
+		var params = {};
+		var fieldTypes = ['combo', 'textfield', 'numberfield', 'checkbox', 'colorpalettefield'];
+		this.dialog.findBy(function (item) {
+			if (fieldTypes.indexOf(item.getXType()) !== -1) {
+				params[item.getItemId()] = item.getValue();
+				return true;
 			}
-		} else {
-			TableOperations.insertSpace(doc, content);
-		}
-		this.buildLanguageFieldset(doc, element, content, "floating");
-		if (this.removedFieldsets.indexOf("layout") == -1) this.buildLayoutFieldset(doc, element, content, "floating");
-		if (this.removedFieldsets.indexOf("alignment") == -1) this.buildAlignmentFieldset(doc, element, content);
-		if (this.removedFieldsets.indexOf("borders") == -1) this.buildBordersFieldset(dialog.dialogWindow, doc, dialog.editor, element, content);
-		if (this.removedFieldsets.indexOf("color") == -1) TableOperations.buildColorsFieldset(dialog.dialogWindow, doc, dialog.editor, element, content);
-		dialog.addButtons("ok", "cancel");
-	},
-	
-	/*
-	 * Update the row/column/cell properties
-	 */
-	rowCellPropertiesUpdate : function(dialog, params) {
-		var element = dialog.arguments.element;
-		var cell = dialog.arguments.cell;
-		var column = dialog.arguments.column;
-		var section = (cell || column) ? element.parentNode.parentNode : element.parentNode;
+			return false;
+		});
+		var cell = this.dialog.arguments.cell;
+		var column = this.dialog.arguments.column;
+		var section = (cell || column) ? this.dialog.arguments.element.parentNode.parentNode : this.dialog.arguments.element.parentNode;
 		var table = section.parentNode;
-		var elements = new Array();
+		var elements = [];
 		if (column) {
-			elements = this.getColumnCells(dialog.arguments.element);
+			elements = this.getColumnCells(this.dialog.arguments.element);
 		} else {
-			elements.push(dialog.arguments.element);
+			elements.push(this.dialog.arguments.element);
 		}
-		for (var k = elements.length; --k >= 0;) {
-			var element = elements[k];
-			element = this.processStyle(element, params);
-			for (var i in params) {
-				var val = params[i];
-				switch (i) {
+		Ext.each(elements, function (element) {
+			this.processStyle(element, params);
+			Ext.iterate(params, function (item) {
+				var val = params[item];
+				switch (item) {
 				    case "f_cell_type":
 					if (val.substring(0,2) != element.nodeName.toLowerCase()) {
 						element = this.remapCell(element, val.substring(0,2));
@@ -465,7 +615,7 @@
 					var nodeName = section.nodeName.toLowerCase();
 					if (val != nodeName) {
 						var newSection = table.getElementsByTagName(val)[0];
-						if (!newSection) var newSection = table.insertBefore(dialog.editor._doc.createElement(val), table.getElementsByTagName("tbody")[0]);
+						if (!newSection) var newSection = table.insertBefore(this.editor._doc.createElement(val), table.getElementsByTagName("tbody")[0]);
 						if (nodeName == "thead" && val == "tbody") var newElement = newSection.insertBefore(element, newSection.firstChild);
 							else var newElement = newSection.appendChild(element);
 						if (!section.hasChildNodes()) table.removeChild(section);
@@ -479,46 +629,52 @@
 					}
 					break;
 				    case "f_st_textAlign":
-					if (this.editor.plugins.BlockElements) {
-						this.editor.plugins.BlockElements.instance.toggleAlignmentClass(element, this.convertAlignment[val]);
+					if (this.getPluginInstance('BlockElements')) {
+						this.getPluginInstance('BlockElements').toggleAlignmentClass(element, this.convertAlignment[val]);
 						element.style.textAlign = "";
 					}
 					break;
 				    case "f_class":
-					this.editor.plugins.BlockStyle.instance.applyClassChange(element, val);
+					this.getPluginInstance('BlockStyle').applyClassChange(element, val);
 					break;
 				    case "f_lang":
-					this.getPluginInstance("Language").setLanguageAttributes(element, val);
+					this.getPluginInstance('Language').setLanguageAttributes(element, val);
 					break;
 				    case "f_dir":
 					element.dir = (val != "not set") ? val : "";
 					break;
 				}
-			}
-		}
+			}, this);
+		}, this);
 		this.reStyleTable(table);
-		dialog.close();
+		this.close();
 	},
-	
 	/*
 	 * This function gets called when the plugin is generated
-	 * Set table borders if requested by configuration
 	 */
-	onGenerate : function() {
+	onGenerate: function () {
+			// Set table borders if requested by configuration
 		if (this.buttonsConfiguration.toggleborders && this.buttonsConfiguration.toggleborders.setOnRTEOpen) {
 			this.toggleBorders(true);
 		}
+			// Register handler for the enter key for IE and Opera when buttons.table.disableEnterParagraphs is set in the editor configuration
+		if ((Ext.isIE || Ext.isOpera) && this.disableEnterParagraphs) {
+			this.editor.iframe.keyMap.addBinding({
+				key: Ext.EventObject.ENTER,
+				shift: false,
+				handler: this.onKey,
+				scope: this
+			});
+		}
 	},
-	
 	/*
 	 * This function gets called when the toolbar is being updated
 	 */
-	onUpdateToolbar : function() {
-		if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable() && this.isButtonInToolbar("TO-toggle-borders")) {
-			this.editor._toolbarObjects["TO-toggle-borders"].state("active", HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-showtableborders'));
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'TO-toggle-borders') {
+			button.setInactive(!HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-showtableborders'));
 		}
 	},
-	
 	/*
 	 * This function gets called when a Table Operations button was pressed.
 	 *
@@ -527,7 +683,7 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function (editor, id, target) {
+	onButtonPress: function (editor, id, target) {
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
@@ -858,7 +1014,7 @@
 			for (var k = tableParts.length; --k >= 0;) rows[k] = [];
 			var row = null;
 			var cells = null;
-			if (HTMLArea.is_gecko && !HTMLArea.is_safari && !HTMLArea.is_opera) {
+			if (Ext.isGecko) {
 				try {
 					while (range = sel.getRangeAt(i++)) {
 						var td = range.startContainer.childNodes[range.startOffset];
@@ -878,7 +1034,7 @@
 				var cell = this.getClosest("td");
 				if (!cell) var cell = this.getClosest("th");
 				if (!cell) {
-					alert(this.localize("Please click into some cell"));
+					Ext.MessageBox.alert('', this.localize("Please click into some cell"));
 					break;
 				}
 				var tr = cell.parentElement;
@@ -956,19 +1112,19 @@
 			// CREATION AND PROPERTIES
 		    case "InsertTable":
 		    case "TO-table-prop":
-			this.dialogTableProperties(buttonId);
+		    	this.openPropertiesDialogue('table', buttonId);
 			break;
 		    case "TO-table-restyle":
-			this.reStyleTable(this.getClosest("table"));
+			this.reStyleTable(this.getClosest('table'));
 			break;
 		    case "TO-row-prop":
-			this.dialogRowCellProperties(false, false);
+		    	this.openPropertiesDialogue('row', buttonId);
 			break;
 		    case "TO-col-prop":
-			this.dialogRowCellProperties(true, true);
+		    	this.openPropertiesDialogue('column', buttonId);
 			break;
 		    case "TO-cell-prop":
-			this.dialogRowCellProperties(true, false);
+		    	this.openPropertiesDialogue('cell', buttonId);
 			break;
 		    case "TO-toggle-borders":
 			this.toggleBorders();
@@ -977,7 +1133,6 @@
 			alert("Button [" + buttonId + "] not yet implemented");
 		}
 	},
-	
 	/*
 	 * Returns an array of all cells in the column containing the given cell
 	 *
@@ -1002,7 +1157,6 @@
 		}
 		return cells;
 	},
-	
 	/*
 	 * Toggles the display of borders on tables and table cells
 	 *
@@ -1018,7 +1172,6 @@
 			HTMLArea._removeClass(body,'htmlarea-showtableborders');
 		}
 	},
-	
 	/*
 	 * Applies to rows/cells the alternating and counting classes of an alternating or counting style scheme
 	 *
@@ -1058,7 +1211,6 @@
 			}
 		}
 	},
-	
 	/*
 	 * Removes from rows/cells the alternating classes of an alternating style scheme
 	 *
@@ -1083,7 +1235,6 @@
 			}
 		}
 	},
-	
 	/*
 	 * Applies/removes the alternating classes of an alternating rows style scheme
 	 *
@@ -1124,7 +1275,6 @@
 			}
 		}
 	},
-	
 	/*
 	 * Applies/removes the alternating classes of an alternating columns style scheme
 	 *
@@ -1168,8 +1318,7 @@
 				}
 			}
 		}
-	},
-	
+	},	
 	/*
 	 * Removes from rows/cells the counting classes of an counting style scheme
 	 *
@@ -1194,7 +1343,6 @@
 			}
 		}
 	},
-
 	/*
 	 * Applies/removes the counting classes of an counting rows style scheme
 	 *
@@ -1241,7 +1389,6 @@
 			}
 		}
 	},
-
 	/*
 	 * Applies/removes the counting classes of a counting columns style scheme
 	 *
@@ -1292,16 +1439,15 @@
 			}
 		}
 	},
-
 	/*
 	 * This function sets the headers cells on the table (top, left, both or none)
 	 *
 	 * @param	object		table: the table being edited
 	 * @param	object		params: the field values entered in the form
 	 *
-	 * @return	object		the modified table
+	 * @return	void
 	 */
-	setHeaders : function (table, params) {
+	setHeaders: function (table, params) {
 		var headers = params.f_headers;
 		var doc = this.editor._doc;
 		var tbody = table.tBodies[0];
@@ -1371,7 +1517,6 @@
 			}
 		}
 		this.reStyleTable(table);
-		return table;
 	},
 	
 	/*
@@ -1442,9 +1587,9 @@
 	 * @param	object		element: the element
 	 * @param	object		params: the properties
 	 *
-	 * @return	object		the modified element
+	 * @return	void
 	 */
-	processStyle : function (element, params) {
+	processStyle: function (element, params) {
 		var style = element.style;
 		if (HTMLArea.is_ie) {
 			style.styleFloat = "";
@@ -1457,10 +1602,10 @@
 				var val = params[i];
 				switch (i) {
 				    case "f_st_backgroundColor":
-					style.backgroundColor = val;
+				    	style.backgroundColor = ((val.charAt(0) === '#') ? '' : '#') + val;
 					break;
 				    case "f_st_color":
-					style.color = val;
+					style.color = ((val.charAt(0) === '#') ? '' : '#') + val;
 					break;
 				    case "f_st_backgroundImage":
 					if (/\S/.test(val)) {
@@ -1482,10 +1627,16 @@
 					style.borderStyle = (val != "not set") ? val : "";
 					break;
 				    case "f_st_borderColor":
-					style.borderColor = val;
+					style.borderColor = ((val.charAt(0) === '#') ? '' : '#') + val;
+					if (params.f_st_borderStyle === 'none') {
+						style.borderColor = '';
+					}
 					break;
 				    case "f_st_borderCollapse":
-					style.borderCollapse = val ? "collapse" : "";
+					style.borderCollapse = (val !== 'not set') ? val : '';
+					if (params.f_st_borderStyle === 'none') {
+						style.borderCollapse = '';
+					}
 					break;
 				    case "f_st_width":
 					if (/\S/.test(val)) {
@@ -1510,610 +1661,888 @@
 				}
 			}
 		}
-		return element;
 	},
-	
 	/*
-	 * This function creates a Size and Headers fieldset to be added to the form
+	 * This function builds the configuration object for the table Description fieldset
 	 *
-	 * @param	object		doc: the dialog document
-	 * @param	object		table: the table being edited
-	 * @param	object		content: the content div of the dialog window
+	 * @param	object		table: the table being edited, if any
 	 *
-	 * @return	void
+	 * @return	object		the fieldset configuration object
 	 */
-	buildSizeAndHeadersFieldset : function (doc, table, content, fieldsetClass) {
-		if (!table || this.removedProperties.indexOf("headers") == -1) {
-			var fieldset = doc.createElement("fieldset");
-			if (fieldsetClass) fieldset.className = fieldsetClass;
-			if (!table) {
-				TableOperations.insertLegend(doc, fieldset, "Size and Headers");
-				TableOperations.buildInput(doc, fieldset, "f_rows", "Rows:", "Number of rows", "", "5", ((this.properties && this.properties.numberOfRows && this.properties.numberOfRows.defaultValue) ? this.properties.numberOfRows.defaultValue : "2"), "fr");
-				TableOperations.insertSpace(doc, fieldset);
-				TableOperations.buildInput(doc, fieldset, "f_cols", "Cols:", "Number of columns", "", "5", ((this.properties && this.properties.numberOfColumns && this.properties.numberOfColumns.defaultValue) ? this.properties.numberOfColumns.defaultValue : "4"), "fr");
+	buildDescriptionFieldsetConfig: function (table) {
+		if (!Ext.isEmpty(table)) {
+			var caption = table.getElementsByTagName('caption')[0];
+		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Description'),
+			defaultType: 'textfield',
+			defaults: {
+				labelSeparator: '',
+				helpIcon: true
+			},
+			items: [{
+				fieldLabel: this.localize('Caption:'),
+				itemId: 'f_caption',
+				value: Ext.isDefined(caption) ? caption.innerHTML : '',
+				width: 300,
+				helpTitle: this.localize('Description of the nature of the table')
+			    	},{
+				fieldLabel: this.localize('Summary:'),
+				itemId: 'f_summary',
+				value: !Ext.isEmpty(table) ? table.summary : '',
+				width: 300,
+				helpTitle: this.localize('Summary of the table purpose and structure')
+			}]
+		};
+	},
+	/*
+	 * This function builds the configuration object for the table Size and Headers fieldset
+	 *
+	 * @param	object		table: the table being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildSizeAndHeadersFieldsetConfig: function (table) {
+		var itemsConfig = [];
+		if (Ext.isEmpty(table)) {
+			itemsConfig.push({
+				fieldLabel: this.localize('Rows:'),
+				labelSeparator: '',
+				itemId: 'f_rows',
+				value: (this.properties && this.properties.numberOfRows && this.properties.numberOfRows.defaultValue) ? this.properties.numberOfRows.defaultValue : '2',
+				width: 30,
+				minValue: 1,
+				helpTitle: this.localize('Number of rows')
+			});
+			itemsConfig.push({
+				fieldLabel: this.localize('Cols:'),
+				labelSeparator: '',
+				itemId: 'f_cols',
+				value: (this.properties && this.properties.numberOfColumns && this.properties.numberOfColumns.defaultValue) ? this.properties.numberOfColumns.defaultValue : '4',
+				width: 30,
+				minValue: 1,
+				helpTitle: this.localize('Number of columns')
+			});
+		}
+		if (this.removedProperties.indexOf('headers') == -1) {
+				// Create combo store
+			var store = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('No header cells'), 'none'],
+					[this.localize('Header cells on top'), 'top'],
+					[this.localize('Header cells on left'), 'left'],
+					[this.localize('Header cells on top and left'), 'both']
+				]
+			});
+			this.removeOptions(store, 'headers');
+			if (Ext.isEmpty(table)) {
+				var selected = (this.properties && this.properties.headers && this.properties.headers.defaultValue) ? this.properties.headers.defaultValue : 'top';
 			} else {
-				TableOperations.insertLegend(doc, fieldset, "Headers");
-			}
-			if (this.removedProperties.indexOf("headers") == -1) {
-				var ul = doc.createElement("ul");
-				fieldset.appendChild(ul);
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				if (!table) {
-					var selected = (this.properties && this.properties.headers && this.properties.headers.defaultValue) ? this.properties.headers.defaultValue : "top";
-				} else {
-					var selected = "none";
-					var thead = table.getElementsByTagName("thead");
-					var tbody = table.getElementsByTagName("tbody");
-					if (thead.length && thead[0].rows.length) {
-						selected = "top";
-					} else if (tbody.length && tbody[0].rows.length) {
-						if (HTMLArea._hasClass(tbody[0].rows[0], this.useHeaderClass)) {
-							selected = "both";
-						} else if (tbody[0].rows[0].cells.length && tbody[0].rows[0].cells[0].nodeName.toLowerCase() == "th") {
-							selected = "left";
-						}
+				var selected = 'none';
+				var thead = table.getElementsByTagName('thead');
+				var tbody = table.getElementsByTagName('tbody');
+				if (thead.length && thead[0].rows.length) {
+					selected = 'top';
+				} else if (tbody.length && tbody[0].rows.length) {
+					if (HTMLArea._hasClass(tbody[0].rows[0], this.useHeaderClass)) {
+						selected = 'both';
+					} else if (tbody[0].rows[0].cells.length && tbody[0].rows[0].cells[0].nodeName.toLowerCase() == 'th') {
+						selected = 'left';
 					}
 				}
-				var selectHeaders = TableOperations.buildSelectField(doc, li, "f_headers", "Headers:", "fr", "floating", "Table headers", ["No header cells", "Header cells on top", "Header cells on left", "Header cells on top and left"], ["none", "top", "left", "both"],  new RegExp((selected ? selected : "top"), "i"));
-				this.removeOptions(selectHeaders, "headers");
 			}
-			TableOperations.insertSpace(doc, fieldset);
-			content.appendChild(fieldset);
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Headers:'),
+				itemId: 'f_headers',
+				helpTitle: this.localize('Table headers'),
+				store: store,
+				width: (this.properties && this.properties['headers'] && this.properties['headers'].width) ? this.properties['headers'].width : 200,
+				value: selected
+			}, this.configDefaults['combo']));
 		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize(Ext.isEmpty(table) ? 'Size and Headers' : 'Headers'),
+			defaultType: 'numberfield',
+			defaults: {
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
 	},
-	
-	buildLayoutFieldset : function(doc, el, content, fieldsetClass) {
-		var select, selected;
-		var fieldset = doc.createElement("fieldset");
-		if (fieldsetClass) fieldset.className = fieldsetClass;
-		TableOperations.insertLegend(doc, fieldset, "Layout");
-		var f_st_width = el ? TableOperations.getLength(el.style.width) : ((this.properties && this.properties.width && this.properties.width.defaultValue) ? this.properties.width.defaultValue : "");
-		var f_st_height = el ? TableOperations.getLength(el.style.height) : ((this.properties && this.properties.height && this.properties.height.defaultValue) ? this.properties.height.defaultValue : "");
-		var selectedWidthUnit = el ? (/%/.test(el.style.width) ? '%' : (/px/.test(el.style.width) ? 'px' : 'em')) : ((this.properties && this.properties.widthUnit &&this.properties.widthUnit.defaultValue) ? this.properties.widthUnit.defaultValue : "%");
-		var selectedHeightUnit = el ? (/%/.test(el.style.height) ? '%' : (/px/.test(el.style.height) ? 'px' : 'em')) : ((this.properties && this.properties.heightUnit &&this.properties.heightUnit.defaultValue) ? this.properties.heightUnit.defaultValue : "%");
-		var nodeName = el ? el.nodeName.toLowerCase() : "table";
-		var ul = doc.createElement("ul");
-		fieldset.appendChild(ul);
-		switch(nodeName) {
-			case "table" :
-				var widthTitle = "Table width";
-				var heightTitle = "Table height";
-				break;
-			case "tr" :
-				var widthTitle = "Row width";
-				var heightTitle = "Row height";
-				break;
-			case "td" :
-			case "th" :
-				var widthTitle = "Cell width";
-				var heightTitle = "Cell height";
+	/*
+	 * This function builds the configuration object for the Style fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 * @param	string		buttonId: the id of the button that was pressed
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildStylingFieldsetConfig: function (element, buttonId) {
+		var itemsConfig = [];
+		var nodeName = element ? element.nodeName.toLowerCase() : 'table';
+		var table = (nodeName == 'table');
+		var select = this.buildStylingFieldConfig('f_class', (table ? 'Table class:' : 'Class:'), (table ? 'Table class selector' : 'Class selector'));
+		this.setStyleOptions(select, element, nodeName, (buttonId === 'InsertTable') ? this.defaultClass : null);
+		itemsConfig.push(select);
+		if (element && table) {
+			var tbody = element.getElementsByTagName('tbody')[0];
+			if (tbody) {
+				var tbodyStyleSelect = this.buildStylingFieldConfig('f_class_tbody', 'Table body class:', 'Table body class selector');
+				this.setStyleOptions(tbodyStyleSelect, tbody, 'tbody');
+				itemsConfig.push(tbodyStyleSelect);
+			}
+			var thead = element.getElementsByTagName('thead')[0];
+			if (thead) {
+				var theadStyleSelect = this.buildStylingFieldConfig('f_class_thead', 'Table header class:', 'Table header class selector');
+				this.setStyleOptions(theadStyleSelect, thead, 'thead');
+				itemsConfig.push(theadStyleSelect);
+			}
+			var tfoot = element.getElementsByTagName('tfoot')[0];
+			if (tfoot) {
+				var tfootStyleSelect = this.buildStylingFieldConfig('f_class_tfoot', 'Table footer class:', 'Table footer class selector');
+				this.setStyleOptions(tfootStyleSelect, tfoot, 'tfoot');
+				itemsConfig.push(tfootStyleSelect);
+			}
 		}
-		if (this.removedProperties.indexOf("width") == -1) {
-			var li = doc.createElement("li");
-			ul.appendChild(li);
-			TableOperations.buildInput(doc, li, "f_st_width", "Width:", widthTitle, "", "5", f_st_width, "fr");
-			select = TableOperations.buildSelectField(doc, li, "f_st_widthUnit", "", "", "", "Width unit", ["percent", "pixels", "em"], ["%", "px", "em"], new RegExp((selectedWidthUnit ? selectedWidthUnit : "%"), "i"));
-			this.removeOptions(select, "widthUnit");
-		}
-		if (this.removedProperties.indexOf("height") == -1) {
-			var li = doc.createElement("li");
-			ul.appendChild(li);
-			TableOperations.buildInput(doc, li, "f_st_height", "Height:", heightTitle, "", "5", f_st_height, "fr");
-			select = TableOperations.buildSelectField(doc, li, "f_st_heightUnit", "", "", "", "Height unit", ["percent", "pixels", "em"], ["%", "px", "em"], new RegExp((selectedHeightUnit ? selectedHeightUnit : "%"), "i"));
-			this.removeOptions(select, "heightUnit");
-		}
-		if (nodeName == "table" && this.removedProperties.indexOf("float") == -1) {
-			selected = el ? (HTMLArea._hasClass(el, this.floatLeft) ? "left" : (HTMLArea._hasClass(el, this.floatRight) ? "right" : "not set")) : this.floatDefault;
-			select = TableOperations.buildSelectField(doc, li, "f_st_float", "Float:", "", "", "Specifies where the table should float", ["Not set", "Left", "Right"], ["not set", "left", "right"], new RegExp((selected ? selected : "not set"), "i"));
-			this.removeOptions(select, "float");
-		}
-		content.appendChild(fieldset);
+		return {
+			xtype: 'fieldset',
+			defaults: {
+				labelSeparator: ''
+			},
+			title: this.localize('CSS Style'),
+			items: itemsConfig
+		};
 	},
-	
-	setStyleOptions : function (doc, dropDown, el, nodeName, defaultClass) {
-		if (!dropDown) return false;
-		if (this.editor.config.customSelects.BlockStyle) {
-			var blockStyle = this.editor.plugins.BlockStyle.instance;
-			if (!blockStyle || !blockStyle.cssLoaded) return false;
+	/*
+	 * This function builds a style selection field
+	 *
+	 * @param	string		fieldName: the name of the field
+	 * @param	string		fieldLabel: the label for the field
+	 * @param	string		fieldTitle: the title for the field tooltip
+	 *
+	 * @return	object		the style selection field object
+	 */
+	buildStylingFieldConfig: function(fieldName, fieldLabel, fieldTitle) {
+		return new Ext.form.ComboBox(Ext.apply({
+			xtype: 'combo',
+			itemId: fieldName,
+			fieldLabel: this.localize(fieldLabel),
+			helpTitle: this.localize(fieldTitle),
+			width: (this.properties && this.properties['style'] && this.properties['style'].width) ? this.properties['style'].width : 300,
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ],
+				data: [[this.localize('No block style'), 'none']]
+			}),
+			}, {
+			tpl: '<tpl for="."><div ext:qtip="{value}" style="{style}text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
+			}, this.configDefaults['combo']
+		));
+	},
+	/*
+	 * This function populates the style store and sets the selected option
+	 *
+	 * @param	object:		dropDown: the combobox object
+	 * @param	object		element: the element being edited, if any
+	 * @param	string		nodeName: the type of element ('table' on table insertion)
+	 * @param	string		defaultClass: default class, if any is configured
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	setStyleOptions: function (dropDown, element, nodeName, defaultClass) {
+		var blockStyle = this.getPluginInstance('BlockStyle');
+		if (dropDown && blockStyle && blockStyle.cssLoaded) {
 			if (defaultClass) {
 				var classNames = new Array();
 				classNames.push(defaultClass);
 			} else {
-				var classNames = blockStyle.getClassNames(el);
+				var classNames = blockStyle.getClassNames(element);
 			}
 			blockStyle.buildDropDownOptions(dropDown, nodeName);
-			blockStyle.setSelectedOption(dropDown, classNames, "noUnknown", defaultClass);
+			blockStyle.setSelectedOption(dropDown, classNames, 'noUnknown', defaultClass);
 		}
 	},
-	
-	buildStylingFieldset : function (doc, el, content, fieldsetClass, buttonId) {
-		var nodeName = el ? el.nodeName.toLowerCase() : "table";
-		var table = (nodeName == "table");
-		var fieldset = doc.createElement("fieldset");
-		if (fieldsetClass) fieldset.className = fieldsetClass;
-		TableOperations.insertLegend(doc, fieldset, "CSS Style");
-		TableOperations.insertSpace(doc, fieldset);
-		var ul = doc.createElement("ul");
-		ul.className = "floating";
-		fieldset.appendChild(ul);
-		var li = doc.createElement("li");
-		ul.appendChild(li);
-		var select = TableOperations.buildSelectField(doc, li, "f_class", (table ? "Table class:" : "Class:"), "fr", "", (table ? "Table class selector" : "Class selector"), new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false);
-		this.setStyleOptions(doc, select, el, nodeName, (buttonId === "InsertTable") ? this.defaultClass : null);
-		if (el && table) {
-			var tbody = el.getElementsByTagName("tbody")[0];
-			if (tbody) {
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				var select = TableOperations.buildSelectField(doc, li, "f_class_tbody", "Table body class:", "fr", "", "Table body class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false);
-				this.setStyleOptions(doc, select, tbody, "tbody");
+	/*
+	 * This function builds the configuration object for the Language fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildLanguageFieldsetConfig: function (element) {
+		var itemsConfig = [];
+		var languageObject = this.getPluginInstance('Language');
+		if (this.removedProperties.indexOf('language') == -1 && this.getButton('Language')) {
+			var languageStore = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'} ],
+				data: this.getDropDownConfiguration('Language').options
+			});
+			var selectedLanguage = !Ext.isEmpty(element) ? languageObject.getLanguageAttribute(element) : 'none';
+			if (selectedLanguage !== 'none') {
+				languageStore.removeAt(0);
+				languageStore.insert(0, new languageStore.recordType({
+					text: languageObject.localize('Remove language mark'),
+					value: 'none'
+				}));
 			}
-			var thead = el.getElementsByTagName("thead")[0];
-			if (thead) {
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				var select = TableOperations.buildSelectField(doc, li, "f_class_thead", "Table header class:", "fr", "", "Table header class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false);
-				this.setStyleOptions(doc, select, thead, "thead");
-			}
-			var tfoot = el.getElementsByTagName("tfoot")[0];
-			if (tfoot) {
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				var select = TableOperations.buildSelectField(doc, li, "f_class_tfoot", "Table footer class:", "fr", "", "Table footer class selector", new Array("undefined"), new Array("none"), new RegExp("none", "i"), "", false);
-				this.setStyleOptions(doc, select, tfoot, "tfoot");
-			}
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Language'),
+				itemId: 'f_lang',
+				helpTitle: this.localize('Language'),
+				store: languageStore,
+				width: (this.properties && this.properties['language'] && this.properties['language'].width) ? this.properties['language'].width : 200,
+				value: selectedLanguage
+			}, this.configDefaults['combo']));
 		}
-		TableOperations.insertSpace(doc, fieldset);
-		content.appendChild(fieldset);
+		if (this.removedProperties.indexOf('direction') == -1 && (this.getButton('LeftToRight') || this.getButton('RightToLeft'))) {
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Text direction'),
+				itemId: 'f_dir',
+				helpTitle: this.localize('Text direction'),
+				store: new Ext.data.ArrayStore({
+					autoDestroy:  true,
+					fields: [ { name: 'text'}, { name: 'value'}],
+					data: [
+						[this.localize('Not set'), 'not set'],
+						[this.localize('RightToLeft'), 'rtl'],
+						[this.localize('LeftToRight'), 'ltr']
+					]
+				}),
+				width: (this.properties && this.properties['direction'] && this.properties['dirrection'].width) ? this.properties['direction'].width : 200,
+				value: !Ext.isEmpty(element) && element.dir ? element.dir : 'not set'
+			}, this.configDefaults['combo']));
+		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Language'),
+			items: itemsConfig
+		};
 	},
-	
-	buildLanguageFieldset : function (doc, el, content, fieldsetClass) {
-		if (this.removedFieldsets.indexOf("language") == -1 && (this.removedProperties.indexOf("language") == -1 || this.removedProperties.indexOf("direction") == -1) && this.getPluginInstance("Language") && (this.isButtonInToolbar("Language") || this.isButtonInToolbar("LeftToRight") || this.isButtonInToolbar("RightToLeft"))) {
-			var languageObject = this.getPluginInstance("Language");
-			var fieldset = doc.createElement("fieldset");
-			if (fieldsetClass) {
-				fieldset.className = fieldsetClass;
-			}
-			TableOperations.insertLegend(doc, fieldset, "Language");
-			var ul = doc.createElement("ul");
-			fieldset.appendChild(ul);
-			if (this.removedProperties.indexOf("language") == -1 && this.isButtonInToolbar("Language")) {
-				var languageOptions = this.getDropDownConfiguration("Language").options;
-				var select,
-					selected = "",
-					options = new Array(),
-					values = new Array();
-				for (var option in languageOptions) {
-					if (languageOptions.hasOwnProperty(option)) {
-						options.push(option);
-						values.push(languageOptions[option]);
-					}
+	/*
+	 * This function builds the configuration object for the spacing fieldset
+	 *
+	 * @param	object		table: the table being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildSpacingFieldsetConfig: function (table) {
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Spacing and padding'),
+			defaultType: 'numberfield',
+			defaults: {
+				labelSeparator: '',
+				helpIcon: true
+			},
+			items: [{
+				fieldLabel: this.localize('Cell spacing:'),
+				itemId: 'f_spacing',
+				value: !Ext.isEmpty(table) ? table.cellSpacing : '',
+				width: 30,
+				minValue: 0,
+				helpTitle: this.localize('Space between adjacent cells')
+				},{
+				fieldLabel: this.localize('Cell padding:'),
+				itemId: 'f_padding',
+				value: !Ext.isEmpty(table) ? table.cellPadding : '',
+				width: 30,
+				minValue: 0,
+				helpTitle: this.localize('Space between content and border in cell')
+			}]
+		};
+	},
+	/*
+	 * This function builds the configuration object for the Layout fieldset
+	 *
+	 * @param	object		table: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildLayoutFieldsetConfig: function(element) {
+		var itemsConfig = [];
+		var nodeName = element ? element.nodeName.toLowerCase() : 'table';
+		switch(nodeName) {
+			case 'table' :
+				var widthTitle = 'Table width';
+				var heightTitle = 'Table height';
+				break;
+			case 'tr' :
+				var widthTitle = 'Row width';
+				var heightTitle = 'Row height';
+				break;
+			case 'td' :
+			case 'th' :
+				var widthTitle = 'Cell width';
+				var heightTitle = 'Cell height';
+		}
+		if (this.removedProperties.indexOf('width') === -1) {
+			var widthUnitStore = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('percent'), '%'],
+					[this.localize('pixels'), 'px'],
+					[this.localize('em'), 'em']
+				]
+			});
+			this.removeOptions(widthUnitStore, 'widthUnit');
+			itemsConfig.push({
+				fieldLabel: this.localize('Width:'),
+				labelSeparator: '',
+				itemId: 'f_st_width',
+				value: element ? this.getLength(element.style.width) : ((this.properties && this.properties.width && this.properties.width.defaultValue) ? this.properties.width.defaultValue : ''),
+				width: 30,
+				helpTitle: this.localize(widthTitle)
+			});
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Width unit'),
+				itemId: 'f_st_widthUnit',
+				helpTitle: this.localize('Width unit'),
+				store: widthUnitStore,
+				width: (this.properties && this.properties['widthUnit'] && this.properties['widthUnit'].width) ? this.properties['widthUnit'].width : 60,
+				value: element ? (/%/.test(element.style.width) ? '%' : (/px/.test(element.style.width) ? 'px' : 'em')) : ((this.properties && this.properties.widthUnit &&this.properties.widthUnit.defaultValue) ? this.properties.widthUnit.defaultValue : '%')
+			}, this.configDefaults['combo']));
+		}
+		if (this.removedProperties.indexOf('height') === -1) {
+			var heightUnitStore = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('percent'), '%'],
+					[this.localize('pixels'), 'px'],
+					[this.localize('em'), 'em']
+				]
+			});
+			this.removeOptions(heightUnitStore, 'heightUnit');
+			itemsConfig.push({
+				fieldLabel: this.localize('Height:'),
+				labelSeparator: '',
+				itemId: 'f_st_height',
+				value: element ? this.getLength(element.style.height) : ((this.properties && this.properties.height && this.properties.height.defaultValue) ? this.properties.height.defaultValue : ''),
+				width: 30,
+				helpTitle: this.localize(heightTitle)
+			});
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Height unit'),
+				itemId: 'f_st_heightUnit',
+				helpTitle: this.localize('Height unit'),
+				store: heightUnitStore,
+				width: (this.properties && this.properties['heightUnit'] && this.properties['heightUnit'].width) ? this.properties['heightUnit'].width : 60,
+				value: element ? (/%/.test(element.style.height) ? '%' : (/px/.test(element.style.height) ? 'px' : 'em')) : ((this.properties && this.properties.heightUnit &&this.properties.heightUnit.defaultValue) ? this.properties.heightUnit.defaultValue : '%')
+			}, this.configDefaults['combo']));
+		}
+		if (nodeName == 'table' && this.removedProperties.indexOf('float') === -1) {
+			var floatStore = new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('Not set'), 'not set'],
+					[this.localize('Left'), 'left'],
+					[this.localize('Right'), 'right']
+				]
+			});
+			this.removeOptions(floatStore, 'float');
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Float:'),
+				labelSeparator: '',
+				itemId: 'f_st_float',
+				helpTitle: this.localize('Specifies where the table should float'),
+				store: floatStore,
+				width: (this.properties && this.properties['float'] && this.properties['float'].width) ? this.properties['float'].width : 120,
+				value: element ? (Ext.get(element).hasClass(this.floatLeft) ? 'left' : (Ext.get(element).hasClass(this.floatRight) ? 'right' : 'not set')) : this.floatDefault
+			}, this.configDefaults['combo']));
+		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Layout'),
+			defaultType: 'numberfield',
+			defaults: {
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * This function builds the configuration object for the Layout fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildAlignmentFieldsetConfig: function (element) {
+		var itemsConfig = [];
+			// Text alignment
+		var selectedTextAlign = 'not set';
+		var blockElements = this.getPluginInstance('BlockElements');
+		if (element && blockElements) {
+			Ext.iterate(this.convertAlignment, function (value) {
+				if (Ext.get(element).hasClass(blockElements.useClass[this.convertAlignment[value]])) {
+					selectedTextAlign = value;
+					return false;
 				}
-				selected = el ? languageObject.getLanguageAttribute(el) : "none";
-				if (selected != "none") {
-					options[0] = languageObject.localize("Remove language mark");
+				return true;
+			}, this);
+		} else {
+			selectedTextAlign = (element && element.style.textAlign) ? element.style.textAlign : 'not set';
+		}
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			fieldLabel: this.localize('Text alignment:'),
+			itemId: 'f_st_textAlign',
+			helpTitle: this.localize('Horizontal alignment of text within cell'),
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('Not set'), 'not set'],
+					[this.localize('Left'), 'left'],
+					[this.localize('Center'), 'center'],
+					[this.localize('Right'), 'right'],
+					[this.localize('Justify'), 'justify']
+				]
+			}),
+			width: (this.properties && this.properties['textAlign'] && this.properties['textAlign'].width) ? this.properties['textAlign'].width : 100,
+			value: selectedTextAlign
+		}, this.configDefaults['combo']));
+			// Vertical alignment
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			fieldLabel: this.localize('Vertical alignment:'),
+			itemId: 'f_st_vertAlign',
+			helpTitle: this.localize('Vertical alignment of content within cell'),
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('Not set'), 'not set'],
+					[this.localize('Top'), 'top'],
+					[this.localize('Middle'), 'middle'],
+					[this.localize('Bottom'), 'bottom'],
+					[this.localize('Baseline'), 'baseline']
+				]
+			}),
+			width: (this.properties && this.properties['verticalAlign'] && this.properties['verticalAlign'].width) ? this.properties['verticalAlign'].width : 100,
+			value: (element && element.style.verticalAlign) ? element.style.verticalAlign : 'not set'
+		}, this.configDefaults['combo']));
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Alignment'),
+			defaults: {
+				labelSeparator: ''
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * This function builds the configuration object for the Borders fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildBordersFieldsetConfig: function (element) {
+		var itemsConfig = [];
+		var nodeName = element ? element.nodeName.toLowerCase() : 'table';
+			// Border style
+		var borderStyleStore = new Ext.data.ArrayStore({
+			autoDestroy:  true,
+			fields: [ { name: 'text'}, { name: 'value'}],
+			data: [
+				[this.localize('Not set'), 'not set'],
+				[this.localize('No border'), 'none'],
+				[this.localize('Dotted'), 'dotted'],
+				[this.localize('Dashed'), 'dashed'],
+				[this.localize('Solid'), 'solid'],
+				[this.localize('Double'), 'double'],
+				[this.localize('Groove'), 'groove'],
+				[this.localize('Ridge'), 'ridge'],
+				[this.localize('Inset'), 'inset'],
+				[this.localize('Outset'), 'outset']
+			]
+		});
+		this.removeOptions(borderStyleStore, 'borderStyle');
+			// Gecko reports "solid solid solid solid" for "border-style: solid".
+			// That is, "top right bottom left" -- we only consider the first value.
+		var selectedBorderStyle = element && element.style.borderStyle ? element.style.borderStyle : ((this.properties && this.properties.borderWidth) ? ((this.properties.borderStyle && this.properties.borderStyle.defaultValue) ? this.properties.borderStyle.defaultValue : 'solid') : 'not set');
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			fieldLabel: this.localize('Border style:'),
+			itemId: 'f_st_borderStyle',
+			helpTitle: this.localize('Border style'),
+			store: borderStyleStore,
+			width: (this.properties && this.properties.borderStyle && this.properties.borderStyle.width) ? this.properties.borderStyle.width : 150,
+			value: selectedBorderStyle,
+			listeners: {
+				change: {
+					fn: this.setBorderFieldsDisabled
 				}
-				(selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1);
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				select = TableOperations.buildSelectField(doc, li, "f_lang", "Language:", "fr", "", "Language", options, values, new RegExp((selected ? selected : "none"), "i"));
 			}
-			if (this.removedProperties.indexOf("direction") == -1 && (this.isButtonInToolbar("LeftToRight") || this.isButtonInToolbar("RightToLeft"))) {
-				var li = doc.createElement("li");
-				ul.appendChild(li);
-				selected = el ? el.dir : "";
-				(selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1);
-				select = TableOperations.buildSelectField(doc, li, "f_dir", "Text direction:", "fr", "", "Text direction", ["Not set", "Right to left", "Left to right"], ["not set", "rtl", "ltr"], new RegExp((selected ? selected : "not set"), "i"));
-			}
-			content.appendChild(fieldset);
+		}, this.configDefaults['combo']));
+			// Border width
+		itemsConfig.push({
+			fieldLabel: this.localize('Border width:'),
+			itemId: 'f_st_borderWidth',
+			value: element ? this.getLength(element.style.borderWidth) : ((this.properties && this.properties.borderWidth && this.properties.borderWidth.defaultValue) ? this.properties.borderWidth.defaultValue : ''),
+			width: 30,
+			minValue: 0,
+			helpTitle: this.localize('Border width'),
+			helpText: this.localize('pixels'),
+			disabled: (selectedBorderStyle === 'none')
+		});
+			// Border color
+		itemsConfig.push({
+			xtype: 'colorpalettefield',
+			fieldLabel: this.localize('Color:'),
+			itemId: 'f_st_borderColor',
+			colorsConfiguration: this.editorConfiguration.colors,
+			value: HTMLArea.util.Color.colorToHex(element && element.style.borderColor ? element.style.borderColor : ((this.properties && this.properties.borderColor && this.properties.borderColor.defaultValue) ? this.properties.borderColor.defaultValue : '')).substr(1, 6),
+			helpTitle: this.localize('Border color'),
+			disabled: (selectedBorderStyle === 'none')
+		});
+		if (nodeName === 'table') {
+				// Collapsed borders
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Collapsed borders'),
+				labelSeparator: ':',
+				itemId: 'f_st_borderCollapse',
+				helpTitle: this.localize('Collapsed borders'),
+				store: new Ext.data.ArrayStore({
+					autoDestroy:  true,
+					fields: [ { name: 'text'}, { name: 'value'}],
+					data: [
+						[this.localize('Not set'), 'not set'],
+						[this.localize('Collapsed borders'), 'collapse'],
+						[this.localize('Detached borders'), 'separate']
+					]
+				}),
+				width: (this.properties && this.properties.borderCollapse && this.properties.borderCollapse.width) ? this.properties.borderCollapse.width : 150,
+				value: element && element.style.borderCollapse ? element.style.borderCollapse : 'not set',
+				disabled: (selectedBorderStyle === 'none')
+			}, this.configDefaults['combo']));
+				// Frame
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Frames:'),
+				itemId: 'f_frames',
+				helpTitle: this.localize('Specifies which sides should have a border'),
+				store: new Ext.data.ArrayStore({
+					autoDestroy:  true,
+					fields: [ { name: 'text'}, { name: 'value'}],
+					data: [
+						[this.localize('Not set'), 'not set'],
+						[this.localize('No sides'), 'void'],
+						[this.localize('The top side only'), 'above'],
+						[this.localize('The bottom side only'), 'below'],
+						[this.localize('The top and bottom sides only'), 'hsides'],
+						[this.localize('The right and left sides only'), 'vsides'],
+						[this.localize('The left-hand side only'), 'lhs'],
+						[this.localize('The right-hand side only'), 'rhs'],
+						[this.localize('All four sides'), 'box']
+					]
+				}),
+				width: (this.properties && this.properties.frame && this.properties.frame.width) ? this.properties.frame.width : 250,
+				value: (element && element.frame) ? element.frame : 'not set',
+				disabled: (selectedBorderStyle === 'none')
+			}, this.configDefaults['combo']));
+				// Rules
+			itemsConfig.push(Ext.apply({
+				xtype: 'combo',
+				fieldLabel: this.localize('Rules:'),
+				itemId: 'f_rules',
+				helpTitle: this.localize('Specifies where rules should be displayed'),
+				store: new Ext.data.ArrayStore({
+					autoDestroy:  true,
+					fields: [ { name: 'text'}, { name: 'value'}],
+					data: [
+						[this.localize('Not set'), 'not set'],
+						[this.localize('No rules'), 'none'],
+						[this.localize('Rules will appear between rows only'), 'rows'],
+						[this.localize('Rules will appear between columns only'), 'cols'],
+						[this.localize('Rules will appear between all rows and columns'), 'all']
+					]
+				}),
+				width: (this.properties && this.properties.rules && this.properties.rules.width) ? this.properties.rules.width : 360,
+				value: (element && element.rules) ? element.rules : 'not set'
+			}, this.configDefaults['combo']));
 		}
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Frame and borders'),
+			defaultType: 'numberfield',
+			defaults: {
+				labelSeparator: '',
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
 	},
-	
-	buildCellTypeFieldset : function (doc, el, content, column, fieldsetClass) {
-		var fieldset = doc.createElement("fieldset");
-		if (fieldsetClass) fieldset.className = fieldsetClass;
-		TableOperations.insertLegend(doc, fieldset, column ? "Type of cells" : "Cell Type and Scope");
-		TableOperations.insertSpace(doc, fieldset);
-		var ul = doc.createElement("ul");
-		fieldset.appendChild(ul);
-		var li = doc.createElement("li");
-		ul.appendChild(li);
+	/*
+	 * onChange handler: enable/disable other fields of the same fieldset
+	 */
+	setBorderFieldsDisabled: function (field, value) {
+		field.ownerCt.findBy(function (item) {
+			var itemId = item.getItemId();
+			if (itemId == 'f_st_borderStyle' || itemId == 'f_rules') {
+				return false;
+			} else if (value === 'none') {
+				switch (item.getXType()) {
+					case 'numberfield':
+						item.setValue(0);
+						break;
+					case 'colorpalettefield':
+						item.setValue('');
+						break;
+					default:
+						item.setValue('not set');
+						break;
+				}
+				item.setDisabled(true);
+			} else {
+				item.setDisabled(false);
+			}
+			return true;
+		});
+	},
+	/*
+	 * This function builds the configuration object for the Colors fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildColorsFieldsetConfig: function (element) {
+		var itemsConfig = [];
+			// Text color
+		itemsConfig.push({
+			xtype: 'colorpalettefield',
+			fieldLabel: this.localize('FG Color:'),
+			itemId: 'f_st_color',
+			colorsConfiguration: this.editorConfiguration.colors,
+			value: HTMLArea.util.Color.colorToHex(element && element.style.color ? element.style.color : ((this.properties && this.properties.color && this.properties.color.defaultValue) ? this.properties.color.defaultValue : '')).substr(1, 6)
+		});
+			// Background color
+		itemsConfig.push({
+			xtype: 'colorpalettefield',
+			fieldLabel: this.localize('Background:'),
+			itemId: 'f_st_backgroundColor',
+			colorsConfiguration: this.editorConfiguration.colors,
+			value: HTMLArea.util.Color.colorToHex(element && element.style.backgroundColor ? element.style.backgroundColor : ((this.properties && this.properties.backgroundColor && this.properties.backgroundColor.defaultValue) ? this.properties.backgroundColor.defaultValue : '')).substr(1, 6)
+		});
+			// Background image
+		itemsConfig.push({
+			fieldLabel: this.localize('Image URL:'),
+			itemId: 'f_st_backgroundImage',
+			value: element && element.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/) ? RegExp.$1 : '',
+			width: (this.properties && this.properties.backgroundImage && this.properties.backgroundImage.width) ? this.properties.backgroundImage.width : 300,
+			helpTitle: this.localize('URL of the background image'),
+			helpIcon: true
+		});
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Background and colors'),
+			defaultType: 'textfield',
+			defaults: {
+				labelSeparator: ''
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * This function builds the configuration object for the Cell Type fieldset
+	 *
+	 * @param	object		element: the element being edited, if any
+	 * @param	boolean		column: true if the element is a column, false if the element is a cell
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildCellTypeFieldsetConfig: function (element, column) {
+		var itemsConfig = [];
 		if (column) {
-			var selectType = TableOperations.buildSelectField(doc, li, "f_cell_type", "Type of cells of the column", "fl", "", "Specifies the type of cells", ["Data cells", "Headers for rows", "Headers for row groups"], ["td", "throw", "throwgroup"], new RegExp(el.nodeName.toLowerCase()+el.scope.toLowerCase()+"$", "i"));
+			var data = [
+				[this.localize('Data cells'), 'td'],
+				[this.localize('Headers for rows'), 'throw'],
+				[this.localize('Headers for row groups'), 'throwgroup']
+			];
 		} else {
-			var selectType = TableOperations.buildSelectField(doc, li, "f_cell_type", "Type of cell", "fr", "", "Specifies the type of cell", ["Normal", "Header for column", "Header for row", "Header for row group"], ["td", "thcol", "throw", "throwgroup"], new RegExp(el.nodeName.toLowerCase()+el.scope.toLowerCase()+"$", "i"));
+			var data = [
+				[this.localize('Normal'), 'td'],
+				[this.localize('Header for column'), 'thcol'],
+				[this.localize('Header for row'), 'throw'],
+				[this.localize('Header for row group'), 'throwgroup']
+			];
 		}
+			// onChange handler: reset the CSS class dropdown when the cell type changes
+			// @param	object		cellTypeField: the combo object
+			// @param	string		value: the value of the cell type field
+			// @return	void
 		var self = this;
-		selectType.onchange = function() { self.setStyleOptions(doc, doc.getElementById("f_class"), el, this.value.substring(0,2)); };
-		TableOperations.insertSpace(doc, fieldset);
-		content.appendChild(fieldset);
-	},
-	
-	buildAlignmentFieldset : function (doc, el, content, fieldsetClass) {
-		var select;
-		var nodeName = el ? el.nodeName.toLowerCase() : "table";
-		var fieldset = doc.createElement("fieldset");
-		if (fieldsetClass) fieldset.className = fieldsetClass;
-		TableOperations.insertLegend(doc, fieldset, "Alignment");
-		var options = ["Not set", "Left", "Center", "Right", "Justify"];
-		var values = ["not set", "left", "center", "right", "justify"];
-		var selected = "";
-		if (el && this.editor.plugins.BlockElements) {
-			var blockElements = this.editor.plugins.BlockElements.instance;
-			for (var value in this.convertAlignment) {
-				if (this.convertAlignment.hasOwnProperty(value) && HTMLArea._hasClass(el, blockElements.useClass[this.convertAlignment[value]])) {
-					selected = value;
-					break;
+		function resetStyleOptions(cellTypeField, value) {
+			self.setStyleOptions(self.dialog.find('itemId', 'f_class'), element, value.substring(0,2));
+		}
+		var selected = element.nodeName.toLowerCase() + element.scope.toLowerCase();
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			fieldLabel: this.localize(column ? 'Type of cells of the column' : 'Type of cell'),
+			itemId: 'f_cell_type',
+			helpTitle: this.localize(column ? 'Specifies the type of cells' : 'Specifies the type of cell'),
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: data
+			}),
+			width: (this.properties && this.properties.cellType && this.properties.cellType.width) ? this.properties.cellType.width : 250,
+			value: (column && selected == 'thcol') ? 'td' : selected,
+			listeners: {
+				change: {
+					fn: resetStyleOptions,
+					scope: this
 				}
 			}
-		} else {
-			selected = el ? el.style.verticalAlign : "";
+		}, this.configDefaults['combo']));
+		return {
+			xtype: 'fieldset',
+			title: this.localize(column ? 'Type of cells' : 'Cell Type and Scope'),
+			defaults: {
+				labelSeparator: '',
+				helpIcon: true
+			},
+			items: itemsConfig
+		};
+	},
+	/*
+	 * This function builds the configuration object for the Row Group fieldset
+	 *
+	 * @param	object		element: the row being edited, if any
+	 *
+	 * @return	object		the fieldset configuration object
+	 */
+	buildRowGroupFieldsetConfig: function (element) {
+		var itemsConfig = [];
+		var current = element.parentNode.nodeName.toLowerCase();
+			// onChange handler: show/hide cell conversion checkbox with appropriate label
+			// @param	object		field: the combo object
+			// @param	object		record: the selected record
+			// @return	void
+		function displayCheckbox(field, record, index) {
+			var checkBox = field.ownerCt.getComponent('f_convertCells');
+			var value = record.get('value');
+			if (current !== value && (current === 'thead' || value === 'thead')) {
+				checkBox.label.dom.innerHTML = (value === 'thead') ? this.localize('Make cells header cells') : this.localize('Make cells data cells');
+				checkBox.show();
+				checkBox.label.show();
+				checkBox.setValue(true);
+			} else {
+				checkBox.setValue(false);
+				checkBox.hide();
+				checkBox.label.hide();
+			}
 		}
-		(selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1);
-		var ul = doc.createElement("ul");
-		fieldset.appendChild(ul);
-		var li = doc.createElement("li");
-		ul.appendChild(li);
-		select = TableOperations.buildSelectField(doc, li, "f_st_textAlign", "Text alignment:", "fr", "", "Horizontal alignment of text within cell", options, values, new RegExp((selected ? selected : "not set"), "i"));
-		
-		var li = doc.createElement("li");
-		ul.appendChild(li);
-		selected = el ? el.style.verticalAlign : "";
-		(selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1);
-		select = TableOperations.buildSelectField(doc, li, "f_st_vertAlign", "Vertical alignment:", "fr", "", "Vertical alignment of content within cell", ["Not set", "Top", "Middle", "Bottom", "Baseline"], ["not set", "top", "middle", "bottom", "baseline"], new RegExp((selected ? selected : "not set"), "i"));
-		content.appendChild(fieldset);
-	},
-	
-	buildBordersFieldset : function (w, doc, editor, el, content, fieldsetClass) {
-		var nodeName = el ? el.nodeName.toLowerCase() : "table";
-		var select;
-		var selected;
-		var borderFields = [];
-		function setBorderFieldsVisibility(value) {
-			for (var i = 0; i < borderFields.length; ++i) {
-				var borderFieldElement = borderFields[i];
-				borderFieldElement.style.visibility = value ? "hidden" : "visible";
-				if (!value && (borderFieldElement.nodeName.toLowerCase() == "input")) {
-					borderFieldElement.focus();
-					borderFieldElement.select();
+		itemsConfig.push(Ext.apply({
+			xtype: 'combo',
+			fieldLabel: this.localize('Row group:'),
+			itemId: 'f_rowgroup',
+			helpTitle: this.localize('Table section'),
+			store: new Ext.data.ArrayStore({
+				autoDestroy:  true,
+				fields: [ { name: 'text'}, { name: 'value'}],
+				data: [
+					[this.localize('Table body'), 'tbody'],
+					[this.localize('Table header'), 'thead'],
+					[this.localize('Table footer'), 'tfoot']
+				]
+			}),
+			width: (this.properties && this.properties.rowGroup && this.properties.rowGroup.width) ? this.properties.rowGroup.width : 150,
+			value: current,
+			labelSeparator: '',
+			listeners: {
+				select: {
+					fn: displayCheckbox,
+					scope: this
 				}
 			}
+		}, this.configDefaults['combo']));
+			// Cell conversion checkbox
+		itemsConfig.push({
+			xtype: 'checkbox',
+			fieldLabel: this.localize('Make cells header cells'),
+			labelSeparator: ':',
+			itemId: 'f_convertCells',
+			helpTitle: this.localize('Make cells header cells'),
+			value: false,
+			hideMode: 'visibility',
+			hidden: true,
+			hideLabel: true
+		});
+		return {
+			xtype: 'fieldset',
+			title: this.localize('Row group'),
+			defaults: {
+				helpIcon: true
+			},
+			items: itemsConfig
 		};
-		var fieldset = doc.createElement("fieldset");
-		fieldset.className = fieldsetClass;
-		TableOperations.insertLegend(doc, fieldset, "Frame and borders");
-		TableOperations.insertSpace(doc, fieldset);
-			// Gecko reports "solid solid solid solid" for "border-style: solid".
-			// That is, "top right bottom left" -- we only consider the first value.
-		var f_st_borderWidth = el ? TableOperations.getLength(el.style.borderWidth) : ((this.properties && this.properties.borderWidth && this.properties.borderWidth.defaultValue) ? this.properties.borderWidth.defaultValue : "");
-		selected = el ? el.style.borderStyle : ((this.properties && this.properties.borderWidth) ? ((this.properties.borderStyle && this.properties.borderStyle.defaultValue) ? this.properties.borderStyle.defaultValue : "solid") : "");
-		(selected.match(/([^\s]*)\s/)) && (selected = RegExp.$1);
-		selectBorderStyle = TableOperations.buildSelectField(doc, fieldset, "f_st_borderStyle", "Border style:", "fr", "floating", "Border style", ["Not set", "No border", "Dotted", "Dashed", "Solid", "Double", "Groove", "Ridge", "Inset", "Outset"], ["not set", "none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"], new RegExp((selected ? selected : "not set"), "i"));
-		selectBorderStyle.onchange = function() { setBorderFieldsVisibility(this.value == "none"); };
-		this.removeOptions(selectBorderStyle, "borderStyle");
-		TableOperations.buildInput(doc, fieldset, "f_st_borderWidth", "Border width:", "Border width", "pixels", "5", f_st_borderWidth, "fr", "floating", "postlabel", borderFields);
-		TableOperations.insertSpace(doc, fieldset, borderFields);
-		
-		if (nodeName == "table") {
-			TableOperations.buildColorField(w, doc, editor, fieldset, "", "Color:", "fr", "colorButton", (el ? el.style.borderColor : ""), "borderColor", borderFields);
-			var label = doc.createElement("label");
-			label.className = "fl-borderCollapse";
-			label.htmlFor = "f_st_borderCollapse";
-			label.innerHTML = "Collapsed borders";
-			fieldset.appendChild(label);
-			borderFields.push(label);
-			var input = doc.createElement("input");
-			input.className = "checkbox";
-			input.type = "checkbox";
-			input.name = "f_st_borderCollapse";
-			input.id = "f_st_borderCollapse";
-			input.defaultChecked = el ? /collapse/i.test(el.style.borderCollapse) : false;
-			input.checked = input.defaultChecked;
-			fieldset.appendChild(input);
-			borderFields.push(input);
-			TableOperations.insertSpace(doc, fieldset, borderFields);
-			select = TableOperations.buildSelectField(doc, fieldset, "f_frames", "Frames:", "fr", "floating", "Specifies which sides should have a border", ["Not set", "No sides", "The top side only", "The bottom side only", "The top and bottom sides only", "The right and left sides only", "The left-hand side only", "The right-hand side only", "All four sides"], ["not set", "void", "above", "below", "hsides", "vsides", "lhs", "rhs", "box"], new RegExp(((el && el.frame) ? el.frame : "not set"), "i"), borderFields);
-			TableOperations.insertSpace(doc, fieldset, borderFields);
-			select = TableOperations.buildSelectField(doc, fieldset, "f_rules", "Rules:", "fr", "floating", "Specifies where rules should be displayed", ["Not set", "No rules", "Rules will appear between rows only", "Rules will appear between columns only", "Rules will appear between all rows and columns"], ["not set", "none", "rows", "cols", "all"], new RegExp(((el && el.rules) ? el.rules : "not set"), "i"), borderFields);
-		} else {
-			TableOperations.insertSpace(doc, fieldset, borderFields);
-			TableOperations.buildColorField(w, doc, editor, fieldset, "", "Color:", "fr", "colorButton", (el ? el.style.borderColor : ""), "borderColor", borderFields);
-		}
-		setBorderFieldsVisibility(selectBorderStyle.value == "none");
-		TableOperations.insertSpace(doc, fieldset);
-		content.appendChild(fieldset);
 	},
-	
-	removeOptions : function(select, property) {
+	/*
+	 * This function removes some items from a data store for the specified property
+	 *
+	 */
+	removeOptions: function (store, property) {
 		if (this.properties && this.properties[property] && this.properties[property].removeItems) {
-			for (var i = select.options.length; --i >= 0;) {
-				if (this.properties[property].removeItems.indexOf(select.options[i].value) != -1) {
-					if (select.options[i].value != select.value) {
-						select.options[i] = null;
-					}
+			var items = this.properties[property].removeItems.split(',');
+			var index = -1;
+			Ext.each(items, function (item) {
+				index = store.findExact('value', item.trim());
+				if (index !== -1) {
+					store.removeAt(index);
 				}
-			}
+				return true;
+			});
 		}
 	},
-	
 	/*
-	 * This function gets called by the main editor event handler when a key was pressed.
+	 * This function gets called by the editor key map when a key was pressed.
 	 * It will process the enter key for IE and Opera when buttons.table.disableEnterParagraphs is set in the editor configuration
+	 *
+	 * @param	string		key: the key code
+	 * @param	object		event: the Ext event object (keydown)
+	 *
+	 * @return	boolean		false, if the event was taken care of
 	 */
-	onKeyPress : function (ev) {
-		if ((HTMLArea.is_ie || HTMLArea.is_opera) && ev.keyCode == 13 && !ev.shiftKey && this.disableEnterParagraphs) {
-			var selection = this.editor._getSelection();
-			var range = this.editor._createRange(selection);
-			var parentElement = this.editor.getParentElement(selection, range);
-			while (parentElement && !HTMLArea.isBlockElement(parentElement)) {
-				parentElement = parentElement.parentNode;
-			}
-			if (/^(td|th)$/i.test(parentElement.nodeName)) {
-				if (HTMLArea.is_ie) {
-					range.pasteHTML("<br />");
+	onKey: function (key, event) {
+		var selection = this.editor._getSelection();
+		var range = this.editor._createRange(selection);
+		var parentElement = this.editor.getParentElement(selection, range);
+		while (parentElement && !HTMLArea.isBlockElement(parentElement)) {
+			parentElement = parentElement.parentNode;
+		}
+		if (/^(td|th)$/i.test(parentElement.nodeName)) {
+			if (Ext.isIE) {
+				range.pasteHTML('<br />');
+				range.select();
+			} else {
+				var brNode = this.editor._doc.createElement('br');
+				this.editor.insertNodeAtSelection(brNode);
+				if (brNode.nextSibling) {
+					this.editor.selectNodeContents(brNode.nextSibling, true);
 				} else {
-					var brNode = this.editor._doc.createElement("br");
-					this.editor.insertNodeAtSelection(brNode);
-					this.editor.selectNode(brNode, false);
+					this.editor.selectNodeContents(brNode, false);
 				}
-				return false;
 			}
+			event.stopEvent();
+			return false;
 		}
 		return true;
 	}
 });
-
-TableOperations.getLength = function(value) {
-	var len = parseInt(value);
-	if (isNaN(len)) len = "";
-	return len;
-};
-
-// Returns an HTML element for a widget that allows color selection.  That is,
-// a button that contains the given color, if any, and when pressed will popup
-// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
-// to select some color.  If a color is selected, an input field with the name
-// "f_st_"+name will be updated with the color value in #123456 format.
-TableOperations.createColorButton = function(w, doc, editor, color, name) {
-	if (!color) {
-		color = "";
-	} else if (!/#/.test(color)) {
-		color = HTMLArea._colorToRgb(color);
-	}
-
-	var df = doc.createElement("span");
- 	var field = doc.createElement("input");
-	field.type = "hidden";
-	df.appendChild(field);
- 	field.name = "f_st_" + name;
- 	field.id = "f_st_" + name;
-	field.value = color;
-	var button = doc.createElement("span");
-	button.className = "buttonColor";
-	df.appendChild(button);
-	var span = doc.createElement("span");
-	span.className = "chooser";
-	span.style.backgroundColor = color;
-	var space = doc.createTextNode("\xA0");
-	span.appendChild(space);
-	button.appendChild(span);
-	button.onmouseover = function() { if (!this.disabled) this.className += " buttonColor-hilite"; };
-	button.onmouseout = function() { if (!this.disabled) this.className = "buttonColor"; };
-	span.onclick = function() {
-		if (this.parentNode.disabled) return false;
-		var colorPlugin = editor.plugins.TYPO3Color;
-		if (colorPlugin) {
-			colorPlugin.instance.dialogSelectColor("color", span, field, w);
-		} else {
-			colorPlugin = editor.plugins.DefaultColor;
-			if (colorPlugin) {
-				w.insertColor = function (color) {
-					if (color) {
-						span.style.backgroundColor = color;
-						field.value = color;
-					}
-				};
-				colorPlugin.instance.onButtonPress(editor, "TableOperations");
-			}
-		}
-	};
-	var span2 = doc.createElement("span");
-	span2.innerHTML = "&#x00d7;";
-	span2.className = "nocolor";
-	span2.title = "Unset color";
-	button.appendChild(span2);
-	span2.onmouseover = function() { if (!this.parentNode.disabled) this.className += " nocolor-hilite"; };
-	span2.onmouseout = function() { if (!this.parentNode.disabled) this.className = "nocolor"; };
-	span2.onclick = function() {
-		span.style.backgroundColor = "";
-		field.value = "";
-	};
-	return df;
-};
-TableOperations.buildTitle = function(doc, content, title) {
-	var div = doc.createElement("div");
-	div.className = "title";
-	div.innerHTML = title;
-	content.appendChild(div);
-	doc.title = title;
-};
-TableOperations.buildDescriptionFieldset = function(doc, el, content, fieldsetClass) {
-	var fieldset = doc.createElement("fieldset");
-	if (fieldsetClass) fieldset.className = fieldsetClass;
-	TableOperations.insertLegend(doc, fieldset, "Description");
-	TableOperations.insertSpace(doc, fieldset);
-	var f_caption = "";
-	if (el) {
-		var capel = el.getElementsByTagName("caption")[0];
-		if (capel) f_caption = capel.innerHTML;
-	}
-	TableOperations.buildInput(doc, fieldset, "f_caption", "Caption:", "Description of the nature of the table", "", "", f_caption, "fr", "value", "");
-	TableOperations.insertSpace(doc, fieldset);
-	TableOperations.buildInput(doc, fieldset, "f_summary", "Summary:", "Summary of the table purpose and structure", "", "", (el ? el.summary : ""), "fr", "value", "");
-	TableOperations.insertSpace(doc, fieldset);
-	content.appendChild(fieldset);
-};
-TableOperations.buildRowGroupFieldset = function(w, doc, editor, el, content, fieldsetClass) {
-	var fieldset = doc.createElement("fieldset");
-	if (fieldsetClass) fieldset.className = fieldsetClass;
-	TableOperations.insertLegend(doc, fieldset, "Row group");
-	TableOperations.insertSpace(doc, fieldset);
-	TableOperations.insertSpace(doc, fieldset);
-	selected = el.parentNode.nodeName.toLowerCase();
-	var selectScope = TableOperations.buildSelectField(doc, fieldset, "f_rowgroup", "Row group:", "fr", "floating", "Table section", ["Table body", "Table header", "Table footer"], ["tbody", "thead", "tfoot"], new RegExp((selected ? selected : "tbody"), "i"));
-	function displayCheckbox(current, value) {
-		if (current !== "thead" && value === "thead") {
-			label1.style.display = "inline";
-			label2.style.display = "none";
-			input.style.display = "inline";
-			input.checked = true;
-		} else if (current === "thead" && value !== "thead") {
-			label1.style.display = "none";
-			label2.style.display = "inline";
-			input.style.display = "inline";
-			input.checked = true;
-		} else {
-			label1.style.display = "none";
-			label2.style.display = "none";
-			input.style.display = "none";
-			input.checked = false;
-		}
-	}
-	selectScope.onchange = function() { displayCheckbox(selected, this.value); };
-	var label1 = doc.createElement("label");
-	label1.className = "fl";
-	label1.htmlFor = "f_convertCells";
-	label1.innerHTML = "Make cells header cells";
-	label1.style.display = "none";
-	fieldset.appendChild(label1);
-	var label2 = doc.createElement("label");
-	label2.className = "fl";
-	label2.htmlFor = "f_convertCells";
-	label2.innerHTML = "Make cells data cells";
-	label2.style.display = "none";
-	fieldset.appendChild(label2);
-	var input = doc.createElement("input");
-	input.className = "checkbox";
-	input.type = "checkbox";
-	input.name = "f_convertCells";
-	input.id = "f_convertCells";
-	input.checked = false;
-	input.style.display = "none";
-	fieldset.appendChild(input);
-	TableOperations.insertSpace(doc, fieldset);
-	content.appendChild(fieldset);
-};
-TableOperations.buildSpacingFieldset = function(doc, el, content) {
-	var fieldset = doc.createElement("fieldset");
-	TableOperations.insertLegend(doc, fieldset, "Spacing and padding");
-	TableOperations.buildInput(doc, fieldset, "f_spacing", "Cell spacing:", "Space between adjacent cells", "pixels", "5", (el ? el.cellSpacing : ""), "fr", "", "postlabel");
-	TableOperations.insertSpace(doc, fieldset);
-	TableOperations.buildInput(doc, fieldset, "f_padding", "Cell padding:", "Space between content and border in cell", "pixels", "5", (el ? el.cellPadding : ""), "fr", "", "postlabel");
-	content.appendChild(fieldset);
-};
-TableOperations.buildColorsFieldset = function(w, doc, editor, el, content) {
-	var fieldset = doc.createElement("fieldset");
-	TableOperations.insertLegend(doc, fieldset, "Background and colors");
-	var ul = doc.createElement("ul");
-	fieldset.appendChild(ul);
-	var li = doc.createElement("li");
-	ul.appendChild(li);
-	TableOperations.buildColorField(w, doc, editor, li, "", "FG Color:", "fr", "colorButtonNoFloat", (el ? el.style.color : ""), "color");
-	var li = doc.createElement("li");
-	ul.appendChild(li);
-	TableOperations.buildColorField(w, doc, editor, li, "", "Background:", "fr", "colorButtonNoFloat", (el ? el.style.backgroundColor : ""), "backgroundColor");
-	var url;
-	if (el && el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) url = RegExp.$1;
-	TableOperations.buildInput(doc, li, "f_st_backgroundImage", "Image URL:", "URL of the background image", "", "", url, "", "shorter-value");
-	content.appendChild(fieldset);
-};
-TableOperations.insertLegend = function(doc, fieldset, legend) {
-	var legendNode = doc.createElement("legend");
-	legendNode.innerHTML = legend;
-	fieldset.appendChild(legendNode);
-};
-TableOperations.insertSpace =	function(doc,fieldset,fields) {
-	var space = doc.createElement("div");
-	space.className = "space";
-	fieldset.appendChild(space);
-	if(fields) fields.push(space);
-};
-TableOperations.buildInput = function(doc, fieldset,fieldName,fieldLabel,fieldTitle,postLabel,fieldSize,fieldValue,labelClass,inputClass,postClass,fields) {
-	var label;
-		// Field label
-	if(fieldLabel) {
-		label = doc.createElement("label");
-		if(labelClass) label.className = labelClass;
-		label.innerHTML = fieldLabel;
-		label.htmlFor = fieldName;
-		fieldset.appendChild(label);
-		if(fields) fields.push(label);
-	}
-		// Input field
-	var input = doc.createElement("input");
-	input.type = "text";
-	input.id = fieldName;
-	input.name =  fieldName;
-	if(inputClass) input.className = inputClass;
-	if(fieldTitle) input.title = fieldTitle;
-	if(fieldSize) input.size = fieldSize;
-	if(fieldValue) input.value = fieldValue;
-	fieldset.appendChild(input);
-	if(fields) fields.push(input);
-		// Field post label
-	if(postLabel) {
-		label = doc.createElement("span");
-		if(postClass) label.className = postClass;
-		label.innerHTML = postLabel;
-		fieldset.appendChild(label);
-		if(fields) fields.push(label);
-	}
-	return input;
-};
-TableOperations.buildSelectField = function(doc, fieldset,fieldName,fieldLabel,labelClass,selectClass,fieldTitle,options,values,selected,fields,translateOptions) {
-	if(typeof(translateOptions) == "undefined") var translateOptions = true;
-		// Field Label
-	if(fieldLabel) {
-		var label = doc.createElement("label");
-		if(labelClass) label.className = labelClass;
-		label.innerHTML = fieldLabel;
-		label.htmlFor = fieldName;
-		fieldset.appendChild(label);
-		if(fields) fields.push(label);
-	}
-		// Text Alignment Select Box
-	var select = doc.createElement("select");
-	if (selectClass) select.className = selectClass;
-	select.id = fieldName;
-	select.name =  fieldName;
-	select.title= fieldTitle;
-	select.selectedIndex = 0;
-	var option;
-	for (var i = 0; i < options.length; ++i) {
-		option = doc.createElement("option");
-		select.appendChild(option);
-		option.value = values[i];
-		option.innerHTML = options[i];
-		option.selected = selected.test(option.value);
-	}
-	if (select.options.length>1) select.disabled = false;
-		else select.disabled = true;
-	fieldset.appendChild(select);
-	if(fields) fields.push(select);
-	return select;
-};
-TableOperations.buildColorField = function(w, doc, editor, fieldset,fieldName,fieldLabel,labelClass, buttonClass, fieldValue,fieldType,fields) {
-		// Field Label
-	if(fieldLabel) {
-		var label = doc.createElement("label");
-		if(labelClass) label.className = labelClass;
-		label.innerHTML = fieldLabel;
-		fieldset.appendChild(label);
-		if(fields) fields.push(label);
-	}
-	var colorButton = TableOperations.createColorButton(w, doc, editor, fieldValue, fieldType);
-	colorButton.className = buttonClass;
-	fieldset.appendChild(colorButton);
-	if(fields) fields.push(colorButton);
-};
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js	(révision 0)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TextIndicator/text-indicator.js	(révision 0)
@@ -0,0 +1,103 @@
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/*
+ * TextIndicator Plugin for TYPO3 htmlArea RTE
+ *
+ * TYPO3 SVN ID: $Id: text-indicator.js 6539 2009-11-25 14:49:14Z stucki $
+ */
+TextIndicator = HTMLArea.Plugin.extend({
+		
+	constructor : function(editor, pluginName) {
+		this.base(editor, pluginName);
+	},
+	
+	/*
+	 * This function gets called by the class constructor
+	 */
+	configurePlugin : function (editor) {
+		/*
+		 * Registering plugin "About" information
+		 */
+		var pluginInformation = {
+			version		: "1.0",
+			developer	: "Stanislas Rolland",
+			developerUrl	: "http://www.sjbr.ca/",
+			copyrightOwner	: "Stanislas Rolland",
+			sponsor		: "SJBR",
+			sponsorUrl	: "http://www.sjbr.ca/",
+			license		: "GPL"
+		};
+		this.registerPluginInformation(pluginInformation);
+		
+		/*
+		 * Registering the indicator
+		 */
+		var buttonId = 'TextIndicator';
+		var textConfiguration = {
+			id: buttonId,
+			cls: 'indicator',
+			text: 'A',
+			tooltip: this.localize(buttonId.toLowerCase())
+		};
+		this.registerText(textConfiguration);
+		return true;
+	 },
+
+	/*
+	 * This function gets called when the toolbar is updated
+	 */
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		var editor = this.editor;
+		if (mode === 'wysiwyg' && editor.isEditable()) {
+			var doc = editor._doc;
+			try {
+				var style = {
+					backgroundColor: HTMLArea._makeColor(doc.queryCommandValue((HTMLArea.is_ie || HTMLArea.is_safari) ? 'BackColor' : 'HiliteColor')),
+					color: HTMLArea._makeColor(doc.queryCommandValue('ForeColor')),
+					fontFamily: doc.queryCommandValue('FontName'),
+					fontWeight: 'normal',
+					fontStyle: 'normal'
+				};
+					// Mozilla
+				if (/transparent/i.test(style.backgroundColor)) {
+					style.backgroundColor = HTMLArea._makeColor(doc.queryCommandValue('BackColor'));
+				}
+				try {
+					style.fontWeight = doc.queryCommandState('Bold') ? 'bold' : 'normal';
+				} catch(e) {
+					style.fontWeight = 'normal';
+				}
+				try {
+					style.fontStyle = doc.queryCommandState('Italic') ? 'italic' : 'normal';
+				} catch(e) {
+					style.fontStyle = 'normal';
+				}
+				button.getEl().setStyle(style);
+			} catch (e) { }
+		}
+	}
+});
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2007-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2007-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -112,15 +112,22 @@
 		/* 
 		 * Registering the dropdown list
 		 */
-		var buttonId = "TextStyle";
+		var buttonId = 'TextStyle';
+		var fieldLabel = this.pageTSconfiguration.fieldLabel;
+		if (Ext.isEmpty(fieldLabel) && this.isButtonInToolbar('I[text_style]')) {
+			fieldLabel = this.localize('text_style');
+		}
 		var dropDownConfiguration = {
-			id		: buttonId,
-			tooltip		: this.localize(buttonId + "-Tooltip"),
-			textMode	: false,
-			options		: {"":""},
-			action		: "onChange",
-			refresh		: "generate",
-			context		: null
+			id: buttonId,
+			tooltip: this.localize(buttonId + '-Tooltip'),
+			fieldLabel: fieldLabel,
+			width: this.pageTSconfiguration.width ? this.pageTSconfiguration.width : 'auto',
+			listWidth:  this.pageTSconfiguration.listWidth ? this.pageTSconfiguration.listWidth : 250,
+			maxHeight: this.pageTSconfiguration.maxHeight ? this.pageTSconfiguration.maxHeight : 300,
+			options: [[this.localize('No style'), 'none']],
+			action: 'onChange',
+			storeFields: [ { name: 'text'}, { name: 'value'}, { name: 'style'} ],
+			tpl: '<tpl for="."><div ext:qtip="{value}" style="{style}text-align:left;font-size:11px;" class="x-combo-list-item">{text}</div></tpl>'
 		};
 		this.registerDropDown(dropDownConfiguration);
 		
@@ -145,15 +152,14 @@
 	/*
 	 * This function gets called when some style in the drop-down list applies it to the highlighted textt
 	 */
-	onChange : function (editor, buttonId) {
-		var select = document.getElementById(this.editor._toolbarObjects[buttonId].elementId);
-		var className = select.value;
+	onChange : function (editor, combo, record, index) {
+		var className = combo.getValue();
 		var classNames = null;
 		var fullNodeSelected = false;
 		
 		this.editor.focusEditor();
 		var selection = this.editor._getSelection();
-		var statusBarSelection = this.editor.getPluginInstance("StatusBar") ? this.editor.getPluginInstance("StatusBar").getSelection() : null;
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		var range = this.editor._createRange(selection);
 		var parent = this.editor.getParentElement();
 		var selectionEmpty = this.editor._selectionEmpty(selection);
@@ -213,7 +219,9 @@
 	 * This function gets called when the plugin is generated
 	 * Get the classes configuration and initiate the parsing of the style sheets
 	 */
-	onGenerate : function() {
+	onGenerate: function() {
+			// Monitor editor changing mode
+		this.editor.iframe.mon(this.editor, 'modeChange', this.onModeChange, this);
 		this.generate(this.editor, "TextStyle");
 	},
 	
@@ -226,11 +234,7 @@
 			this.updateToolbar(dropDownId);
 		} else {
 			if (this.cssTimeout) {
-				if (editor._iframe.contentWindow) {
-					editor._iframe.contentWindow.clearTimeout(this.cssTimeout);
-				} else {
-					window.clearTimeout(this.cssTimeout);
-				}
+				window.clearTimeout(this.cssTimeout);
 				this.cssTimeout = null;
 			}
 			if (this.classesUrl && (typeof(HTMLArea.classesLabels) === "undefined")) {
@@ -243,8 +247,7 @@
 	buildCssArray : function(editor, dropDownId) {
 		this.cssArray = this.parseStyleSheet();
 		if (!this.cssLoaded && (this.cssParseCount < 17)) {
-			var buildCssArrayLaterFunctRef = this.makeFunctionReference("buildCssArray");
-			this.cssTimeout = editor._iframe.contentWindow ? editor._iframe.contentWindow.setTimeout(buildCssArrayLaterFunctRef, 200) : window.setTimeout(buildCssArrayLaterFunctRef, 200);
+			this.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]);
 			this.cssParseCount++;
 		} else {
 			this.cssTimeout = null;
@@ -393,9 +396,9 @@
 	/*
 	 * This function gets called when the toolbar is being updated
 	 */
-	onUpdateToolbar : function() {
-		if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) {
-			this.generate(this.editor, "TextStyle");
+	onUpdateToolbar: function(button, mode, selectionEmpty, ancestors) {
+		if (mode === "wysiwyg" && this.editor.isEditable()) {
+			this.generate(this.editor, button.itemId);
 		}
 	},
 	
@@ -407,7 +410,7 @@
 		if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) {
 			var tagName = false, classNames = Array(), fullNodeSelected = false;
 			var selection = editor._getSelection();
-			var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
+			var statusBarSelection = editor.statusBar ? editor.statusBar.getSelection() : null;
 			var range = editor._createRange(selection);
 			var parent = editor.getParentElement(selection);
 			var ancestors = editor.getAllAncestors();
@@ -446,122 +449,144 @@
 			if (!disabled && !tagName) {
 				tagName = "span";
 			}
-			
 			this.updateValue(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled);
+		} else {
+			var dropDown = this.getButton(dropDownId);
+			if (dropDown) {
+				dropDown.setDisabled(!dropDown.textMode);
+			}
 		}
 	},
 
+	/*
+	 * This function reinitializes the options of the dropdown
+	 */
+	initializeDropDown : function (dropDown) {
+		var store = dropDown.getStore();
+		store.removeAll(true);
+		store.insert(0, new store.recordType({
+			text: this.localize('No style'),
+			value: 'none'
+		}));
+		dropDown.setValue('none');
+	},
+
+	/*
+	 * This function sets the selected option of the dropDown box
+	 */
+	setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) {
+		var store = dropDown.getStore();
+		var index = store.findExact('value', classNames[classNames.length-1]);
+		if (index != -1) {
+			dropDown.setValue(classNames[classNames.length-1]);
+			if (!defaultClass) {
+				store.getAt(0).set('text', this.localize('Remove style'));
+			}
+		}
+		if (index == -1 && !noUnknown) {
+			store.add(new store.recordType({
+				text: this.localize('Unknown style'),
+				value: classNames[classNames.length-1]
+			}));
+			index = store.getCount()-1;
+			dropDown.setValue(classNames[classNames.length-1]);
+			if (!defaultClass) {
+				store.getAt(0).set('text', this.localize('Remove style'));
+			}
+		}
+		store.each(function (option) {
+			if (("," + classNames.join(",") + ",").indexOf("," + option.get('value') + ",") != -1 && store.indexOf(option) != index) {
+				store.removeAt(store.indexOf(option));
+			}
+			return true;
+		});
+	},
+
 	updateValue : function(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled) {
 		var editor = this.editor;
-		var select = document.getElementById(editor._toolbarObjects[dropDownId]["elementId"]);
-		var cssArray = new Array();
-		
-		while(select.options.length > 0) {
-			select.options[select.length-1] = null;
-		}
-		select.options[0] = new Option(this.localize("No style"),"none");
-		if (this.REInlineTags.test(tagName)) {
-				// Get classes allowed for all tags
-			if (typeof(this.cssArray["all"]) !== "undefined") {
-				var cssArrayAll = this.cssArray.all;
-				if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
-					var allowedClasses = this.tags[tagName].allowedClasses;
-					for (var cssClass in cssArrayAll) {
-						if (cssArrayAll.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
-							cssArray[cssClass] = cssArrayAll[cssClass];
+		var dropDown = this.getButton(dropDownId);
+		if (dropDown) {
+			var store = dropDown.getStore();
+			var cssArray = new Array();
+			this.initializeDropDown(dropDown);
+			if (this.REInlineTags.test(tagName)) {
+					// Get classes allowed for all tags
+				if (typeof(this.cssArray["all"]) !== "undefined") {
+					var cssArrayAll = this.cssArray.all;
+					if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
+						var allowedClasses = this.tags[tagName].allowedClasses;
+						for (var cssClass in cssArrayAll) {
+							if (cssArrayAll.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
+								cssArray[cssClass] = cssArrayAll[cssClass];
+							}
 						}
-					}
-				} else {
-					for (var cssClass in cssArrayAll) {
-						if (cssArrayAll.hasOwnProperty(cssClass)) {
-							cssArray[cssClass] = cssArrayAll[cssClass];
+					} else {
+						for (var cssClass in cssArrayAll) {
+							if (cssArrayAll.hasOwnProperty(cssClass)) {
+								cssArray[cssClass] = cssArrayAll[cssClass];
+							}
 						}
 					}
 				}
-			}
-				// Merge classes allowed for tagName and sort the array
-			if (typeof(this.cssArray[tagName]) !== "undefined") {
-				var cssArrayTagName = this.cssArray[tagName];
-				if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
-					var allowedClasses = this.tags[tagName].allowedClasses;
-					for (var cssClass in cssArrayTagName) {
-						if (cssArrayTagName.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
-							cssArray[cssClass] = cssArrayTagName[cssClass];
+					// Merge classes allowed for tagName and sort the array
+				if (typeof(this.cssArray[tagName]) !== "undefined") {
+					var cssArrayTagName = this.cssArray[tagName];
+					if (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses) {
+						var allowedClasses = this.tags[tagName].allowedClasses;
+						for (var cssClass in cssArrayTagName) {
+							if (cssArrayTagName.hasOwnProperty(cssClass) && allowedClasses.test(cssClass)) {
+								cssArray[cssClass] = cssArrayTagName[cssClass];
+							}
 						}
+					} else {
+						for (var cssClass in cssArrayTagName) {
+							if (cssArrayTagName.hasOwnProperty(cssClass)) {
+								cssArray[cssClass] = cssArrayTagName[cssClass];
+							}
+						}
 					}
-				} else {
-					for (var cssClass in cssArrayTagName) {
-						if (cssArrayTagName.hasOwnProperty(cssClass)) {
-							cssArray[cssClass] = cssArrayTagName[cssClass];
+					var sortedCssArray = new Object();
+					var cssArrayKeys = new Array();
+					for (var cssClass in cssArray) {
+						if (cssArray.hasOwnProperty(cssClass)) {
+							cssArrayKeys.push(cssClass);
 						}
 					}
+					function compare(a, b) {
+						x = cssArray[a];
+						y = cssArray[b];
+						return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+					}
+					cssArrayKeys = cssArrayKeys.sort(compare);
+					for (var i = 0; i < cssArrayKeys.length; ++i) {
+						sortedCssArray[cssArrayKeys[i]] = cssArray[cssArrayKeys[i]];
+					}
+					cssArray = sortedCssArray;
 				}
-				var sortedCssArray = new Object();
-				var cssArrayKeys = new Array();
 				for (var cssClass in cssArray) {
-					if (cssArray.hasOwnProperty(cssClass)) {
-						cssArrayKeys.push(cssClass);
-					}
-				}
-				function compare(a, b) {
-					x = cssArray[a];
-					y = cssArray[b];
-					return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-				}
-				cssArrayKeys = cssArrayKeys.sort(compare);
-				for (var i = 0; i < cssArrayKeys.length; ++i) {
-					sortedCssArray[cssArrayKeys[i]] = cssArray[cssArrayKeys[i]];
-				}
-				cssArray = sortedCssArray;
-			}
-			for (var cssClass in cssArray) {
-				if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
-					if (cssClass == "none") {
-						select.options[0] = new Option(cssArray[cssClass], cssClass);
-					} else {
-						select.options[select.options.length] = new Option(cssArray[cssClass], cssClass);
-						if (!editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
-							select.options[select.options.length-1].setAttribute("style", HTMLArea.classesValues[cssClass]);
+					if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
+						if (cssClass == 'none') {
+							store.getAt(0).set('text', cssArray[cssClass]);
+						} else {
+							store.add(new store.recordType({
+								text: cssArray[cssClass],
+								value: cssClass,
+								style: (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) ? HTMLArea.classesValues[cssClass] : null
+							}));
 						}
 					}
 				}
-			}
-			
-			select.selectedIndex = 0;
-			if (classNames.length && (selectionEmpty || fullNodeSelected)) {
-				for (i = select.options.length; --i >= 0;) {
-					if (classNames[classNames.length-1] == select.options[i].value) {
-						select.options[i].selected = true;
-						select.selectedIndex = i;
-						select.options[0].text = this.localize("Remove style");
-						break;
-					}
+				if (classNames.length && (selectionEmpty || fullNodeSelected)) {
+					this.setSelectedOption(dropDown, classNames);
 				}
-				if (select.selectedIndex == 0) {
-					select.options[select.options.length] = new Option(this.localize("Unknown style"), classNames[classNames.length-1]);
-					select.options[select.options.length-1].selected = true;
-					select.selectedIndex = select.options.length-1;
-				}
-				for (i = select.options.length; --i >= 0;) {
-					if (("," + classNames.join(",") + ",").indexOf("," + select.options[i].value + ",") !== -1) {
-						if (select.selectedIndex != i) {
-							select.options[i] = null;
-						}
-					}
-				}
 			}
+			dropDown.setDisabled(!(store.getCount()>1) || disabled);
 		}
-		select.disabled = !(select.options.length>1) || disabled;
-		select.className = "";
-		if (select.disabled) {
-			select.className = "buttonDisabled";
-		}
 	},
-	
 	/*
 	 * This function gets called when the editor has changed its mode to "wysiwyg"
 	 */
-	onMode : function(mode) {
+	onModeChange: function(mode) {
 		if (mode === "wysiwyg" && this.editor.isEditable()) {
 			this.generate(this.editor, "TextStyle");
 		}
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Color/typo3color.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2004-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2004-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -64,12 +64,11 @@
 				this.allowedAttributes.push("className");
 			}
 		}
-
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "3.0",
+			version		: "4.0",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -78,7 +77,6 @@
 			license		: "GPL"
 		};
 		this.registerPluginInformation(pluginInformation);
-
 		/*
 		 * Registering the buttons
 		 */
@@ -95,26 +93,33 @@
 			};
 			this.registerButton(buttonConfiguration);
 		}
-		
 		return true;
 	 },
-
 	/*
 	 * The list of buttons added by this plugin
 	 */
-	buttonList : [
-		["ForeColor", "textcolor"],
-		["HiliteColor", "bgcolor"]
+	buttonList: [
+		['ForeColor', 'textcolor'],
+		['HiliteColor', 'bgcolor']
 	],
-
 	/*
 	 * Conversion object: button name to corresponding style property name
 	 */
-	styleProperty : {
-		ForeColor	: "color",
-		HiliteColor	: "backgroundColor"
+	styleProperty: {
+		ForeColor	: 'color',
+		HiliteColor	: 'backgroundColor'
 	},
-
+	colors: [
+		'000000', '222222', '444444', '666666', '999999', 'BBBBBB', 'DDDDDD', 'FFFFFF',
+		'660000', '663300', '996633', '003300', '003399', '000066', '330066', '660066',
+		'990000', '993300', 'CC9900', '006600', '0033FF', '000099', '660099', '990066',
+		'CC0000', 'CC3300', 'FFCC00', '009900', '0066FF', '0000CC', '663399', 'CC0099',
+		'FF0000', 'FF3300', 'FFFF00', '00CC00', '0099FF', '0000FF', '9900CC', 'FF0099',
+		'CC3333', 'FF6600', 'FFFF33', '00FF00', '00CCFF', '3366FF', '9933FF', 'FF00FF',
+		'FF6666', 'FF6633', 'FFFF66', '66FF66', '00FFFF', '3399FF', '9966FF', 'FF66FF',
+		'FF9999', 'FF9966', 'FFFF99', '99FF99', '99FFFF', '66CCFF', '9999FF', 'FF99FF',
+		'FFCCCC', 'FFCC99', 'FFFFCC', 'CCFFCC', 'CCFFFF', '99CCFF', 'CCCCFF', 'FFCCFF'
+	],
 	/*
 	 * This function gets called when the button was pressed.
 	 *
@@ -124,275 +129,258 @@
 	 *
 	 * @return	boolean		false if action is completed
 	 */
-	onButtonPress : function (editor, id, target) {
+	onButtonPress: function (editor, id, target) {
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
-		this.dialogSelectColor(buttonId,"","");
+		var element = this.editor.getParentElement();
+		this.openDialogue(
+			buttonId + '_title',
+			{
+				element: element,
+				buttonId: buttonId
+			},
+			this.getWindowDimensions({ width: 350}, buttonId),
+			this.buildItemsConfig(element, buttonId),
+			this.setColor
+		);
 	},
-
-	dialogSelectColor : function (buttonId, element, field, dialogOpener) {
-		var dimensions = {
-			width	: 440,
-			height	: 300
-		};
-		var arguments = {
-			title 		: buttonId + "_title",
-			buttonId	: buttonId,
-			element		: element,
-			field		: field
-		};
-			// buttonId's  "color" and "tag" are not registered but used to interface with the Table Operations and QuickTag plugins
-		switch (buttonId) {
-			case "ForeColor"	:
-			case "HiliteColor"	:
-				var selectColorWithButtonInitFunctRef = this.makeFunctionReference("selectColorWithButtonInit");
-				arguments.initialize = selectColorWithButtonInitFunctRef;
-				this.dialog = this.openDialog(buttonId, "", "setColor", arguments, dimensions, "yes");
-				break;
-			case "color"		:
-				var selectColorCodeInitFunctRef = this.makeFunctionReference("selectColorCodeInit");
-				arguments.initialize = selectColorCodeInitFunctRef;
-				this.dialog = this.openDialog(buttonId, "", "setColor", arguments, dimensions, "yes", dialogOpener);
-				break;
-			case "tag"		:
-				var selectColorCodeInitFunctRef = this.makeFunctionReference("selectColorCodeInit");
-				arguments.initialize = selectColorCodeInitFunctRef;
-				arguments.title = "color_title";
-				this.dialog = this.openDialog(buttonId, "", "setColorInTag", arguments, dimensions, "yes", dialogOpener);
-		}
-	},
-	
 	/*
-	 * Initialize the forecolor and the hilitecolor select color dialogues
+	 * Build the window items config
 	 */
-	selectColorWithButtonInit : function(dialog) {
-		var editor = dialog.editor;
-		var doc = editor._doc;
-		var buttonId = dialog.arguments.buttonId;
-		var initialValue;
-		var parentElement = editor.getParentElement();
-		initialValue = HTMLArea._colorToRgb(parentElement.style[this.styleProperty[buttonId]]);
-		dialog.content.innerHTML = this.renderPopupSelectColor(buttonId, dialog, dialog.arguments.title, initialValue);
-		var colorTable = dialog.document.getElementById("colorTable");
-		colorTable.onclick = function(e) {
-			dialog.callFormInputHandler();
-			return false;
-		};
-		var colorForm = dialog.document.getElementById("HA-color-select-form");
-		colorForm.onsubmit = function (e) {
-			dialog.callFormInputHandler();
-			return false;
-		};
-		var colorUnset = dialog.document.getElementById("colorUnset");
-		colorUnset.onclick = function(e) {
-			dialog.document.getElementById(buttonId).value="";
-			dialog.callFormInputHandler();
-			return false;
-		};
-		dialog.document.getElementById(buttonId+"Current").style.backgroundColor = initialValue;
-		dialog.addButtons("ok", "cancel");
-	},
-	
-	/*
-	 * Set the color and close the ForeColor and the HiliteColor select color dialogues
-	 */
-	setColor : function(dialog, params) {
-		var editor = this.editor, element;
-		switch (dialog.arguments.buttonId) {
-			case "ForeColor":
-			case "HiliteColor":
-				var selection = editor._getSelection();
-				var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
-				var range = editor._createRange(selection);
-				if (editor._selectionEmpty(selection)) {
-					element = editor.getParentElement(selection, range);
-						// Set the color in the style attribute
-					this.processStyle(dialog, params, element, dialog.arguments.field);
-						// Remove the span tag if it has no more attribute
-					if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
-						editor.removeMarkup(element);
+	buildItemsConfig: function (element, buttonId) {
+		var itemsConfig = [];
+		var paletteItems = [];
+			// Standard colors palette (boxed)
+		if (!this.disableColorPicker) {
+			paletteItems.push({
+				xtype: 'container',
+				items: {
+					xtype: 'colorpalette',
+					itemId: 'color-palette',
+					colors: this.colors,
+					cls: 'color-palette',
+					value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '',
+					allowReselect: true,
+					listeners: {
+						select: {
+							fn: this.onSelect,
+							scope: this
+						}
 					}
-				} else if (statusBarSelection) {
-					element = statusBarSelection;
-						// Set the color in the style attribute
-					this.processStyle(dialog, params, element, dialog.arguments.field);
-						// Remove the span tag if it has no more attribute
-					if ((element.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
-						editor.removeMarkup(element);
+				}
+			});
+		}
+			// Custom colors palette (boxed)
+		if (this.colorsConfiguration) {
+			paletteItems.push({
+				xtype: 'container',
+				items: {
+					xtype: 'colorpalette',
+					itemId: 'custom-colors',
+					cls: 'htmlarea-custom-colors',
+					colors: this.colorsConfiguration,
+					value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '',
+					tpl: new Ext.XTemplate(
+						'<tpl for="."><a href="#" class="color-{1}" hidefocus="on"><em><span style="background:#{1}" unselectable="on">&#160;</span></em><span unselectable="on">{0}<span></a></tpl>'
+					),
+					allowReselect: true,
+					listeners: {
+						select: {
+							fn: this.onSelect,
+							scope: this
+						}
 					}
-				} else if (editor.endPointsInSameBlock()) {
-					element = editor._doc.createElement("span");
-						// Set the color in the style attribute
-					this.processStyle(dialog, params, element, dialog.arguments.field);
-					editor.wrapWithInlineElement(element, selection, range);
-					if (HTMLArea.is_gecko) {
-						range.detach();
-					}
 				}
-				break;
-			case "color":
-			default:
-				element = dialog.arguments.element;
-					// Set the color in the style attribute
-				this.processStyle(dialog, params, element, dialog.arguments.field);
-				break;
+			});
 		}
-		dialog.close();
+		itemsConfig.push({
+			xtype: 'container',
+			layout: 'hbox',
+			items: paletteItems
+		});
+		itemsConfig.push({
+			xtype: 'displayfield',
+			itemId: 'show-color',
+			cls: 'show-color',
+			width: 60,
+			height: 22,
+			helpTitle: this.localize(buttonId)
+		});
+		itemsConfig.push({
+			itemId: 'color',
+			cls: 'color',
+			width: 60,
+			minValue: 0,
+			value: (element && element.style[this.styleProperty[buttonId]]) ? HTMLArea.util.Color.colorToHex(element.style[this.styleProperty[buttonId]]).substr(1, 6) : '',
+			enableKeyEvents: true,
+			fieldLabel: this.localize(buttonId),
+			helpTitle: this.localize(buttonId),
+			listeners: {
+				change: {
+					fn: this.onChange,
+					scope: this
+				},
+				afterrender: {
+					fn: this.onAfterRender,
+					scope: this
+				}
+			}
+		});
+	 	return {
+			xtype: 'fieldset',
+			title: this.localize('color_title'),
+			defaultType: 'textfield',
+			labelWidth: 175,
+			defaults: {
+				helpIcon: false
+			},
+			items: itemsConfig
+		};
 	},
-	
 	/*
-	 * Initialize the case=color select color dialogue
-	 * This case is used by the Table Operations and QuickTag plugins
+	 * On select handler: set the value of the color field, display the new color and update the other palette
 	 */
-	selectColorCodeInit : function(dialog) {
-		var buttonId = dialog.arguments.buttonId;
-		var field = dialog.arguments.field;
-		dialog.content.innerHTML = this.renderPopupSelectColor(buttonId, dialog, this.localize(dialog.arguments.title), (field.value ? field.value : ""));
-		var colorTable = dialog.document.getElementById("colorTable");
-		colorTable.onclick = function(e) {
-			if(!e) var e = dialog.dialogWindow.event;
-			var target = e.target ? e.target : e.srcElement;
-			if (target.nodeType == 3) target = target.parentNode;
-			dialog.document.getElementById(buttonId).value = target.bgColor;
-			dialog.callFormInputHandler();
-			return false;
-		};
-		var colorUnset = dialog.document.getElementById("colorUnset");
-		colorUnset.onclick = function(e) {
-			dialog.document.getElementById(buttonId).value = "";
-			dialog.callFormInputHandler();
-			return false;
-		};
-		var colorForm = dialog.document.getElementById("HA-color-select-form");
-		colorForm.onsubmit = function(e) {
-			dialog.callFormInputHandler();
-			return false;
-		};
-		if (buttonId === "color") {
-			dialog.document.getElementById(buttonId+"Current").style.backgroundColor = field.value;
-		} else if (buttonId === "tag"){
-			dialog.document.getElementById(buttonId+"Current").style.backgroundColor = "";
+	onSelect: function (palette, color) {
+		this.dialog.find('itemId', 'color')[0].setValue(color);
+		this.showColor(color);
+		if (palette.getItemId() == 'color-palette') {
+			var customPalette = this.dialog.find('itemId', 'custom-colors')[0];
+			if (customPalette) {
+				customPalette.deSelect();
+			}
+		} else {
+			var standardPalette = this.dialog.find('itemId', 'color-palette')[0];
+			if (standardPalette) {
+				standardPalette.deSelect();
+			}
 		}
-		dialog.addButtons("ok", "cancel");
 	},
-	
 	/*
-	* Sets the color
-	*/
-	setColorInTag : function(dialog, params) {
-		dialog.arguments.field.insertColor(params.tag);
-		dialog.close();
+	 * Display the selected color
+	 */
+	showColor: function (color) {
+		if (color) {
+			this.dialog.find('itemId', 'show-color')[0].el.setStyle('backgroundColor', '#' + color);
+		}
 	},
-	
 	/*
-	* Applies the style found in "params" to the given element
-	*/
-	processStyle : function (dialog, params, element, field) {
-		if (element) {
-			for (var i in params) {
-				var val = params[i];
-				if (val && val.charAt(0) != "#") {
-					val = "#" + val;
-				}
-				switch (i) {
-					case "ForeColor":
-					case "HiliteColor":
-						element.style[this.styleProperty[i]] = val;
-						break;
-					case "color":
-						element.style.backgroundColor = val;
-						field.value = val;
-						break;
-				}
+	 * On change handler: display the new color and select it in the palettes, if it exists
+	 */
+	onChange: function (field, value) {
+		if (value) {
+			var color = value.toUpperCase();
+			this.showColor(color);
+			var standardPalette = this.dialog.find('itemId', 'color-palette')[0];
+			if (standardPalette) {
+				standardPalette.select(color);
 			}
+			var customPalette = this.dialog.find('itemId', 'custom-colors')[0];
+			if (customPalette) {
+				customPalette.select(color);
+			}
 		}
 	},
-	
-	/**
-	 * Making color selector table
+	/*
+	 * On after render handler: display the color
 	 */
-	renderPopupSelectColor : function (sID,dialog,title,initialValue) {
-		var editor = this.editor;
-		var cfgColors = this.colorsConfiguration;
-		var colorDef;
-		var szID = sID + "Current";
-		var sz;
-		var cPick = new Array("00","33","66","99","CC","FF");
-		var iColors = cPick.length;
-		var szColor = "";
-		var szColorId = "";
-		
-		sz = '<div class="title">' + title + '</div>';
-		sz += '<form id="HA-color-select-form"><fieldset>';
-		sz += '<div class="colorTableWrapper"><table class="colorTable" cellspacing="0" cellpadding="0" id="colorTable">';
-		var onMouseOut = ' onMouseout="document.getElementById(\'' + szID + '\').style.backgroundColor=\'\'; document.getElementById(\'' + sID + '\').value=\'\';"';
-		var onMouseOver = ' onMouseover="if(' + HTMLArea.is_ie + '){ if (event.srcElement.bgColor) { document.getElementById(\'' + szID + '\').style.backgroundColor = event.srcElement.bgColor; document.getElementById(\'' + sID + '\').value = event.srcElement.bgColor;} } else { if (event.target.bgColor) { document.getElementById(\'' + szID + '\').style.backgroundColor=event.target.bgColor; document.getElementById(\'' + sID + '\').value=event.target.bgColor;} };" ';
-			// Making colorPicker
-		if (!this.disableColorPicker) {
-			for ( var r = 0; r < iColors; r++) {
-				sz+='<tr>';
-				for (var g = iColors-1; g >= 0; g--) {
-					for (var b=iColors-1;b>=0;b--) {
-						szColor = cPick[r]+cPick[g]+cPick[b];
-						sz+='<td bgcolor="#'+szColor+'" title="#'+szColor+'"' + onMouseOut + onMouseOver +'>&nbsp;</td>';
-					}
+	onAfterRender: function (field) {
+		if (!Ext.isEmpty(field.getValue())) {
+			this.showColor(field.getValue());
+		}
+	},
+	/*
+	 * Open the dialogue window
+	 *
+	 * @param	string		title: the window title
+	 * @param	object		arguments: some arguments for the handler
+	 * @param	integer		dimensions: the opening width of the window
+	 * @param	object		tabItems: the configuration of the tabbed panel
+	 * @param	function	handler: handler when the OK button if clicked
+	 *
+	 * @return	void
+	 */
+	openDialogue: function (title, arguments, dimensions, items, handler) {
+		if (this.dialog) {
+			this.dialog.close();
+		}
+		this.dialog = new Ext.Window({
+			title: this.localize(title),
+			arguments: arguments,
+			cls: 'htmlarea-window',
+			border: false,
+			width: dimensions.width,
+			height: 'auto',
+			iconCls: arguments.buttonId,
+			listeners: {
+				close: {
+					fn: this.onClose,
+					scope: this
 				}
-				sz+='</tr>';
+			},
+			items: {
+				xtype: 'container',
+				layout: 'form',
+				defaults: {
+					labelWidth: 150
+				},
+				items: items
+			},
+			buttons: [
+				this.buildButtonConfig('Cancel', this.onCancel),
+				this.buildButtonConfig('OK', handler)
+			]
+		});
+		this.show();
+	},
+	/*
+	 * Set the color and close the dialogue
+	 */
+	setColor: function(button, event) {
+		this.restoreSelection();
+		var buttonId = this.dialog.arguments.buttonId;
+		var color = '#' + this.dialog.find('itemId', 'color')[0].getValue();
+		var selection = this.editor._getSelection();
+		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
+		var range = this.editor._createRange(selection);
+		if (this.editor._selectionEmpty(selection)) {
+			var element = this.editor.getParentElement(selection, range);
+				// Set the color in the style attribute
+			element.style[this.styleProperty[buttonId]] = color;
+				// Remove the span tag if it has no more attribute
+			if ((element.nodeName.toLowerCase() === 'span') && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
+				this.editor.removeMarkup(element);
 			}
-		}
-		
-			// Making specific color selector:
-		if (cfgColors) {
-			var iCfgColors = cfgColors.length;
-			if (iCfgColors && !this.disableColorPicker) {
-				sz += '<tr><td colspan="36"></td></tr>';
+		} else if (statusBarSelection) {
+			var element = statusBarSelection;
+				// Set the color in the style attribute
+			element.style[this.styleProperty[buttonId]] = color;
+				// Remove the span tag if it has no more attribute
+			if ((element.nodeName.toLowerCase() === 'span') && !HTMLArea.hasAllowedAttributes(element, this.allowedAttributes)) {
+				this.editor.removeMarkup(element);
 			}
-			onMouseOverTitle = ' onMouseover="if(' + HTMLArea.is_ie + '){ if (document.getElementById(event.srcElement.id+\'Value\')) { document.getElementById(\'' + szID + '\').style.backgroundColor = document.getElementById(event.srcElement.id+\'Value\').bgColor; document.getElementById(\'' + sID + '\').value = document.getElementById(event.srcElement.id+\'Value\').bgColor;} } else { if (document.getElementById(event.target.id+\'Value\')) { document.getElementById(\'' + szID + '\').style.backgroundColor=document.getElementById(event.target.id+\'Value\').bgColor; document.getElementById(\'' + sID + '\').value=document.getElementById(event.target.id+\'Value\').bgColor;} };" ';
-			for (var theColor = 0; theColor < iCfgColors; theColor++) {
-				colorDef = cfgColors[theColor];
-				szColor = colorDef[1];
-				sz += '<tr' + onMouseOut + '>';
-				sz += '<td id="colorDef' + theColor + 'Value"' + onMouseOver + ' style="width:36px;" colspan="6" bgcolor="'+szColor+'" title="'+szColor+'">&nbsp;</td>';
-				sz += '<td class="colorTitle" id="colorDef' + theColor + '"title="' + szColor + '"' + onMouseOverTitle + 'colspan="30">'+colorDef[0]+'</td>';
-				sz += '</tr>';
+		} else if (this.editor.endPointsInSameBlock()) {
+			var element = this.editor._doc.createElement('span');
+				// Set the color in the style attribute
+			element.style[this.styleProperty[buttonId]] = color;
+			this.editor.wrapWithInlineElement(element, selection, range);
+			if (HTMLArea.is_gecko) {
+				range.detach();
 			}
 		}
-		sz += '</table>';
-		sz += '<div class="space"></div>';
-		sz += '<label for="' + sID + '" class="fr">Color:</label>';
-		sz += '<div class="buttonColor" ';
-		sz += '		onMouseover="className += \' buttonColor-hilite\';" ';
-		sz += '		onMouseout="className = \'buttonColor\';">';
-		sz += '	<span id="' + szID + '" class="chooser">&nbsp;</span>';
-		sz += '	<span id="colorUnset" class="nocolor" title="' + "no_color" + '" ';
-		sz += '		onMouseover="className += \' nocolor-hilite\';" ';
-		sz += '		onMouseout="className = \'nocolor\';"';
-		sz += '	>&#x00d7;</span></div>';
-		sz += '<input type="text" name="' + sID + '" id="' + sID + '" value="' + initialValue + '" />';
-		sz += '</fieldset></form>';
-		return sz;
+		this.close();
+		event.stopEvent();
 	},
-	
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		var editor = this.editor;
-		if (this.getEditorMode() === "wysiwyg" && editor.isEditable()) {
-			var buttonId;
-			var statusBarSelection = editor.getPluginInstance("StatusBar") ? editor.getPluginInstance("StatusBar").getSelection() : null;
-			var parentElement = statusBarSelection ? statusBarSelection : editor.getParentElement();
-			var enabled = editor.endPointsInSameBlock() && !(editor._selectionEmpty(editor._getSelection()) && parentElement.nodeName.toLowerCase() == "body");
-			for (var i = 0, n = this.buttonList.length; i < n; ++i) {
-				buttonId = this.buttonList[i][0];
-				var obj = editor._toolbarObjects[buttonId];
-				if ((typeof(obj) !== "undefined")) {
-					obj.state("active", parentElement.style[this.styleProperty[buttonId]]);
-					obj.state("enabled", enabled);
-				}
-			}
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors, endPointsInSameBlock) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null,
+				parentElement = statusBarSelection ? statusBarSelection : this.editor.getParentElement(),
+				disabled = !endPointsInSameBlock || (selectionEmpty && /^body$/i.test(parentElement.nodeName));
+			button.setInactive(!parentElement.style[this.styleProperty[button.itemId]]);
+			button.setDisabled(disabled);
 		}
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3HtmlParser/typo3html-parser.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -64,7 +64,8 @@
 			id		: buttonId,
 			tooltip		: this.localize(buttonId + "-Tooltip"),
 			action		: "onButtonPress",
-			hide		: true
+			hide		: true,
+			hideInContextMenu: true
 		};
 		this.registerButton(buttonConfiguration);
 	},
@@ -84,61 +85,45 @@
 		this.clean();
 		return false;
 	},
-	
-	onGenerate : function () {
-		var doc = this.editor._doc;
-			// Function reference used on paste with older versions of Mozilla/Firefox in which onPaste is not fired
-		this.cleanLaterFunctRef = this.makeFunctionReference("clean");
-		HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], TYPO3HtmlParser.wordCleanHandler, true);
+	/*
+	 * This function gets called when the editor is generated
+	 */
+	onGenerate: function () {
+		var documentElement = Ext.get(Ext.isIE ? this.editor.document.body : this.editor.document.documentElement);
+		this.editor.iframe.mon(documentElement, 'paste', this.wordCleanHandler, this);
+		this.editor.iframe.mon(documentElement, 'dragdrop', this.wordCleanHandler, this);
+		this.editor.iframe.mon(documentElement, 'drop', this.wordCleanHandler, this);
 	},
 	
-	clean : function() {
+	clean: function() {
 		var editor = this.editor;
-		if (HTMLArea.is_safari) {
+		if (Ext.isWebKit) {
 			editor.cleanAppleStyleSpans(editor._doc.body);
 		}
 		var bookmark = editor.getBookmark(editor._createRange(editor._getSelection()));
 		var content = {
 			editorNo : this.editorNumber,
-			content	 : this.getPluginInstance("EditorMode").getInnerHTML()
+			content	 : editor.getInnerHTML()
 		};
 			// Server-based synchronous pasted content cleaning
 		this.postData(	this.parseHtmlModulePath,
 				content,
 				function(response) {
-					editor.getPluginInstance("EditorMode").setHTML(response);
+					editor.setHTML(response);
 					editor.selectRange(editor.moveToBookmark(bookmark));
 				},
 				false
 		);
+	},
+	/*
+	 * Handler for paste, dragdrop and drop events
+	 */
+	wordCleanHandler: function (event) {
+			// If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window
+		if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) {
+			HTMLArea.Dialog.TYPO3Image.close();
+		} else {
+			this.clean.defer(250, this);
+		}
 	}
 });
-
-/*
- * Closure avoidance for IE
- */
-TYPO3HtmlParser.cleanLater = function (editorNumber) {
-	var editor = RTEarea[editorNumber].editor;
-	editor.getPluginInstance("TYPO3HtmlParser").clean();
-};
-
-/*
- * Handler for paste, dragdrop and drop events
- */
-TYPO3HtmlParser.wordCleanHandler = function (ev) {
-	if (!ev) var ev = window.event;
-	var target = ev.target ? ev.target : ev.srcElement;
-	var owner = target.ownerDocument ? target.ownerDocument : target;
-	if (HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument
-		while (owner.parentElement) { owner = owner.parentElement; }
-	}
-	var editor = RTEarea[owner._editorNo].editor;
-	
-		// If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window
-	if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) {
-		HTMLArea.Dialog.TYPO3Image.close();
-	} else {
-		window.setTimeout("TYPO3HtmlParser.cleanLater(\'" + editor._editorNumber + "\');", 250);
-	}
-};
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TYPO3Link/typo3link.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -48,7 +48,7 @@
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.1",
+			version		: "1.2",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca/",
 			copyrightOwner	: "Stanislas Rolland",
@@ -84,7 +84,7 @@
 	 * The list of buttons added by this plugin
 	 */
 	buttonList : [
-		["CreateLink", "a,img", true, true],
+		["CreateLink", "a,img", false, true],
 		["UnLink", "a", false, false]
 	],
 	 
@@ -371,6 +371,14 @@
 				if (i.nodeType == 1 || i.nodeType == 11) this.cleanAllLinks(i, range, keepLinks);
 			}
 		}
+	},
+	/*
+	 * This function gets called when the toolbar is updated
+	 */
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable() && button.itemId === 'CreateLink') {
+			button.setDisabled(selectionEmpty && !button.isInContext(mode, selectionEmpty, ancestors));
+		}
 	}
 });
 
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/UndoRedo/undo-redo.js	(copie de travail)
@@ -1,7 +1,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2008-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -50,13 +50,12 @@
 		this.undoSteps = 25;
 			// The time interval at which undo samples are taken: 1/2 sec.
 		this.undoTimeout = 500;
-		this.undoTimer;
 		
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.0",
+			version		: "1.1",
 			developer	: "Stanislas Rolland",
 			developerUrl	: "http://www.sjbr.ca",
 			copyrightOwner	: "Stanislas Rolland",
@@ -77,8 +76,8 @@
 				id		: buttonId,
 				tooltip		: this.localize(buttonId.toLowerCase()),
 				action		: "onButtonPress",
-				context		: button[1],
-				hotKey		: (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:button[2])
+				hotKey		: (this.editorConfiguration.buttons[buttonId.toLowerCase()]?this.editorConfiguration.buttons[buttonId.toLowerCase()].hotKey:button[2]),
+				noAutoUpdate	: true
 			};
 			this.registerButton(buttonConfiguration);
 		}
@@ -97,25 +96,18 @@
 	/*
 	 * This function gets called when the editor is generated
 	 */
-	onGenerate : function () {
+	onGenerate: function () {
 			// Start undo snapshots
 		if (this.customUndo) {
-			var takeSnapshotFunctRef = this.makeFunctionReference("takeSnapshot");
-			this.undoTimer = window.setInterval(takeSnapshotFunctRef, this.undoTimeout);
+			Ext.TaskMgr.start({
+				run: this.takeSnapshot,
+				scope: this,
+				interval: this.undoTimeout
+			});
 		}
 	},
 	
 	/*
-	 * This function gets called when the editor is closing
-	 */
-	onClose : function () {
-			// Clear snapshot interval
-		window.clearInterval(this.undoTimer);
-			// Release undo/redo snapshots
-		this.undoQueue = null;
-	},
-	
-	/*
 	 * Take a snapshot of the current contents for undo
 	 */
 	takeSnapshot : function () {
@@ -132,7 +124,7 @@
 			newSnapshot = true;
 		}
 			// Get the html text
-		var text = this.getPluginInstance("EditorMode").getInnerHTML();
+		var text = this.editor.getInnerHTML();
 		
 		if (newSnapshot) {
 				// If previous slot contains the same text, a new one should not be used
@@ -182,7 +174,7 @@
 			}
 				// Get the bookmarked html text and remove the bookmark
 			if (bookmark) {
-				bookmarkedText = this.getPluginInstance("EditorMode").getInnerHTML();
+				bookmarkedText = this.editor.getInnerHTML();
 				var range = this.editor.moveToBookmark(bookmark);
 					// Restore Firefox selection
 				if (HTMLArea.is_gecko && !HTMLArea.is_opera && !HTMLArea.is_safari) {
@@ -192,7 +184,7 @@
 			}
 		}
 		return {
-			text		: this.getPluginInstance("EditorMode").getInnerHTML(),
+			text		: this.editor.getInnerHTML(),
 			bookmark	: bookmark,
 			bookmarkedText	: bookmarkedText
 		};
@@ -231,55 +223,63 @@
 	setContent : function (undoPosition) {
 		var bookmark = this.undoQueue[undoPosition].bookmark;
 		if (bookmark) {
-			this.getPluginInstance("EditorMode").setHTML(this.undoQueue[undoPosition].bookmarkedText);
-			this.editor.focusEditor();
+			this.editor.setHTML(this.undoQueue[undoPosition].bookmarkedText);
+			this.editor.focus();
 			this.editor.selectRange(this.editor.moveToBookmark(bookmark));
 			this.editor.scrollToCaret();
 		} else {
-			this.getPluginInstance("EditorMode").setHTML(this.undoQueue[undoPosition].text);
+			this.editor.setHTML(this.undoQueue[undoPosition].text);
 		}
 	},
 	
 	/*
 	 * This function gets called when the toolbar is updated
 	 */
-	onUpdateToolbar : function () {
-		this.updateButtonsState();
-	},
-	
-	/*
-	 * Update the state of the undo/redo buttons
-	 */
-	updateButtonsState : function () {
-		if (this.editor.getMode() == "wysiwyg" && this.editor.isEditable()) {
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode == 'wysiwyg' && this.editor.isEditable()) {
 			if (this.customUndo) {
-				if (this.isButtonInToolbar("Undo")) {
-					this.editor._toolbarObjects.Undo.state("enabled", this.undoPosition > 0);
+				switch (button.itemId) {
+					case 'Undo':
+						button.setDisabled(this.undoPosition == 0);
+						break;
+					case 'Redo':
+						button.setDisabled(this.undoPosition >= this.undoQueue.length-1);
+						break;
 				}
-				if (this.isButtonInToolbar("Redo")) {
-					this.editor._toolbarObjects.Redo.state("enabled", this.undoPosition < this.undoQueue.length-1);
-				}
 			} else {
 				try {
-					if (this.isButtonInToolbar("Undo")) {
-						this.editor._toolbarObjects.Undo.state("enabled", this.editor._doc.queryCommandEnabled("Undo"));
-					}
-					if (this.isButtonInToolbar("Redo")) {
-						this.editor._toolbarObjects.Redo.state("enabled", this.editor._doc.queryCommandEnabled("Redo"));
-					}
+					button.setDisabled(!this.editor._doc.queryCommandEnabled(button.itemId));
 				} catch (e) {
-					if (this.isButtonInToolbar("Undo")) {
-						this.editor._toolbarObjects.Undo.state("enabled", false);
-					}
-					if (this.isButtonInToolbar("Redo")) {
-						this.editor._toolbarObjects.Redo.state("enabled", false);
-					}
+					button.setDisabled(true);
 				}
 			}
+		} else {
+			button.setDisabled(!button.textMode);
 		}
 	},
 	
 	/*
+	 * Update the state of the undo/redo buttons
+	 */
+	updateButtonsState: function () {
+		var mode = this.getEditorMode(),
+			selectionEmpty = true,
+			ancestors = null;
+		if (mode === 'wysiwyg') {
+			selectionEmpty = this.editor._selectionEmpty(this.editor._getSelection());
+			ancestors = this.editor.getAllAncestors();
+		}
+		var button = this.getButton('Undo');
+		if (button) {
+			this.onUpdateToolbar(button, mode, selectionEmpty, ancestors)
+		}
+		var button = this.getButton('Redo');
+		if (button) {
+			this.onUpdateToolbar(button, mode, selectionEmpty, ancestors)
+		}
+	},
+	
+	/*
 	 * This function gets called when the button was pressed.
 	 *
 	 * @param	object		editor: the editor instance
@@ -291,7 +291,7 @@
 			// Could be a button or its hotkey
 		var buttonId = this.translateHotKey(id);
 		buttonId = buttonId ? buttonId : id;
-		if (this.isButtonInToolbar(buttonId) && !this.editor._toolbarObjects[buttonId].disabled) {
+		if (this.getButton(buttonId) && !this.getButton(buttonId).disabled) {
 			if (this.customUndo) {
 				this[buttonId.toLowerCase()]();
 			} else {
Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea-edited-content.css	(copie de travail)
@@ -5,6 +5,7 @@
 	margin:0;
 	padding:3px;
 	background-color:#ffffff;
+	border-width:0;
 }
 
 /* Selectors for the Table Operations plugin */
@@ -16,7 +17,7 @@
 
 /* Make language marks visible */
 body.htmlarea-show-language-marks *[lang] {
-	background: url("images/language-marker.gif") left bottom no-repeat; padding-left: 14px; text-decoration: underline;
+	background: url("images/language-marker.gif") left top no-repeat; padding-left: 14px; text-decoration: underline;
 }
 
 /* Selectors for the Abbreviation plugin */
Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css	(révision 6908)
+++ typo3/sysext/rtehtmlarea/htmlarea/skins/default/htmlarea.css	(copie de travail)
@@ -1,100 +1,103 @@
 /* Selectors for the htmlArea RTE editor */
 .htmlarea {
 	background-color:#fff;
- 	margin:0;padding:0;
+ 	margin:0 2px 0 0;padding:0;
 }
-.resizable {
-	background-color:transparent;
-	padding-right:7px;
-	padding-bottom:6px;
-	background-image: url("images/resize.gif");
-	background-position: bottom right;
-	background-repeat: no-repeat;
-}
 .pleasewait {
- 	position:relative;top:0px;text-align:left;
- 	font-size:8pt;
+ 	position:relative;
  	margin-top:30px;
+ 	padding: 20px 0 20px 50px;
+ 	font-size: 11px !important;
+ 	text-align:left;
+	background: url('images/loading.gif') no-repeat 10px center;
+	vertical-align: middle;
+	color: #7F8083;
 }
 .editorWrap {
  	margin:0;padding:0;
 }
-/* Selectors for the editor toolbar */
-.htmlarea div.toolbar {
-	background-color:#e4e0db;cursor:default;
-	width:100%;
-	border:1px solid #e4e0db;border-bottom:1px solid #000;margin:0;padding:0px 0px 2px 0px;
+.editorWrap textarea {
+	border: 1px solid #A2AAB8;
+	border-style:solid;
+	border-color:#A2AAB8;
+	border-width:0px 1px 1px 1px;
+	padding:0px 1px;
+	margin:0;
 }
-.htmlarea .toolbar ul {
-	background-color:transparent;
-	list-style-type:none;list-style-image:none;
-	border-style:none;margin:0;padding:0;
+.editorWrap .resizable {
+	background-image: url("images/resize.gif");
+	background-position: bottom right;
+	background-repeat: no-repeat;
 }
-.htmlarea .toolbar ul.tb-line {
-	clear:both;
+.editorWrap div.resizable {
+	padding-right: 7px;
+	padding-bottom: 5px;
 }
-.htmlarea .toolbar ul.tb-group {
-	clear:none;float:left;
+/* Selectors for the editor toolbar */
+.htmlarea .toolbar {
+	background-color:#E4E0DB;cursor:default;
+	border:1px solid #E4E0DB;
+	border-bottom:0px;
+	margin:0;
+	padding:2px 0px;
+	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
 }
-.htmlarea .toolbar ul li {
+.htmlarea .toolbar .tb-group {
+	clear:none;
 	float:left;
-	background-color:transparent;
-	font:11px Tahoma,Verdana,sans-serif;
-	border-style:none;padding:0;
+	margin:1px 2px 0px 0px;
+	padding:0;
 }
-.htmlarea .toolbar ul.tb-line li {
-	margin:1px 0px 1px 0px;
-}
-.htmlarea .toolbar ul.free-float li, .htmlarea .toolbar ul.tb-group li {
-	height:22px;
+.htmlarea .toolbar .x-form-item {
+	float: left;
 	margin:0;
 }
-.htmlarea .toolbar label {
-	float:left;
+.htmlarea .toolbar .x-form-item-label {
 	vertical-align:middle;
-	height:22px;
-	background-color:#e4e0db;
+	background-color:transparent;
+	border-style:none;
 	margin:0;padding:3px 3px 0px 3px;
 }
-.htmlarea .toolbar button {
-	vertical-align:top;
-	background-color:#e4e0db;background-position:1px 1px;background-repeat:no-repeat;color:ButtonText;
-	border:1px solid #e4e0db;margin:0;padding:1px;
+.htmlarea .toolbar .button {
+	background-color:transparent;color:ButtonText;background-position:10px 0px;background-repeat:no-repeat;
 	width:22px;height:22px;
+	border-style:solid;border-color:#EFEFF4;border-width:1px;
+	margin:0 0 1px 0;padding:0;
+	float:left;
 }
-.htmlarea .toolbar button div.buttonImgContainer {
-	position:relative;top:0;left:0;
-	width:18px;height:18px;overflow:hidden;
+.htmlarea .toolbar .x-btn-mc, .htmlarea .toolbar .x-btn-ml, .htmlarea .toolbar .x-btn-mr, .htmlarea .toolbar .x-btn-tc, .htmlarea .toolbar .x-btn-tl, .htmlarea .toolbar .x-btn-tr, .htmlarea .toolbar .x-btn-bl, .htmlarea .toolbar .x-btn-bc, .htmlarea .toolbar .x-btn-br {
+	background-color:transparent;background-image:none;
+	border-style:none;
 	margin:0;padding:0;
 }
-.htmlarea .toolbar .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");}
-.htmlarea .toolbar .Big {background-image:url("images/InlineElements/big.gif");}
-.htmlarea .toolbar .Bold {background-image:url("images/InlineElements/bold.gif");}
-.htmlarea .toolbar .Citation {background-image:url("images/InlineElements/citation.gif");}
-.htmlarea .toolbar .Code {background-image:url("images/InlineElements/code.gif");}
-.htmlarea .toolbar .Definition {background-image:url("images/InlineElements/definition.gif");}
-.htmlarea .toolbar .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");}
-.htmlarea .toolbar .Emphasis {background-image:url("images/InlineElements/emphasis.gif");}
-.htmlarea .toolbar .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");}
-.htmlarea .toolbar .Italic {background-image:url("images/InlineElements/italic.gif");}
-.htmlarea .toolbar .Keyboard {background-image:url("images/InlineElements/keyboard.gif");}
-.htmlarea .toolbar .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");}
-.htmlarea .toolbar .Quotation {background-image:url("images/InlineElements/quotation.gif");}
-.htmlarea .toolbar .Sample {background-image:url("images/InlineElements/sample.gif");}
-.htmlarea .toolbar .Small {background-image:url("images/InlineElements/small.gif");}
-.htmlarea .toolbar .Span {background-image:url("images/InlineElements/span.gif");}
-.htmlarea .toolbar .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");}
-.htmlarea .toolbar .Strong {background-image:url("images/InlineElements/strong.gif");}
-.htmlarea .toolbar .Subscript {background-image:url("images/InlineElements/subscript.gif");}
-.htmlarea .toolbar .Superscript {background-image:url("images/InlineElements/superscript.gif");}
-.htmlarea .toolbar .Underline {background-image:url("images/InlineElements/underline.gif");}
-.htmlarea .toolbar .Variable {background-image:url("images/InlineElements/variable.gif");}
-.htmlarea .toolbar .LeftToRight {background-image:url("images/ed_left_to_right.gif");}
-.htmlarea .toolbar .RightToLeft {background-image:url("images/ed_right_to_left.gif");}
-.htmlarea .toolbar .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");}
-.htmlarea .toolbar .Indent {background-image:url("images/BlockElements/indent.gif");}
-.htmlarea .toolbar .Outdent {background-image:url("images/BlockElements/outdent.gif");}
-.htmlarea .toolbar .Blockquote {background-image:url("images/BlockElements/blockquote.gif");}
+.htmlarea .toolbar .BiDiOverride, .htmlarea-context-menu .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");}
+.htmlarea .toolbar .Big, .htmlarea-context-menu .Big {background-image:url("images/InlineElements/big.gif");}
+.htmlarea .toolbar .Bold, .htmlarea-context-menu .Bold {background-image:url("images/InlineElements/bold.gif");}
+.htmlarea .toolbar .Citation, .htmlarea-context-menu .Citation {background-image:url("images/InlineElements/citation.gif");}
+.htmlarea .toolbar .Code, .htmlarea-context-menu .Code {background-image:url("images/InlineElements/code.gif");}
+.htmlarea .toolbar .Definition, .htmlarea-context-menu .Definition {background-image:url("images/InlineElements/definition.gif");}
+.htmlarea .toolbar .DeletedText, .htmlarea-context-menu .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");}
+.htmlarea .toolbar .Emphasis, .htmlarea-context-menu .Emphasis {background-image:url("images/InlineElements/emphasis.gif");}
+.htmlarea .toolbar .InsertedText, .htmlarea-context-menu .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");}
+.htmlarea .toolbar .Italic, .htmlarea-context-menu .Italic {background-image:url("images/InlineElements/italic.gif");}
+.htmlarea .toolbar .Keyboard, .htmlarea-context-menu .Keyboard {background-image:url("images/InlineElements/keyboard.gif");}
+.htmlarea .toolbar .MonoSpaced, .htmlarea-context-menu .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");}
+.htmlarea .toolbar .Quotation, .htmlarea-context-menu .Quotation {background-image:url("images/InlineElements/quotation.gif");}
+.htmlarea .toolbar .Sample, .htmlarea-context-menu .Sample {background-image:url("images/InlineElements/sample.gif");}
+.htmlarea .toolbar .Small, .htmlarea-context-menu .Small {background-image:url("images/InlineElements/small.gif");}
+.htmlarea .toolbar .Span, .htmlarea-context-menu .Span {background-image:url("images/InlineElements/span.gif");}
+.htmlarea .toolbar .StrikeThrough, .htmlarea-context-menu .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");}
+.htmlarea .toolbar .Strong, .htmlarea-context-menu .Strong {background-image:url("images/InlineElements/strong.gif");}
+.htmlarea .toolbar .Subscript, .htmlarea-context-menu .Subscript {background-image:url("images/InlineElements/subscript.gif");}
+.htmlarea .toolbar .Superscript, .htmlarea-context-menu .Superscript {background-image:url("images/InlineElements/superscript.gif");}
+.htmlarea .toolbar .Underline, .htmlarea-context-menu .Underline {background-image:url("images/InlineElements/underline.gif");}
+.htmlarea .toolbar .Variable, .htmlarea-context-menu .Variable {background-image:url("images/InlineElements/variable.gif");}
+.htmlarea .toolbar .LeftToRight, .htmlarea-context-menu .LeftToRight {background-image:url("images/ed_left_to_right.gif");}
+.htmlarea .toolbar .RightToLeft, .htmlarea-context-menu .RightToLeft {background-image:url("images/ed_right_to_left.gif");}
+.htmlarea .toolbar .ShowLanguageMarks, .htmlarea-context-menu .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");}
+.htmlarea .toolbar .Indent, .htmlarea-context-menu .Indent {background-image:url("images/BlockElements/indent.gif");}
+.htmlarea .toolbar .Outdent, .htmlarea-context-menu .Outdent {background-image:url("images/BlockElements/outdent.gif");}
+.htmlarea .toolbar .Blockquote, .htmlarea-context-menu .Blockquote {background-image:url("images/BlockElements/blockquote.gif");}
 .htmlarea .toolbar .InsertParagraphBefore, .htmlarea-context-menu .InsertParagraphBefore {background-image:url("images/BlockElements/insertParagraphBefore.gif");}
 .htmlarea .toolbar .InsertParagraphAfter, .htmlarea-context-menu .InsertParagraphAfter {background-image:url("images/BlockElements/insertParagraphAfter.gif");}
 .htmlarea .toolbar .JustifyLeft, .htmlarea-context-menu .JustifyLeft {background-image:url("images/BlockElements/justifyLeft.gif");}
@@ -103,136 +106,172 @@
 .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/BlockElements/justifyFull.gif");}
 .htmlarea .toolbar .DefinitionList, .htmlarea-context-menu .DefinitionList {background-image:url("images/definitionList.gif");}
 .htmlarea .toolbar .DefinitionItem, .htmlarea-context-menu .DefinitionItem {background-image:url("images/definitionItem.gif");}
-.htmlarea .toolbar .InsertOrderedList {background-image:url("images/ed_list_num.gif");}
-.htmlarea .toolbar .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");}
-.htmlarea .toolbar .ForeColor {background-image:url("images/ed_color_fg.gif");}
-.htmlarea .toolbar .HiliteColor {background-image:url("images/ed_color_bg.gif");}
-.htmlarea .toolbar .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");}
-.htmlarea .toolbar .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");}
-.htmlarea .toolbar .InsertHorizontalRule {background-image:url("images/ed_hr.gif");}
-.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink {background-image:url("images/ed_link.gif");}
+.htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/ed_list_num.gif");}
+.htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");}
+.htmlarea .toolbar .InsertHorizontalRule, .htmlarea-context-menu .InsertHorizontalRule {background-image:url("images/BlockElements/insertHorizontalRule.gif");}
+.htmlarea .toolbar .ForeColor, .htmlarea-context-menu .ForeColor, .htmlarea-window .ForeColor {background-image:url("images/ed_color_fg.gif");}
+.htmlarea .toolbar .HiliteColor, .htmlarea-context-menu .HiliteColor, .htmlarea-window .HiliteColor {background-image:url("images/ed_color_bg.gif");}
+.htmlarea .toolbar .InsertSmiley, .htmlarea-context-menu .InsertSmiley, .htmlarea-window .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");}
+.htmlarea .toolbar .InsertCharacter, .htmlarea-context-menu .InsertCharacter, .htmlarea-window .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");}
+.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink, .htmlarea-window .CreateLink {background-image:url("images/ed_link.gif");}
 .htmlarea .toolbar .UnLink, .htmlarea-context-menu .UnLink {background-image:url("images/ed_unlink.gif");}
-.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage {background-image:url("images/ed_image.gif");}
-.htmlarea .toolbar .InsertTable {background-image:url("images/insert_table.gif");}
-.htmlarea .toolbar .UserElements {background-image:url("images/UserElements/ed_user.gif");}
-.htmlarea .toolbar .FindReplace {background-image:url("images/FindReplace/ed_find.gif");}
-.htmlarea .toolbar .SpellCheck { background-image:url("images/SpellChecker/spell-check.gif"); }
-.htmlarea .toolbar .InsertTag { background-image:url("images/QuickTag/ed_quicktag.gif"); }
-.htmlarea .toolbar .Acronym { background-image:url("images/Acronym/ed_acronym.gif"); }
-.htmlarea .toolbar .RemoveFormat { background-image:url("images/RemoveFormat/ed_clean.gif"); }
+.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage, .htmlarea-window .InsertImage {background-image:url("images/ed_image.gif");}
+.htmlarea .toolbar .InsertTable, .htmlarea-context-menu .InsertTable, .htmlarea-window .InsertTable {background-image:url("images/insert_table.gif");}
+.htmlarea .toolbar .UserElements, .htmlarea-context-menu .UserElements, .htmlarea-window .UserElements {background-image:url("images/UserElements/ed_user.gif");}
+.htmlarea .toolbar .FindReplace, .htmlarea-context-menu .FindReplace, .htmlarea-window .FindReplace {background-image:url("images/FindReplace/ed_find.gif");}
+.htmlarea .toolbar .SpellCheck, .htmlarea-context-menu .SpellCheck, .htmlarea-window .SpellCheck { background-image:url("images/SpellChecker/spell-check.gif"); }
+.htmlarea .toolbar .InsertTag, .htmlarea-context-menu .InsertTag, .htmlarea-window .InsertTag { background-image:url("images/QuickTag/ed_quicktag.gif"); }
+.htmlarea .toolbar .Acronym, .htmlarea-context-menu .Acronym, .htmlarea-window .Acronym { background-image:url("images/Acronym/ed_acronym.gif"); }
+.htmlarea .toolbar .RemoveFormat, .htmlarea-context-menu .RemoveFormat, .htmlarea-window .RemoveFormat { background-image:url("images/RemoveFormat/ed_clean.gif"); }
 .htmlarea .toolbar .SplitBlock {background-image:url("images/ed_splitblock.gif"); }
 .htmlarea .toolbar .TextMode { background-image:url("images/ed_html.gif"); }
-.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy  { background-image:url("images/ed_copy.gif");}
-.htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut  { background-image:url("images/ed_cut.gif");}
+.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy { background-image:url("images/ed_copy.gif");}
+.htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut { background-image:url("images/ed_cut.gif");}
 .htmlarea .toolbar .Paste, .htmlarea-context-menu .Paste { background-image:url("images/ed_paste.gif");}
-.htmlarea .toolbar .Undo { background-image:url("images/ed_undo.gif");}
-.htmlarea .toolbar .Redo { background-image:url("images/ed_redo.gif");}
-.htmlarea .toolbar .About { background-image:url("images/ed_about.gif");}
+.htmlarea-context-menu .DeleteTarget {background-image:url("images/ed_delete.gif");}
+.htmlarea .toolbar .Undo, .htmlarea-context-menu .Undo { background-image:url("images/ed_undo.gif");}
+.htmlarea .toolbar .Redo, .htmlarea-context-menu .Redo { background-image:url("images/ed_redo.gif");}
+.htmlarea .toolbar .About, .htmlarea-context-menu .About, .htmlarea-window .About { background-image:url("images/ed_about.gif");}
 .htmlarea .toolbar .ShowHelp { background-image:url("images/TYPO3ViewHelp/module_help.gif");}
 .htmlarea .toolbar .TO-toggle-borders, .htmlarea-context-menu .TO-toggle-borders {background-image:url("images/TableOperations/toggle-borders.gif");}
-.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");}
+.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop, .htmlarea-window .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");}
 .htmlarea .toolbar .TO-table-restyle, .htmlarea-context-menu .TO-table-restyle {background-image:url("images/TableOperations/table-restyle.gif");}
-.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");}
+.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop, .htmlarea-window .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");}
 .htmlarea .toolbar .TO-row-insert-above, .htmlarea-context-menu .TO-row-insert-above {background-image:url("images/TableOperations/row-insert-above.gif");}
 .htmlarea .toolbar .TO-row-insert-under, .htmlarea-context-menu .TO-row-insert-under {background-image:url("images/TableOperations/row-insert-under.gif");}
 .htmlarea .toolbar .TO-row-delete, .htmlarea-context-menu .TO-row-delete {background-image:url("images/TableOperations/row-delete.gif");}
 .htmlarea .toolbar .TO-row-split, .htmlarea-context-menu .TO-row-split {background-image:url("images/TableOperations/row-split.gif");}
-.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");}
+.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop, .htmlarea-window .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");}
 .htmlarea .toolbar .TO-col-insert-before, .htmlarea-context-menu .TO-col-insert-before {background-image:url("images/TableOperations/col-insert-before.gif");}
 .htmlarea .toolbar .TO-col-insert-after, .htmlarea-context-menu .TO-col-insert-after {background-image:url("images/TableOperations/col-insert-after.gif");}
 .htmlarea .toolbar .TO-col-delete, .htmlarea-context-menu .TO-col-delete {background-image:url("images/TableOperations/col-delete.gif");}
 .htmlarea .toolbar .TO-col-split, .htmlarea-context-menu .TO-col-split {background-image:url("images/TableOperations/col-split.gif");}
-.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");}
+.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop, .htmlarea-window .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");}
 .htmlarea .toolbar .TO-cell-insert-before, .htmlarea-context-menu .TO-cell-insert-before {background-image:url("images/TableOperations/cell-insert-before.gif");}
 .htmlarea .toolbar .TO-cell-insert-after, .htmlarea-context-menu .TO-cell-insert-after {background-image:url("images/TableOperations/cell-insert-after.gif");}
 .htmlarea .toolbar .TO-cell-delete, .htmlarea-context-menu .TO-cell-delete {background-image:url("images/TableOperations/cell-delete.gif");}
 .htmlarea .toolbar .TO-cell-split, .htmlarea-context-menu .TO-cell-split {background-image:url("images/TableOperations/cell-split.gif");}
 .htmlarea .toolbar .TO-cell-merge, .htmlarea-context-menu .TO-cell-merge {background-image:url("images/TableOperations/cell-merge.gif");}
-.htmlarea .toolbar button.buttonHover {
+.htmlarea .toolbar .buttonHover {
 	border:1px solid;border-color:#e4e0db #999999 #999999 #e4e0db;
 }
-.htmlarea .toolbar button.buttonActive {
+.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive {
 	border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
-	padding:2px 0px 0px 2px;
+	background-color:ButtonHighlight;
 }
-.htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive {
+.htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive {
 	background-color:ButtonHighlight;
-	border:1px solid;border-color:#999999 #e4e0db #e4e0db #999999;
-	padding:2px 0px 0px 2px;
 	text-decoration:none;
 }
-.htmlarea .toolbar div.indicator {
-	margin:4px 0px 0px 0px;
-	padding:0px 3px;
-	overflow:hidden;
-	width:20px;
+.htmlarea .toolbar .indicator {
+	background-color:white;cursor:default;
+	width:20px;overflow:hidden;
+	height:16px;
 	text-align:center;
-	cursor:default;
 	border:1px solid ButtonShadow;
+	margin:3px 1px 4px 1px;padding:0 3px;
+	float:left;
 }
-.htmlarea .toolbar button.buttonDisabled {
+.htmlarea .toolbar .buttonDisabled {
 	filter: alpha(opacity=25);
 	-moz-opacity: 0.25;
 	opacity: 0.25;
 }
-.htmlarea .toolbar div.separator {
-	position:relative;
-	border-left:1px solid #999;margin:0 3px;padding:0;
-	width:0px;height:20px;
-}
-.htmlarea .toolbar li.tb-first-cell .separator {
-	border-style:none;margin:0;padding:0;
-}
-.htmlarea .toolbar div.space {
+.htmlarea .toolbar .separator {
+	border:1px solid #999;
+	width:7px;height:23px;
 	float:left;
+}
+.htmlarea .toolbar .space {
 	height:22px;
-	margin:0;padding:0px 1px 0px 0px;
+	border-style:none;
+	margin:0;padding:0 1px;
+	float:left;
 }
-.htmlarea .toolbar select {
+.htmlarea .toolbar .select {
 	font:10px Tahoma,Verdana,sans-serif;
 	height:18px;
 	border:1px solid #A2AAB8;
-	margin:0;padding:1px;
+	margin:0 0 3px 0;padding:1px;
 }
-.htmlarea .toolbar select, .htmlarea .toolbar select:hover, .htmlarea .toolbar select:active {
+.htmlarea .toolbar .select, .htmlarea .toolbar .select:hover, .htmlarea .toolbar .select:active {
 	background-color:#fff;color:ButtonText;
 }
-.htmlarea .toolbar select.buttonDisabled {
+.htmlarea .toolbar .buttonDisabled {
 	background-color:#e4e0db;
 }
 .htmlarea .editorIframe {
 	clear:both;
 	width:100%;
-	border:1px solid #000;border-top:0px;margin:0;padding:0;
+	border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db;
+	margin:0;padding:0;
 }
 .htmlarea .noStatusBar {
 	border-bottom:1px solid #000;
 }
 .htmlarea .statusBar {
-	clear:both;
-	background-color:#e4e0db;color:ButtonText;
-	font:11px Tahoma,Verdana,sans-serif;
-	width:100%;
-	border:1px solid;border-color:ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;margin:0;padding:0;
+	color:ButtonText;
+	background-color:#e4e0db;
+	font-size:10px;
+	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
+	border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8;
+	margin: 0;
+	padding: 0 3px;
+	line-height: 20px;
 }
-.htmlarea .statusBarTree {
-	padding:2px 5px;
-}
 .htmlarea .statusBar .statusBarTree a {
-	color:#00f;
-	padding:2px 5px;
+	color:ButtonText;
+	text-decoration:none;
+	font-weight:bold;
+ 	padding:0px 5px;
 }
 .htmlarea .statusBar .statusBarTree a:visited {
 	color:#00f;
 }
 .htmlarea .statusBar .statusBarTree a:hover {
-	background-color:Highlight;color:HighlightText;
-	border:1px solid HighlightText;padding:1px 4px;
+	text-decoration: underline;
 }
-.htmlarea .statusBarTextMode {
-	padding:2px 5px;
-}
 /* Selectors for dialogue windows */
+.htmlarea-window .x-tab-panel-body {
+	background-color: #EFEFF4;
+}
+.htmlarea-window .x-fieldset {
+	margin: 3px;
+}
+.htmlarea-window .x-form-item-label {
+	text-align: right;
+	vertical-align: middle;
+	padding: 4px 5px 0 5px;
+}
+.htmlarea-window .x-btn-text {
+	font-weight: normal;
+	color: #000000;
+}
+.htmlarea-window .x-form-check-wrap input {
+	vertical-align: middle;
+}
+.htmlarea-window .show-color {
+	margin-top: 10px;
+	margin-left: 5px;
+	border-style: solid;
+	border-width: 1px;
+	border-color: white;
+}
+.htmlarea-custom-colors a {
+	border-style: none;
+	float: none;
+	display: block;
+	width: 100%;
+}
+.htmlarea-custom-colors em {
+	display: block;
+	border: 1px solid;
+	border-color: #C5C5D5;
+	width: 100%;
+}
+.htmlarea-custom-colors em span {
+	width: 100%;
+}
 .popupwin {
 	background-color:#e4e0db;color:ButtonText;
 	font:11px Tahoma,Verdana,sans-serif;
@@ -393,53 +432,6 @@
 .popupwin input.shorter-value {
 	width:17em;
 }
-/* Selectors for TYPO3 Color dialogue */
-.popupwin .buttonColor {
-	cursor:default;
-	border-style:solid;border-width:1px;border-color:ButtonHighlight ButtonShadow ButtonHighlight ButtonHighlight;
-	padding:1px;margin:2px 10px 0 0;
-	height:1em;
-	white-space:nowrap;
-}
-.popupwin div.buttonColor {
-	float:left;
-	vertical-align:middle;
-}
-.popupwin .buttonColor-hilite {
-	border-color:black black black black;
-}
-.popupwin .buttonColor .chooser, .popupwin .buttonColor .nocolor {
-	height:0.6em;
-	border-width:1px;border-style:solid;border-width:1px;border-color:ButtonShadow ButtonHighlight ButtonShadow ButtonShadow;
-	padding:0 1em;
-}
-.popupwin .buttonColor .nocolor {
-	padding:0;
-}
-.popupwin .buttonColor .nocolor-hilite {
-	background-color:#fff;color:#f00;cursor:pointer;
-}
-.popupwin .colorTableWrapper {
-}
-.popupwin .colorTable {
-	width:350px;
-}
-.popupwin .currentColor {
-	width:20px;height:20px;
-	border:black 1px solid;
-	margin:0pt 15pt;
-}
-.popupwin .colorTable tr {
-	height:6px;
-}
-.popupwin .colorTable td {
-	width:6px;
-	cursor:pointer;
-}
-.popupwin .colorTable td.colorTitle {
-	width:auto;
-	padding-left:10px;
-}
 /* Selectors for the Default Image dialogue */
 .htmlarea-default-image #image, .htmlarea-default-image #alt {
 	white-space:nowrap;
@@ -460,22 +452,18 @@
 	white-space:nowrap;
 }
 /* Selectors for the InsertSmiley plugin */
-.htmlarea-insert-smiley div.smileytable {
-	text-align:center;
-	height:130px;margin-bottom:10px;
+.htmlarea-window .emoticon-array {
+	padding: 10px;
+	width: 150px;
 }
-.htmlarea-insert-smiley #smileytable {
-	height:130px;
+.htmlarea-window .emoticon {
+    display: block;
+    float: left;
+    padding: 5px;
+    width: 20px;
+    height: 20px;
+    vertical-align: middle;
 }
-.htmlarea-insert-smiley #smileytable tr {
-	height:25px;
-}
-.htmlarea-insert-smiley #smileytable td {
-	width:35px;height:25px;
-}
-.htmlarea-insert-smiley #smileytable td img {
-	border-style:none;
-}
 /* Selectors for the FindReplace dialogue */
 .htmlarea-find-replace .long-label {
 	text-align:left;
@@ -505,47 +493,6 @@
 .htmlarea-character-map td.character-hilite {
 	background-color:Highlight;color:HighlightText;
 }
-/* Selectors for the DefaultColor dialogue */
-.htmlarea-default-color #selectedColor div {
-	white-space:nowrap;
-}
-.htmlarea-default-color #ColorPreview {
-	height:21px;width:50px;
-	float:left;
-	background-color:#000;
-}
-.htmlarea-default-color #ColorHex {
-	font-size:12px;
-	display:inline;
-	vertical-align:top;
-	margin-left:5px;
-}
-.htmlarea-default-color table {
-	margin:5px 0;
-}
-.htmlarea-default-color .color {
-	width:10px;height:10px;
-	cursor:pointer;
-}
-/* Selectors for the QuickTag dialogue */
-.htmlarea-quick-tag #tag {
-	text-align:center;
-	padding:3px;
-	background-color:#E9E9E9;
-}
-.htmlarea-quick-tag #tagopen {
-	background-color: #E9E9E9;
-	width:370px;
-	border-style:none;
-}
-.htmlarea-quick-tag strong {
-	font-size:14px;
-}
-.htmlarea-quick-tag #showselect {
-	position:absolute;left:7px;top:81px;
-	width:150px;height:13px;
-	z-index:100;visibility:visible;
-}
 /* Selectors for the SpellChecker dialogue */
 .htmlarea-spell-check .dictionaries {
 	float:right;
@@ -599,32 +546,23 @@
 }
 /* Selectors for the ContextMenu plugin */
 .htmlarea-context-menu {
-	position:absolute;top:-1000px;left:-1000px;z-index:1000;
-	background-color:#cdf;cursor:default;
-	font:11px Tahoma,Verdana,sans-serif;
-	list-style:none;
-	border:1px solid #aca899;margin:0;padding:2px;
+	background-color:#EFEFF4;
+	color:#212424;
+	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
+	font-size:10px;
 }
-.htmlarea-context-menu li {
-	background-color:#cdf;
-	border:1px solid #cdf;margin:1px 0;padding:0;
-	font-size:11px;
+.htmlarea-context-menu .button {
+	background-color:transparent;
+	background-repeat:no-repeat;
+	background-position:0px 0px;
 }
-.htmlarea-context-menu li button {
-	text-align:left;vertical-align:middle;
-	background-color:transparent;background-repeat:no-repeat;background-position:0px 0px;
-	height:19px;width:20px;
-	border-style:none;margin:0px 3px 0px 0;padding:0;
+.htmlarea-context-menu .separator {
+	border-top:1px solid #A2AAB8;
 }
-.htmlarea-context-menu li .button img {
-	width:18px;height:18px;
-}
-.htmlarea-context-menu li.separator {
-	border-top:1px solid #fff;
-}
-.htmlarea-context-menu li.hover {
-	background-color:#316ac5;
-}
-.htmlarea-context-menu li.hover .button {
+.htmlarea-context-menu .hover {
+	background-image:url('alt_menu_mainitem_bg.gif');
+	background-repeat: repeat-x;
 	color:#fff;
+	padding-bottom:0;margin-bottom:0;
+	border-color:#A2AAB8;
 }
Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/BlockElements/insertHorizontalRule.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\BlockElements\insertHorizontalRule.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/helpbubble.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\helpbubble.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/rtehtmlarea/htmlarea/skins/default/images/loading.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\rtehtmlarea\htmlarea\skins\default\images\loading.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php
===================================================================
--- typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php	(révision 6908)
+++ typo3/sysext/rtehtmlarea/pi2/class.tx_rtehtmlarea_pi2.php	(copie de travail)
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 2005-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
+*  (c) 2005-2010 Stanislas Rolland <typo3(arobas)sjbr.ca>
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
@@ -225,6 +225,10 @@
 		$pageRenderer->addCssFile($this->hostURL . '/t3lib/js/extjs/ux/resize.css');
 			// Loading JavaScript files and code
 		$pageRenderer->loadExtJs();
+		$pageRenderer->enableExtJSQuickTips();
+		if (!$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts']) {
+			$pageRenderer->enableExtJsDebug();
+		}
 		$pageRenderer->addJsFile($this->hostURL . '/t3lib/js/extjs/ux/ext.resizable.js');
 		if ($this->TCEform->RTEcounter == 1) {
 			$this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
Index: typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt
===================================================================
--- typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt	(révision 6908)
+++ typo3/sysext/rtehtmlarea/res/demo/pageTSConfig.txt	(copie de travail)
@@ -228,7 +228,7 @@
 
 		## Configuration specific to the inserttag button or QuickTag feature (htmlArea RTE only)
 		## Do not allow insertion of the following tags
-	buttons.inserttag.denyTags = font, underline, strike, table
+	buttons.inserttag.denyTags = font, u, strike, table
 
 		## Configuration specific to the bold and italic buttons (htmlArea RTE only)
 		## Add hotkeys associated with bold, italic, strikethrough and underline buttons
Index: typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css
===================================================================
--- typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css	(révision 6908)
+++ typo3/sysext/t3skin/rtehtmlarea/htmlarea-edited-content.css	(copie de travail)
@@ -5,6 +5,7 @@
 	margin:0;
 	padding:3px;
 	background-color:#ffffff;
+	border-width:0;
 }
 
 /* Selectors for the Table Operations plugin */
@@ -16,7 +17,7 @@
 
 /* Make language marks visible */
 body.htmlarea-show-language-marks *[lang] {
-	background: url("images/language-marker.gif") left bottom no-repeat; padding-left: 14px; text-decoration: underline;
+	background: url("images/language-marker.gif") left top no-repeat; padding-left: 14px; text-decoration: underline;
 }
 
 /* Selectors for the Abbreviation plugin */
Index: typo3/sysext/t3skin/rtehtmlarea/htmlarea.css
===================================================================
--- typo3/sysext/t3skin/rtehtmlarea/htmlarea.css	(révision 6908)
+++ typo3/sysext/t3skin/rtehtmlarea/htmlarea.css	(copie de travail)
@@ -1,21 +1,17 @@
-/* CSS Selectors for skin sr_rtehtmlarea_bluelook */
 /* Selectors for the htmlArea RTE editor */
 .htmlarea {
-	background-color:#fff;
- 	margin:0;padding:0;
+	background-color:#EFEFF4;
+ 	margin:0 2px 0 0;padding:0;
 }
-.resizable {
-	background-color:transparent;
-	padding-right:7px;
-	padding-bottom:6px;
-	background-image: url("images/resize.gif");
-	background-position: bottom right;
-	background-repeat: no-repeat;
-}
 .pleasewait {
- 	position:relative;top:0px;text-align:left;
- 	font-size:10px;
+ 	position:relative;
  	margin-top:30px;
+ 	padding: 20px 0 20px 50px;
+ 	font-size: 11px !important;
+ 	text-align:left;
+	background: url('images/loading.gif') no-repeat 10px center;
+	vertical-align: middle;
+	color: #7F8083;
 }
 .editorWrap {
  	margin:0;padding:0;
@@ -28,83 +24,80 @@
 	padding:0px 1px;
 	margin:0;
 }
+.editorWrap .resizable {
+	background-image: url("images/resize.gif");
+	background-position: bottom right;
+	background-repeat: no-repeat;
+}
+.editorWrap div.resizable {
+	padding-right: 7px;
+	padding-bottom: 5px;
+}
 /* Selectors for the editor toolbar */
-.htmlarea div.toolbar {
+.htmlarea .toolbar {
 	background-color:#EFEFF4;cursor:default;
-	width:100%;
 	border:1px solid #EFEFF4;
 	border-bottom:0px;
 	margin:0;
 	padding:2px 0px;
+	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
 }
-.htmlarea .toolbar ul {
-	background-color:transparent;
-	list-style-type:none;
-}
-.htmlarea .toolbar ul.tb-line {
-	clear:both;
-	border-style:none;margin:0;padding:0px 2px;
-}
-.htmlarea .toolbar ul.tb-group {
-	clear:none;float:left;
-	margin:1px 2px 0px 0px;padding:0;
-}
-.htmlarea .toolbar ul li {
+.htmlarea .toolbar .tb-group {
+	clear:none;
 	float:left;
-	background-color:transparent;
-	color: #212424;
-	font-size:10px;
-	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
-	border-style:none;margin:0;padding:0;
+	margin:1px 2px 0px 0px;
+	padding:0;
 }
-.htmlarea .toolbar ul.free-float li, .htmlarea .toolbar ul.tb-group li {
-	height:24px;
+.htmlarea .toolbar .x-form-item {
+	float: left;
+	margin:0;
 }
-.htmlarea .toolbar label {
+.htmlarea .toolbar .x-form-item-label {
 	vertical-align:middle;
 	background-color:transparent;
-	border-style:none;margin:0;padding:3px 3px 0px 3px;
+	border-style:none;
+	margin:0;padding:3px 3px 0px 3px;
 }
-
-.htmlarea .toolbar button {
-	vertical-align:top;
-	background-color:transparent;color:ButtonText;background-position:1px 1px;background-repeat:no-repeat;
+.htmlarea .toolbar .button {
+	background-color:transparent;color:ButtonText;background-position:10px 0px;background-repeat:no-repeat;
 	width:22px;height:22px;
-	border-style:solid;border-color:#EFEFF4;border-width:0px 1px;margin:0;padding:0;
+	border-style:solid;border-color:#EFEFF4;border-width:1px;
+	margin:0 0 1px 0;padding:0;
+	float:left;
 }
-.htmlarea .toolbar button div.buttonImgContainer {
-	position:relative;top:0;left:0;
-	width:18px;height:18px;overflow:hidden;
+.htmlarea .toolbar .x-btn-mc, .htmlarea .toolbar .x-btn-ml, .htmlarea .toolbar .x-btn-mr, .htmlarea .toolbar .x-btn-tc, .htmlarea .toolbar .x-btn-tl, .htmlarea .toolbar .x-btn-tr, .htmlarea .toolbar .x-btn-bl, .htmlarea .toolbar .x-btn-bc, .htmlarea .toolbar .x-btn-br {
+	background-color:transparent;background-image:none;
+	border-style:none;
 	margin:0;padding:0;
 }
-.htmlarea .toolbar .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");}
-.htmlarea .toolbar .Big {background-image:url("images/InlineElements/big.gif");}
-.htmlarea .toolbar .Bold {background-image:url("images/InlineElements/bold.gif");}
-.htmlarea .toolbar .Citation {background-image:url("images/InlineElements/citation.gif");}
-.htmlarea .toolbar .Code {background-image:url("images/InlineElements/code.gif");}
-.htmlarea .toolbar .Definition {background-image:url("images/InlineElements/definition.gif");}
-.htmlarea .toolbar .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");}
-.htmlarea .toolbar .Emphasis {background-image:url("images/InlineElements/emphasis.gif");}
-.htmlarea .toolbar .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");}
-.htmlarea .toolbar .Italic {background-image:url("images/InlineElements/italic.gif");}
-.htmlarea .toolbar .Keyboard {background-image:url("images/InlineElements/keyboard.gif");}
-.htmlarea .toolbar .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");}
-.htmlarea .toolbar .Quotation {background-image:url("images/InlineElements/quotation.gif");}
-.htmlarea .toolbar .Sample {background-image:url("images/InlineElements/sample.gif");}
-.htmlarea .toolbar .Small {background-image:url("images/InlineElements/small.gif");}
-.htmlarea .toolbar .Span {background-image:url("images/InlineElements/span.gif");}
-.htmlarea .toolbar .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");}
-.htmlarea .toolbar .Strong {background-image:url("images/InlineElements/strong.gif");}
-.htmlarea .toolbar .Subscript {background-image:url("images/InlineElements/subscript.gif");}
-.htmlarea .toolbar .Superscript {background-image:url("images/InlineElements/superscript.gif");}
-.htmlarea .toolbar .Underline {background-image:url("images/InlineElements/underline.gif");}
-.htmlarea .toolbar .Variable {background-image:url("images/InlineElements/variable.gif");}
-.htmlarea .toolbar .LeftToRight {background-image:url("images/ed_left_to_right.gif");}
-.htmlarea .toolbar .RightToLeft {background-image:url("images/ed_right_to_left.gif");}
-.htmlarea .toolbar .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");}
-.htmlarea .toolbar .Indent {background-image:url("images/BlockElements/indent.gif");}
-.htmlarea .toolbar .Outdent {background-image:url("images/BlockElements/outdent.gif");}
-.htmlarea .toolbar .Blockquote {background-image:url("images/BlockElements/blockquote.gif");}
+.htmlarea .toolbar .BiDiOverride, .htmlarea-context-menu .BiDiOverride {background-image:url("images/InlineElements/bidioverride.gif");}
+.htmlarea .toolbar .Big, .htmlarea-context-menu .Big {background-image:url("images/InlineElements/big.gif");}
+.htmlarea .toolbar .Bold, .htmlarea-context-menu .Bold {background-image:url("images/InlineElements/bold.gif");}
+.htmlarea .toolbar .Citation, .htmlarea-context-menu .Citation {background-image:url("images/InlineElements/citation.gif");}
+.htmlarea .toolbar .Code, .htmlarea-context-menu .Code {background-image:url("images/InlineElements/code.gif");}
+.htmlarea .toolbar .Definition, .htmlarea-context-menu .Definition {background-image:url("images/InlineElements/definition.gif");}
+.htmlarea .toolbar .DeletedText, .htmlarea-context-menu .DeletedText {background-image:url("images/InlineElements/deletedtext.gif");}
+.htmlarea .toolbar .Emphasis, .htmlarea-context-menu .Emphasis {background-image:url("images/InlineElements/emphasis.gif");}
+.htmlarea .toolbar .InsertedText, .htmlarea-context-menu .InsertedText {background-image:url("images/InlineElements/insertedtext.gif");}
+.htmlarea .toolbar .Italic, .htmlarea-context-menu .Italic {background-image:url("images/InlineElements/italic.gif");}
+.htmlarea .toolbar .Keyboard, .htmlarea-context-menu .Keyboard {background-image:url("images/InlineElements/keyboard.gif");}
+.htmlarea .toolbar .MonoSpaced, .htmlarea-context-menu .MonoSpaced {background-image:url("images/InlineElements/monospaced.gif");}
+.htmlarea .toolbar .Quotation, .htmlarea-context-menu .Quotation {background-image:url("images/InlineElements/quotation.gif");}
+.htmlarea .toolbar .Sample, .htmlarea-context-menu .Sample {background-image:url("images/InlineElements/sample.gif");}
+.htmlarea .toolbar .Small, .htmlarea-context-menu .Small {background-image:url("images/InlineElements/small.gif");}
+.htmlarea .toolbar .Span, .htmlarea-context-menu .Span {background-image:url("images/InlineElements/span.gif");}
+.htmlarea .toolbar .StrikeThrough, .htmlarea-context-menu .StrikeThrough {background-image:url("images/InlineElements/strikethrough.gif");}
+.htmlarea .toolbar .Strong, .htmlarea-context-menu .Strong {background-image:url("images/InlineElements/strong.gif");}
+.htmlarea .toolbar .Subscript, .htmlarea-context-menu .Subscript {background-image:url("images/InlineElements/subscript.gif");}
+.htmlarea .toolbar .Superscript, .htmlarea-context-menu .Superscript {background-image:url("images/InlineElements/superscript.gif");}
+.htmlarea .toolbar .Underline, .htmlarea-context-menu .Underline {background-image:url("images/InlineElements/underline.gif");}
+.htmlarea .toolbar .Variable, .htmlarea-context-menu .Variable {background-image:url("images/InlineElements/variable.gif");}
+.htmlarea .toolbar .LeftToRight, .htmlarea-context-menu .LeftToRight {background-image:url("images/ed_left_to_right.gif");}
+.htmlarea .toolbar .RightToLeft, .htmlarea-context-menu .RightToLeft {background-image:url("images/ed_right_to_left.gif");}
+.htmlarea .toolbar .ShowLanguageMarks, .htmlarea-context-menu .ShowLanguageMarks {background-image:url("images/show-language-marks.gif");}
+.htmlarea .toolbar .Indent, .htmlarea-context-menu .Indent {background-image:url("images/BlockElements/indent.gif");}
+.htmlarea .toolbar .Outdent, .htmlarea-context-menu .Outdent {background-image:url("images/BlockElements/outdent.gif");}
+.htmlarea .toolbar .Blockquote, .htmlarea-context-menu .Blockquote {background-image:url("images/BlockElements/blockquote.gif");}
 .htmlarea .toolbar .InsertParagraphBefore, .htmlarea-context-menu .InsertParagraphBefore {background-image:url("images/BlockElements/insertParagraphBefore.gif");}
 .htmlarea .toolbar .InsertParagraphAfter, .htmlarea-context-menu .InsertParagraphAfter {background-image:url("images/BlockElements/insertParagraphAfter.gif");}
 .htmlarea .toolbar .JustifyLeft, .htmlarea-context-menu .JustifyLeft {background-image:url("images/BlockElements/justifyLeft.gif");}
@@ -113,125 +106,130 @@
 .htmlarea .toolbar .JustifyFull, .htmlarea-context-menu .JustifyFull {background-image:url("images/BlockElements/justifyFull.gif");}
 .htmlarea .toolbar .DefinitionList, .htmlarea-context-menu .DefinitionList {background-image:url("images/definitionList.gif");}
 .htmlarea .toolbar .DefinitionItem, .htmlarea-context-menu .DefinitionItem {background-image:url("images/definitionItem.gif");}
-.htmlarea .toolbar .InsertOrderedList {background-image:url("images/ed_list_num.gif");}
-.htmlarea .toolbar .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");}
-.htmlarea .toolbar .ForeColor {background-image:url("images/ed_color_fg.gif");}
-.htmlarea .toolbar .HiliteColor {background-image:url("images/ed_color_bg.gif");}
-.htmlarea .toolbar .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");}
-.htmlarea .toolbar .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");}
-.htmlarea .toolbar .InsertHorizontalRule {background-image:url("images/ed_hr.gif");}
-.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink {background-image:url("images/ed_link.gif");}
+.htmlarea .toolbar .InsertOrderedList, .htmlarea-context-menu .InsertOrderedList {background-image:url("images/ed_list_num.gif");}
+.htmlarea .toolbar .InsertUnorderedList, .htmlarea-context-menu .InsertUnorderedList {background-image:url("images/ed_list_bullet.gif");}
+.htmlarea .toolbar .InsertHorizontalRule, .htmlarea-context-menu .InsertHorizontalRule {background-image:url("images/BlockElements/insertHorizontalRule.gif");}
+.htmlarea .toolbar .ForeColor, .htmlarea-context-menu .ForeColor, .htmlarea-window .ForeColor {background-image:url("images/ed_color_fg.gif");}
+.htmlarea .toolbar .HiliteColor, .htmlarea-context-menu .HiliteColor, .htmlarea-window .HiliteColor {background-image:url("images/ed_color_bg.gif");}
+.htmlarea .toolbar .InsertSmiley, .htmlarea-context-menu .InsertSmiley, .htmlarea-window .InsertSmiley {background-image:url("images/InsertSmiley/ed_smiley.gif");}
+.htmlarea .toolbar .InsertCharacter, .htmlarea-context-menu .InsertCharacter, .htmlarea-window .InsertCharacter {background-image:url("images/CharacterMap/ed_charmap.gif");}
+.htmlarea .toolbar .CreateLink, .htmlarea-context-menu .CreateLink, .htmlarea-window .CreateLink {background-image:url("images/ed_link.gif");}
 .htmlarea .toolbar .UnLink, .htmlarea-context-menu .UnLink {background-image:url("images/ed_unlink.gif");}
-.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage {background-image:url("images/ed_image.gif");}
-.htmlarea .toolbar .InsertTable {background-image:url("images/insert_table.gif");}
-.htmlarea .toolbar .UserElements {background-image:url("images/UserElements/ed_user.gif");}
-.htmlarea .toolbar .FindReplace {background-image:url("images/FindReplace/ed_find.gif");}
-.htmlarea .toolbar .SpellCheck {background-image:url("images/SpellChecker/spell-check.gif"); }
-.htmlarea .toolbar .InsertTag {background-image:url("images/QuickTag/ed_quicktag.gif"); }
-.htmlarea .toolbar .Acronym {background-image:url("images/Acronym/ed_acronym.gif"); }
-.htmlarea .toolbar .RemoveFormat {background-image:url("images/RemoveFormat/ed_clean.gif"); }
+.htmlarea .toolbar .InsertImage, .htmlarea-context-menu .InsertImage, .htmlarea-window .InsertImage {background-image:url("images/ed_image.gif");}
+.htmlarea .toolbar .InsertTable, .htmlarea-context-menu .InsertTable, .htmlarea-window .InsertTable {background-image:url("images/insert_table.gif");}
+.htmlarea .toolbar .UserElements, .htmlarea-context-menu .UserElements, .htmlarea-window .UserElements {background-image:url("images/UserElements/ed_user.gif");}
+.htmlarea .toolbar .FindReplace, .htmlarea-context-menu .FindReplace, .htmlarea-window .FindReplace {background-image:url("images/FindReplace/ed_find.gif");}
+.htmlarea .toolbar .SpellCheck, .htmlarea-context-menu .SpellCheck, .htmlarea-window .SpellCheck {background-image:url("images/SpellChecker/spell-check.gif"); }
+.htmlarea .toolbar .InsertTag, .htmlarea-context-menu .InsertTag, .htmlarea-window .InsertTag {background-image:url("images/QuickTag/ed_quicktag.gif"); }
+.htmlarea .toolbar .Acronym, .htmlarea-context-menu .Acronym, .htmlarea-window .Acronym {background-image:url("images/Acronym/ed_acronym.gif"); }
+.htmlarea .toolbar .RemoveFormat, .htmlarea-context-menu .RemoveFormat, .htmlarea-window .RemoveFormat {background-image:url("images/RemoveFormat/ed_clean.gif"); }
 .htmlarea .toolbar .SplitBlock {background-image:url("images/ed_splitblock.gif"); }
-.htmlarea .toolbar .TextMode {background-image:url("images/ed_html.gif"); }
-.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy  {background-image:url("images/ed_copy.gif");}
+.htmlarea .toolbar .TextMode, .htmlarea-context-menu .TextMode {background-image:url("images/ed_html.gif"); }
+.htmlarea .toolbar .Copy, .htmlarea-context-menu .Copy {background-image:url("images/ed_copy.gif");}
 .htmlarea .toolbar .Cut, .htmlarea-context-menu .Cut  {background-image:url("images/ed_cut.gif");}
 .htmlarea .toolbar .Paste, .htmlarea-context-menu .Paste {background-image:url("images/ed_paste.gif");}
-.htmlarea .toolbar .Undo {background-image:url("images/ed_undo.gif");}
-.htmlarea .toolbar .Redo {background-image:url("images/ed_redo.gif");}
-.htmlarea .toolbar .About {background-image:url("images/ed_about.gif");}
+.htmlarea-context-menu .DeleteTarget {background-image:url("images/ed_delete.gif");}
+.htmlarea .toolbar .Undo, .htmlarea-context-menu .Undo {background-image:url("images/ed_undo.gif");}
+.htmlarea .toolbar .Redo, .htmlarea-context-menu .Redo {background-image:url("images/ed_redo.gif");}
+.htmlarea .toolbar .About, .htmlarea-context-menu .About, .htmlarea-window .About {background-image:url("images/ed_about.gif");}
 .htmlarea .toolbar .ShowHelp { background-image:url("images/TYPO3ViewHelp/module_help.gif");}
 .htmlarea .toolbar .TO-toggle-borders, .htmlarea-context-menu .TO-toggle-borders {background-image:url("images/TableOperations/toggle-borders.gif");}
-.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop  {background-image:url("images/TableOperations/table-prop.gif");}
+.htmlarea .toolbar .TO-table-prop, .htmlarea-context-menu .TO-table-prop, .htmlarea-window .TO-table-prop {background-image:url("images/TableOperations/table-prop.gif");}
 .htmlarea .toolbar .TO-table-restyle, .htmlarea-context-menu .TO-table-restyle {background-image:url("images/TableOperations/table-restyle.gif");}
-.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");}
+.htmlarea .toolbar .TO-row-prop, .htmlarea-context-menu .TO-row-prop, .htmlarea-window .TO-row-prop {background-image:url("images/TableOperations/row-prop.gif");}
 .htmlarea .toolbar .TO-row-insert-above, .htmlarea-context-menu .TO-row-insert-above {background-image:url("images/TableOperations/row-insert-above.gif");}
 .htmlarea .toolbar .TO-row-insert-under, .htmlarea-context-menu .TO-row-insert-under {background-image:url("images/TableOperations/row-insert-under.gif");}
 .htmlarea .toolbar .TO-row-delete, .htmlarea-context-menu .TO-row-delete {background-image:url("images/TableOperations/row-delete.gif");}
 .htmlarea .toolbar .TO-row-split, .htmlarea-context-menu .TO-row-split {background-image:url("images/TableOperations/row-split.gif");}
-.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");}
+.htmlarea .toolbar .TO-col-prop, .htmlarea-context-menu .TO-col-prop, .htmlarea-window .TO-col-prop {background-image:url("images/TableOperations/col-prop.gif");}
 .htmlarea .toolbar .TO-col-insert-before, .htmlarea-context-menu .TO-col-insert-before {background-image:url("images/TableOperations/col-insert-before.gif");}
 .htmlarea .toolbar .TO-col-insert-after, .htmlarea-context-menu .TO-col-insert-after {background-image:url("images/TableOperations/col-insert-after.gif");}
 .htmlarea .toolbar .TO-col-delete, .htmlarea-context-menu .TO-col-delete {background-image:url("images/TableOperations/col-delete.gif");}
 .htmlarea .toolbar .TO-col-split, .htmlarea-context-menu .TO-col-split {background-image:url("images/TableOperations/col-split.gif");}
-.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");}
+.htmlarea .toolbar .TO-cell-prop, .htmlarea-context-menu .TO-cell-prop, .htmlarea-window .TO-cell-prop {background-image:url("images/TableOperations/cell-prop.gif");}
 .htmlarea .toolbar .TO-cell-insert-before, .htmlarea-context-menu .TO-cell-insert-before {background-image:url("images/TableOperations/cell-insert-before.gif");}
 .htmlarea .toolbar .TO-cell-insert-after, .htmlarea-context-menu .TO-cell-insert-after {background-image:url("images/TableOperations/cell-insert-after.gif");}
 .htmlarea .toolbar .TO-cell-delete, .htmlarea-context-menu .TO-cell-delete {background-image:url("images/TableOperations/cell-delete.gif");}
 .htmlarea .toolbar .TO-cell-split, .htmlarea-context-menu .TO-cell-split {background-image:url("images/TableOperations/cell-split.gif");}
 .htmlarea .toolbar .TO-cell-merge, .htmlarea-context-menu .TO-cell-merge {background-image:url("images/TableOperations/cell-merge.gif");}
-.htmlarea .toolbar button.buttonHover {
+.htmlarea .toolbar .buttonHover {
 	border:1px solid;border-color:white #C5C5D5 #C5C5D5 white;
 	background-color: #E0E0E9;
 }
-.htmlarea .toolbar button.buttonActive, .htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive {
+.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive {
 	border:1px solid;border-color:#C5C5D5 white white #C5C5D5;
+	background-color:ButtonHighlight;
 }
-.htmlarea .toolbar button.buttonPressed, .htmlarea-context-menu button.buttonActive {
+.htmlarea .toolbar .buttonPressed, .htmlarea-context-menu .buttonActive {
 	background-color:ButtonHighlight;
 	text-decoration:none;
 }
-.htmlarea .toolbar div.indicator {
+.htmlarea .toolbar .indicator {
 	background-color:white;cursor:default;
 	width:20px;overflow:hidden;
+	height:16px;
 	text-align:center;
-	border:1px solid ButtonShadow;margin:4px 1px 0px 1px;padding:0px 3px;
+	border:1px solid ButtonShadow;
+	margin:3px 1px 4px 1px;padding:0 3px;
+	float:left;
 }
-.htmlarea .toolbar button.buttonDisabled {
+.htmlarea .toolbar .buttonDisabled {
 	filter: gray() alpha(opacity=25);
 	-moz-opacity:0.25;
 	opacity:0.25;
 }
-.htmlarea .toolbar div.separator {
-	background-color:transparent;background-image:url(separator.gif);background-repeat:no-repeat;
-	width:7px;height:22px;
-	border:1px solid #EFEFF4;margin:0;padding:0;
-}
-.htmlarea .toolbar div.space {
+.htmlarea .toolbar .separator {
+	background-color:transparent;background-image:url(separator.gif);background-repeat:no-repeat;background-position:0;
+	width:7px;height:23px;
+	border:1px solid #EFEFF4;
 	float:left;
+}
+.htmlarea .toolbar .space {
 	background-color:transparent;
 	height:22px;
-	border-style:none;margin:0;padding:0 1px;
+	border-style:none;
+	margin:0;padding:0 1px;
+	float:left;
 }
-.htmlarea .toolbar select {
+.htmlarea .toolbar .select {
 	color:WindowText;
 	font-size:10px;
 	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
 	height:18px;
 	border:1px solid #A2AAB8;
-	margin:0;padding:1px;
+	margin:0 0 3px 0;padding:1px;
 }
-.htmlarea .toolbar select, .htmlarea .toolbar select:hover, .htmlarea .toolbar select:active {
+.htmlarea .toolbar .select, .htmlarea .toolbar .select:hover, .htmlarea .toolbar .select:active {
 	background-color:Window;
 }
-.htmlarea .toolbar select.buttonDisabled {
+.htmlarea .toolbar .select .buttonDisabled {
 	color:GrayText;
 	background-color:#EFEFF4;
 }
 .htmlarea .editorIframe {
 	clear:both;
 	width:100%;
-	border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db;margin:0;padding:0;
+	border:1px solid #A2AAB8;border-bottom:1px solid #e4e0db;
+	margin:0;padding:0;
 }
 .htmlarea .noStatusBar {
 	border-bottom:1px solid #A2AAB8;
 }
 .htmlarea .statusBar {
-	clear:both;
-	background-color:#EFEFF4;background-image:url('alt_menu_mainitem_bg.gif');background-repeat:repeat-x;color:ButtonText;
+	color:#FFFFFF;
+	background-color:#EFEFF4;background-image:url('alt_menu_mainitem_bg.gif');background-repeat:repeat;
 	font-size:10px;
 	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
-	width:100%;height:20px;
-	border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8;margin:0;padding:0;
+	border:1px solid;border-color:#C5C5D5 #A2AAB8 #A2AAB8 #A2AAB8;
+	margin: 0;
+	padding: 0 3px;
+	line-height: 20px;
 }
-.htmlarea .statusBarTree {
-	color:#FFFFFF;
-	display:block;
-	margin:3px 3px;
-}
 .htmlarea .statusBar .statusBarTree a {
 	color:#FFFFFF;
 	text-decoration:none;
 	font-weight:bold;
- 	padding:2px 5px;
+ 	padding:0px 5px;
 }
 .htmlarea .statusBar .statusBarTree a:visited {
  	color:#FFFFFF;
@@ -239,11 +237,47 @@
 .htmlarea .statusBar .statusBarTree a:hover {
 	text-decoration: underline;
 }
-.htmlarea .statusBarTextMode {
-	margin-top:2px;
-	padding:2px 5px;
-}
 /* Selectors for dialogue windows */
+.htmlarea-window .x-tab-panel-body {
+	background-color: #EFEFF4;
+}
+.htmlarea-window .x-fieldset {
+	margin: 3px;
+}
+.htmlarea-window .x-form-item-label {
+	text-align: right;
+	vertical-align: middle;
+	padding: 4px 5px 0 5px;
+}
+.htmlarea-window .x-btn-text {
+	font-weight: normal;
+	color: #000000;
+}
+.htmlarea-window .x-form-check-wrap input {
+	vertical-align: middle;
+}
+.htmlarea-window .show-color {
+	margin-top: 10px;
+	margin-left: 5px;
+	border-style: solid;
+	border-width: 1px;
+	border-color: white;
+}
+.htmlarea-custom-colors a {
+	border-style: none;
+	float: none;
+	display: block;
+	width: 100%;
+}
+.htmlarea-custom-colors em {
+	display: block;
+	border: 1px solid;
+	border-color: #C5C5D5;
+	width: 100%;
+}
+.htmlarea-custom-colors em span {
+	width: 100%;
+}
 .popupwin {
 	color: #212424;background-color:#EFEFF4;
 	font-size:11px;font-family:Verdana, Helvetica, Geneva, Arial, sans-serif;
@@ -295,6 +329,7 @@
 }
 .popupwin select {
 	display:inline;
+	font-size:11px;font-family:Verdana, Helvetica, Geneva, Arial, sans-serif;
 }
 .popupwin table {
 	border-collapse:collapse;border-style:none;margin:0;padding:0;
@@ -348,6 +383,8 @@
 }
 .popupwin select, .popupwin input, .popupwin button, .popupwin textarea, .popupwin table, .popupwin label {
 	font-size:1.0em;
+	padding: 3px 1px 1px 1px;
+	font-family:Verdana, Helvetica, Geneva, Arial, sans-serif;
 }
 .popupwin button {
 	width:8em;
@@ -402,53 +439,6 @@
 .popupwin input.shorter-value {
 	width:17em;
 }
-/* Selectors for TYPO3 Color dialogue */
-.popupwin .buttonColor {
-	cursor:default;
-	border-style:solid;border-width:1px;border-color:ButtonHighlight ButtonShadow ButtonHighlight ButtonHighlight;
-	padding:1px;margin:2px 10px 0 0;
-	height:1em;
-	white-space:nowrap;
-}
-.popupwin div.buttonColor {
-	float:left;
-	vertical-align:middle;
-}
-.popupwin .buttonColor-hilite {
-	border-color:black black black black;
-}
-.popupwin .buttonColor .chooser, .popupwin .buttonColor .nocolor {
-	height:0.6em;
-	border-width:1px;border-style:solid;border-width:1px;border-color:ButtonShadow ButtonHighlight ButtonShadow ButtonShadow;
-	padding:0 1em;
-}
-.popupwin .buttonColor .nocolor {
-	padding:0;
-}
-.popupwin .buttonColor .nocolor-hilite {
-	background-color:#fff;color:#f00;cursor:pointer;
-}
-.popupwin .colorTableWrapper {
-}
-.popupwin .colorTable {
-	width:350px;
-}
-.popupwin .currentColor {
-	width:20px;height:20px;
-	border:black 1px solid;
-	margin:0pt 15pt;
-}
-.popupwin .colorTable tr {
-	height:6px;
-}
-.popupwin .colorTable td {
-	width:6px;
-	cursor:pointer;
-}
-.popupwin .colorTable td.colorTitle {
-	width:auto;
-	padding-left:10px;
-}
 /* Selectors for the Default Image dialogue */
 .htmlarea-default-image #image, .htmlarea-default-image #alt {
 	white-space:nowrap;
@@ -469,22 +459,18 @@
 	white-space:nowrap;
 }
 /* Selectors for the InsertSmiley plugin */
-.htmlarea-insert-smiley div.smileytable {
-	text-align:center;
-	height:130px;margin-bottom:10px;
+.htmlarea-window .emoticon-array {
+	padding: 10px;
+	width: 150px;
 }
-.htmlarea-insert-smiley #smileytable {
-	height:130px;
+.htmlarea-window .emoticon {
+    display: block;
+    float: left;
+    padding: 5px;
+    width: 20px;
+    height: 20px;
+    vertical-align: middle;
 }
-.htmlarea-insert-smiley #smileytable tr {
-	height:25px;
-}
-.htmlarea-insert-smiley #smileytable td {
-	width:35px;height:25px;
-}
-.htmlarea-insert-smiley #smileytable td img {
-	border-style:none;
-}
 /* Selectors for the FindReplace dialogue */
 .htmlarea-find-replace .long-label {
 	text-align:left;
@@ -514,47 +500,6 @@
 .htmlarea-character-map td.character-hilite {
 	background-color:Highlight;color:HighlightText;
 }
-/* Selectors for the DefaultColor dialogue */
-.htmlarea-default-color #selectedColor div {
-	white-space:nowrap;
-}
-.htmlarea-default-color #ColorPreview {
-	height:21px;width:50px;
-	float:left;
-	background-color:#000;
-}
-.htmlarea-default-color #ColorHex {
-	font-size:12px;
-	display:inline;
-	vertical-align:top;
-	margin-left:5px;
-}
-.htmlarea-default-color table {
-	margin:5px 0;
-}
-.htmlarea-default-color .color {
-	width:10px;height:10px;
-	cursor:pointer;
-}
-/* Selectors for the QuickTag dialogue */
-.htmlarea-quick-tag #tag {
-	text-align:center;
-	padding:3px;
-	background-color:#E9E9E9;
-}
-.htmlarea-quick-tag #tagopen {
-	background-color: #E9E9E9;
-	width:370px;
-	border-style:none;
-}
-.htmlarea-quick-tag strong {
-	font-size:14px;
-}
-.htmlarea-quick-tag #showselect {
-	position:absolute;left:7px;top:81px;
-	width:150px;height:13px;
-	z-index:100;visibility:visible;
-}
 /* Selectors for the SpellChecker dialogue */
 .htmlarea-spell-check .dictionaries {
 	float:right;
@@ -608,32 +553,23 @@
 }
 /* Selectors for the ContextMenu plugin */
 .htmlarea-context-menu {
-	position:absolute;top:-1000px;left:-1000px;z-index:1000;
-	background-color:#EFEFF4;cursor:default;
+	background-color:#EFEFF4;
 	color:#212424;
 	font-family: Verdana, Helvetica, Geneva, Arial, sans-serif;
 	font-size:10px;
-	list-style:none;
-	border:1px solid #A2AAB8;margin:0;padding:2px;
 }
-.htmlarea-context-menu li {
-	background-color:#EFEFF4;
-	border:1px solid #EFEFF4;margin:0;padding:0;
-	font-size:10px;
+.htmlarea-context-menu .button {
+	background-color:transparent;
+	background-repeat:no-repeat;
+	background-position:0px 0px;
 }
-.htmlarea-context-menu li button {
-	text-align:left;vertical-align:middle;
-	background-color:transparent;background-repeat:no-repeat;background-position:0px 0px;
-	height:20px;width:21px;
-	border-style:none;margin:0 3px 0 0;padding:0;
-}
-.htmlarea-context-menu li .button img {
-	width:18px;height:18px;
-}
-.htmlarea-context-menu li.separator {
+.htmlarea-context-menu .separator {
 	border-top:1px solid #A2AAB8;
 }
-.htmlarea-context-menu li.hover {
+.htmlarea-context-menu .hover {
 	background-image:url('alt_menu_mainitem_bg.gif');
-	color:#fff;border-color:#A2AAB8;
+	background-repeat: repeat-x;
+	color:#fff;
+	padding-bottom:0;margin-bottom:0;
+	border-color:#A2AAB8;
 }
Index: typo3/sysext/t3skin/rtehtmlarea/images/BlockElements/insertHorizontalRule.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\BlockElements\insertHorizontalRule.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/t3skin/rtehtmlarea/images/helpbubble.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\helpbubble.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

Index: typo3/sysext/t3skin/rtehtmlarea/images/loading.gif
===================================================================
Impossible d'afficher : fichier considéré comme binaire.
svn:mime-type = application/octet-stream

Modification de propriétés sur typo3\sysext\t3skin\rtehtmlarea\images\loading.gif
___________________________________________________________________
Ajouté : svn:mime-type
   + application/octet-stream

