Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea-gecko.js	(copie de travail)
@@ -481,13 +481,13 @@
 		} else {
 			var spans = node.getElementsByTagName("span");
 			for (var i = spans.length; --i >= 0;) {
-				if (HTMLArea._hasClass(spans[i], "Apple-style-span")) {
+				if (HTMLArea.DOM.hasClass(spans[i], "Apple-style-span")) {
 					this.removeMarkup(spans[i]);
 				}
 			}
 			var fonts = node.getElementsByTagName("font");
 			for (i = fonts.length; --i >= 0;) {
-				if (HTMLArea._hasClass(fonts[i], "Apple-style-span")) {
+				if (HTMLArea.DOM.hasClass(fonts[i], "Apple-style-span")) {
 					this.removeMarkup(fonts[i]);
 				}
 			}
Index: typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/htmlarea.js	(copie de travail)
@@ -36,10 +36,7 @@
 	// Avoid re-initialization on AJax call when HTMLArea object was already initialized
 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');
-/***************************************************
- *  CONSTANTS
- ***************************************************/
+Ext.namespace('HTMLArea.CSS', 'HTMLArea.util.TYPO3', 'HTMLArea.util.Tips', 'HTMLArea.util.Color', 'Ext.ux.form', 'Ext.ux.menu', 'Ext.ux.Toolbar');
 Ext.apply(HTMLArea, {
 	/*************************************************************************
 	 * THESE BROWSER IDENTIFICATION CONSTANTS ARE DEPRECATED AS OF TYPO3 4.4 *
@@ -51,7 +48,9 @@
 	is_safari	: Ext.isWebKit,
 	is_chrome	: Ext.isChrome,
 	is_opera	: Ext.isOpera,
-		// Compile some regular expressions
+	/***************************************************
+	 * COMPILED REGULAR EXPRESSIONS                    *
+	 ***************************************************/
 	RE_htmlTag		: /<.[^<>]*?>/g,
 	RE_tagName		: /(<\/|<)\s*([^ \t\n>]+)/ig,
 	RE_head			: /<head>((.|\n)*?)<\/head>/i,
@@ -63,39 +62,48 @@
 	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)$/i,
 	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)$/i,
 	RE_noClosingTag		: /^(img|br|hr|col|input|area|base|link|meta|param)$/i,
-	RE_numberOrPunctuation	: /[0-9.(),;:!¡?¿%#$'"_+=\\\/-]*/g
-});
-/***************************************************
- *  TROUBLESHOOTING
- ***************************************************/
-HTMLArea._appendToLog = function(str){
-	if (HTMLArea.enableDebugMode) {
-		var log = document.getElementById('HTMLAreaLog');
-		if(log) {
-			log.appendChild(document.createTextNode(str));
-			log.appendChild(document.createElement('br'));
+	RE_numberOrPunctuation	: /[0-9.(),;:!¡?¿%#$'"_+=\\\/-]*/g,
+	/***************************************************
+	 * TROUBLESHOOTING                                 *
+	 ***************************************************/
+	_appendToLog: function(str){
+		if (HTMLArea.enableDebugMode) {
+			var log = document.getElementById('HTMLAreaLog');
+			if(log) {
+				log.appendChild(document.createTextNode(str));
+				log.appendChild(document.createElement('br'));
+			}
 		}
+	},
+	appendToLog: function (editorId, objectName, functionName, text) {
+		HTMLArea._appendToLog(editorId + '[' + objectName + '::' + functionName + ']: ' + text);
+	},
+	/***************************************************
+	 * LOCALIZATION                                    *
+	 ***************************************************/
+	localize: function (label) {
+		return HTMLArea.I18N.dialogs[label] || HTMLArea.I18N.tooltips[label] || HTMLArea.I18N.msg[label] || label;
+	},
+	/***************************************************
+	 * INITIALIZATION                                  *
+	 ***************************************************/
+	init: function () {
+			// Apply global configuration settings
+		Ext.apply(HTMLArea, RTEarea[0]);
+		Ext.applyIf(HTMLArea, {
+			editorSkin	: HTMLArea.editorUrl + 'skins/default/',
+			editorCSS	: HTMLArea.editorUrl + 'skins/default/htmlarea.css'
+		});
+		if (!Ext.isString(HTMLArea.editedContentCSS)) {
+			HTMLArea.editedContentCSS = HTMLArea.editorSkin + 'htmlarea-edited-content.css';
+		}
+		HTMLArea.isReady = true;
+		HTMLArea._appendToLog("[HTMLArea::init]: Editor url set to: " + HTMLArea.editorUrl);
+		HTMLArea._appendToLog("[HTMLArea::init]: Editor skin CSS set to: " + HTMLArea.editorCSS);
+		HTMLArea._appendToLog("[HTMLArea::init]: Editor content skin CSS set to: " + HTMLArea.editedContentCSS);
 	}
-};
+});
 /***************************************************
- *  HTMLArea INITIALIZATION
- ***************************************************/
-HTMLArea.init = function() {
-		// Apply global configuration settings
-	Ext.apply(HTMLArea, RTEarea[0]);
-	Ext.applyIf(HTMLArea, {
-		editorSkin	: HTMLArea.editorUrl + 'skins/default/',
-		editorCSS	: HTMLArea.editorUrl + 'skins/default/htmlarea.css'
-	});
-	if (!Ext.isString(HTMLArea.editedContentCSS)) {
-		HTMLArea.editedContentCSS = HTMLArea.editorSkin + 'htmlarea-edited-content.css';
-	}
-	HTMLArea.isReady = true;
-	HTMLArea._appendToLog("[HTMLArea::init]: Editor url set to: " + HTMLArea.editorUrl);
-	HTMLArea._appendToLog("[HTMLArea::init]: Editor skin CSS set to: " + HTMLArea.editorCSS);
-	HTMLArea._appendToLog("[HTMLArea::init]: Editor content skin CSS set to: " + HTMLArea.editedContentCSS);
-};
-/***************************************************
  *  EDITOR CONFIGURATION
  ***************************************************/
 HTMLArea.Config = function (editorId) {
@@ -2085,6 +2093,10 @@
 				this.registerPlugin(plugin);
 			}
 		}, this);
+			// Create Ajax object
+		this.ajax = new HTMLArea.Ajax({
+			editor: this
+		});
 			// Initialize keyboard input inhibit flag
 		this.inhibitKeyboardInput = false;
 		this.addEvents(
@@ -2423,6 +2435,17 @@
 		document.getElementById('editorWrap' + this.editorId).style.visibility = 'visible';
 	},
 	/*
+	 * Append an entry at the end of the troubleshooting log
+	 *
+	 * @param	string		functionName: the name of the editor function writing to the log
+	 * @param	string		text: the text of the message
+	 *
+	 * @return	void
+	 */
+	appendToLog: function (objectName, functionName, text) {
+		HTMLArea.appendToLog(this.editorId, objectName, functionName, text);
+	},
+	/*
 	 * Iframe unload handler: Update the textarea for submission and cleanup
 	 */
 	onUnload: function (event) {
@@ -2450,6 +2473,83 @@
 		RTEarea[this.editorId].editor = null;
 	}
 });
+HTMLArea.Ajax = function (config) {
+	Ext.apply(this, config);
+};
+HTMLArea.Ajax = Ext.extend(HTMLArea.Ajax, {
+	/*
+	 * Load a Javascript file asynchronously
+	 *
+	 * @param	string		url: url of the file to load
+	 * @param	function	callBack: the callBack function
+	 * @param	object		scope: scope of the callbacks
+	 *
+	 * @return	boolean		true on success of the request submission
+	 */
+	getJavascriptFile: function (url, callback, scope) {
+		var success = false;
+		var self = this;
+		this.editor.appendToLog('HTMLArea.Ajax', 'getJavascriptFile', 'Requesting script ' + url);
+		Ext.Ajax.request({
+			method: 'GET',
+			url: url,
+			callback: callback,
+			success: function (response) {
+				success = true;
+			},
+			failure: function (response) {
+				self.editor.inhibitKeyboardInput = false;
+				self.editor.appendToLog('HTMLArea.Ajax', 'getJavascriptFile', 'Unable to get ' + url + ' . Server reported ' + response.status);
+			},
+			scope: scope
+		});
+		return success;
+	},
+	/*
+	 * Post data to the server
+	 *
+	 * @param	string		url: url to post data to
+	 * @param	object		data: data to be posted
+	 * @param	function	callback: function that will handle the response returned by the server
+	 * @param	object		scope: scope of the callbacks
+	 *
+	 * @return	boolean		true on success
+	 */
+	postData: function (url, data, callback, scope) {
+		var success = false;
+		var self = this;
+		data.charset = this.editor.config.typo3ContentCharset ? this.editor.config.typo3ContentCharset : 'utf-8';
+		var params = '';
+		Ext.iterate(data, function (parameter, value) {
+			params += (params.length ? '&' : '') + parameter + '=' + encodeURIComponent(value);
+		});
+		params += this.editor.config.RTEtsConfigParams;
+		this.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Posting to ' + url + '. Data: ' + params);
+		Ext.Ajax.request({
+			method: 'POST',
+			headers: {
+				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
+			},
+			url: url,
+			params: params,
+			callback: Ext.isFunction(callback) ? callback: function (options, success, response) {
+				if (success) {
+					self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Post request to ' + url + ' successful. Server response: ' + response.responseText);
+				} else {
+					self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Post request to ' + url + ' failed. Server reported ' + response.status);
+				}
+			},
+			success: function (response) {
+				success = true;
+			},
+			failure: function (response) {
+				self.editor.appendToLog('HTMLArea.Ajax', 'postData', 'Unable to post ' + url + ' . Server reported ' + response.status);
+			},
+			scope: scope
+		});
+		return success;
+	}
+});
 /***************************************************
  * HTMLArea.util.TYPO3: Utility functions for dealing with tabs and inline elements in TYPO3 forms
  ***************************************************/
@@ -2929,7 +3029,6 @@
 HTMLArea.checkSupportedBrowser = function() {
 	return Ext.isGecko || Ext.isWebKit || Ext.isOpera || Ext.isIE;
 };
-
 /*
  * Remove a class name from the class attribute of an element
  *
@@ -2937,51 +3036,22 @@
  * @param	string		className: the class name to remove
  * @param	boolean		substring: if true, remove the first class name starting with the given string
  * @return	void
+ ***********************************************
+ * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
+ ***********************************************
  */
 HTMLArea._removeClass = function(el, className, substring) {
-	if (!el || !el.className) return;
-	var classes = el.className.trim().split(" ");
-	var newClasses = new Array();
-	for (var i = classes.length; --i >= 0;) {
-		if (!substring) {
-			if (classes[i] != className) {
-				newClasses[newClasses.length] = classes[i];
-			}
-		} else if (classes[i].indexOf(className) != 0) {
-			newClasses[newClasses.length] = classes[i];
-		}
-	}
-	if (newClasses.length == 0) {
-		if (!Ext.isOpera) {
-			el.removeAttribute("class");
-			if (Ext.isIE) {
-				el.removeAttribute("className");
-			}
-		} else {
-			el.className = '';
-		}
-	} else {
-		el.className = newClasses.join(" ");
-	}
+	HTMLArea.DOM.removeClass(el, className, substring);
 };
-
 /*
  * Add a class name to the class attribute
+ ***********************************************
+ * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
+ ***********************************************
  */
-HTMLArea._addClass = function(el, addClassName) {
-	HTMLArea._removeClass(el, addClassName);
-	if (el.className && HTMLArea.classesXOR && HTMLArea.classesXOR.hasOwnProperty(addClassName) && typeof(HTMLArea.classesXOR[addClassName].test) == "function") {
-		var classNames = el.className.trim().split(" ");
-		for (var i = classNames.length; --i >= 0;) {
-			if (HTMLArea.classesXOR[addClassName].test(classNames[i])) {
-				HTMLArea._removeClass(el, classNames[i]);
-			}
-		}
-	}
-	if (el.className) el.className += " " + addClassName;
-		else el.className = addClassName;
+HTMLArea._addClass = function(el, className) {
+	HTMLArea.DOM.addClass(el, className);
 };
-
 /*
  * Check if a class name is in the class attribute of an element
  *
@@ -2989,14 +3059,12 @@
  * @param	string		className: the class name to look for
  * @param	boolean		substring: if true, look for a class name starting with the given string
  * @return	boolean		true if the class name was found
+ ***********************************************
+ * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.5 *
+ ***********************************************
  */
 HTMLArea._hasClass = function(el, className, substring) {
-	if (!el || !el.className) return false;
-	var classes = el.className.trim().split(" ");
-	for (var i = classes.length; --i >= 0;) {
-		if (classes[i] == className || (substring && classes[i].indexOf(className) == 0)) return true;
-	}
-	return false;
+	return HTMLArea.DOM.hasClass(el, className, substring);
 };
 
 HTMLArea.isBlockElement = function(el) { return el && el.nodeType == 1 && HTMLArea.RE_blockTags.test(el.nodeName.toLowerCase()); };
@@ -3069,11 +3137,11 @@
 /*****************************************************************
  * HTMLArea.DOM: Utility functions for dealing with the DOM tree *
  *****************************************************************/
-/***************************************************
- *  DOM-RELATED CONSTANTS
- ***************************************************/
 HTMLArea.DOM = function () {
 	return {
+		/***************************************************
+		*  DOM-RELATED CONSTANTS
+		***************************************************/
 			// DOM node types
 		ELEMENT_NODE: 1,
 		ATTRIBUTE_NODE: 2,
@@ -3086,7 +3154,110 @@
 		DOCUMENT_NODE: 9,
 		DOCUMENT_TYPE_NODE: 10,
 		DOCUMENT_FRAGMENT_NODE: 11,
-		NOTATION_NODE: 12
+		NOTATION_NODE: 12,
+		/*
+		 * Gets the class names assigned to a node, reserved classes removed
+		 *
+		 * @param	object		node: the node
+		 * @return	array		array of class names on the node, reserved classes removed
+		 */
+		getClassNames: function (node) {
+			var classNames = [];
+			if (node) {
+				if (node.className && /\S/.test(node.className)) {
+					classNames = node.className.trim().split(' ');
+				}
+				if (HTMLArea.reservedClassNames.test(node.className)) {
+					var cleanClassNames = [];
+					var j = -1;
+					for (var i = 0; i < classNames.length; ++i) {
+						if (!HTMLArea.reservedClassNames.test(classNames[i])) {
+							cleanClassNames[++j] = classNames[i];
+						}
+					}
+					classNames = cleanClassNames;
+				}
+			}
+			return classNames;
+		},
+		/*
+		 * Check if a class name is in the class attribute of a node
+		 *
+		 * @param	object		node: the node
+		 * @param	string		className: the class name to look for
+		 * @param	boolean		substring: if true, look for a class name starting with the given string
+		 * @return	boolean		true if the class name was found, false otherwise
+		 */
+		hasClass: function (node, className, substring) {
+			var found = false;
+			if (node && node.className) {
+				var classes = node.className.trim().split(' ');
+				for (var i = classes.length; --i >= 0;) {
+					found = ((classes[i] == className) || (substring && classes[i].indexOf(className) == 0));
+					if (found) {
+						break;
+					}
+				}
+			}
+			return found;
+		},
+		/*
+		 * Add a class name to the class attribute of a node
+		 *
+		 * @param	object		node: the node
+		 * @param	string		className: the name of the class to be added
+		 * @return	void
+		 */
+		addClass: function (node, className) {
+			if (node) {
+				HTMLArea.DOM.removeClass(node, className);
+					// Remove classes configured to be incompatible with the class to be added
+				if (node.className && HTMLArea.classesXOR && HTMLArea.classesXOR[className] && Ext.isFunction(HTMLArea.classesXOR[className].test)) {
+					var classNames = node.className.trim().split(' ');
+					for (var i = classNames.length; --i >= 0;) {
+						if (HTMLArea.classesXOR[className].test(classNames[i])) {
+							HTMLArea.DOM.removeClass(node, classNames[i]);
+						}
+					}
+				}
+				if (node.className) {
+					node.className += ' ' + className;
+				} else {
+					node.className = className;
+				}
+			}
+		},
+		/*
+		 * Remove a class name from the class attribute of a node
+		 *
+		 * @param	object		node: the node
+		 * @param	string		className: the class name to removed
+		 * @param	boolean		substring: if true, remove the class names starting with the given string
+		 * @return	void
+		 */
+		removeClass: function (node, className, substring) {
+			if (node && node.className) {
+				var classes = node.className.trim().split(' ');
+				var newClasses = [];
+				for (var i = classes.length; --i >= 0;) {
+					if ((!substring && classes[i] != className) || (substring && classes[i].indexOf(className) != 0)) {
+						newClasses[newClasses.length] = classes[i];
+					}
+				}
+				if (newClasses.length) {
+					node.className = newClasses.join(' ');
+				} else {
+					if (!Ext.isOpera) {
+						node.removeAttribute('class');
+						if (Ext.isIE) {
+							node.removeAttribute('className');
+						}
+					} else {
+						node.className = '';
+					}
+				}
+			}
+		}
 	};
 }();
 /***************************************************
@@ -3101,7 +3272,7 @@
 		keepTags: /.*/i,
 		removeAttributes: /none/i,
 		removeTrailingBR: true
-	}
+	};
 	Ext.apply(this, config, configDefaults);
 };
 HTMLArea.DOM.Walker = Ext.extend(HTMLArea.DOM.Walker, {
@@ -3303,6 +3474,304 @@
 	}
 });
 /***************************************************
+ *  HTMLArea.CSS.Parser: CSS Parser
+ ***************************************************/
+HTMLArea.CSS.Parser = Ext.extend(Ext.util.Observable, {
+	/*
+	 * HTMLArea.CSS.Parser constructor
+	 */
+	constructor: function (config) {
+		HTMLArea.CSS.Parser.superclass.constructor.call(this, {});
+		var configDefaults = {
+			parseAttemptsMaximumNumber: 17,
+			prefixLabelWithClassName: false,
+			postfixLabelWithClassName: false,
+			showTagFreeClasses: false,
+			tags: null,
+			editor: null
+		};
+		Ext.apply(this, config, configDefaults);
+		this.addEvents(
+			/*
+			 * @event HTMLAreaEventCssParsingComplete
+			 * Fires when parsing of the stylesheets of the iframe is complete
+			 */
+			'HTMLAreaEventCssParsingComplete'
+		);
+	},
+	/*
+	 * The parsed classes
+	 */
+	parsedClasses: {},
+	/*
+	 * Boolean indicating whether are not parsing is complete
+	 */
+	isReady: false,
+	/*
+	 * Boolean indicating whether or not the stylesheets were accessible
+	 */
+	cssLoaded: false,
+	/*
+	 * Counter of the number of attempts at parsing the stylesheets
+	 */
+	parseAttemptsCounter: 0,
+	/*
+	 * Parsing attempt timeout id
+	 */
+	attemptTimeout: null,
+	/*
+	 * The error that occurred on the last attempt at parsing the stylesheets
+	 */
+	error: null,
+	/*
+	 * This function gets the parsed css classes
+	 *
+	 * @return	object	this.parsedClasses
+	 */
+	getClasses: function() {
+		return this.parsedClasses;
+	},
+	/*
+	 * This function initiates parsing of the stylesheets
+	 *
+	 * @return	void
+	 */
+	initiateParsing: function () {
+		if (this.editor.config.classesUrl && (typeof(HTMLArea.classesLabels) === 'undefined')) {
+			this.editor.ajax.getJavascriptFile(this.editor.config.classesUrl, function (options, success, response) {
+				if (success) {
+					try {
+						if (typeof(HTMLArea.classesLabels) === 'undefined') {
+							eval(response.responseText);
+							this.editor.appendToLog('HTMLArea.CSS.Parser', 'initiateParsing', 'Javascript file successfully evaluated: ' + this.editor.config.classesUrl);
+						}
+					} catch(e) {
+						this.editor.appendToLog('HTMLArea.CSS.Parser', 'initiateParsing', 'Error evaluating contents of Javascript file: ' + this.editor.config.classesUrl);
+					}
+				}
+				this.parse();
+			}, this);
+		} else {
+			this.parse();
+		}
+	},
+	/*
+	 * This function parses the stylesheets of the iframe set in config
+	 *
+	 * @return	void	parsed css classes are accumulated in this.parsedClasses
+	 */
+	parse: function() {
+		if (this.editor.document) {
+			this.parseStyleSheets();
+			if (!this.cssLoaded) {
+				if (this.parseAttemptsCounter < this.parseAttemptsMaximumNumber) {
+					this.attemptTimeout = this.parse.defer(200, this);
+					this.parseAttemptsCounter++;
+				} else {
+					this.editor.appendToLog('HTMLArea.CSS.Parser', 'parse', 'The stylesheets could not be parsed. Reported error: ' + this.error);
+					this.fireEvent('HTMLAreaEventCssParsingComplete');
+				}
+			} else {
+				this.attemptTimeout = null;
+				this.isReady = true;
+				this.filterAllowedClasses();
+				this.sort();
+				this.fireEvent('HTMLAreaEventCssParsingComplete');
+			}
+		}
+	},
+	/*
+	 * This function parses the stylesheets of an iframe
+	 *
+	 * @return	void	parsed css classes are accumulated in this.parsedClasses
+	 */
+	parseStyleSheets: function () {
+		this.cssLoaded = true;
+		this.error = null;
+		for (var i = 0; i < this.editor.document.styleSheets.length; i++) {
+			if (!Ext.isIE) {
+				try {
+					this.parseRules(this.editor.document.styleSheets[i].cssRules);
+				} catch (e) {
+					this.error = e;
+					this.cssLoaded = false;
+					this.parsedClasses = {};
+				}
+			} else {
+				try{
+					if (this.editor.document.styleSheets[i].imports) {
+						this.parseIeRules(this.editor.document.styleSheets[i].imports);
+					}
+					if (this.editor.document.styleSheets[i].rules) {
+						this.parseRules(this.editor.document.styleSheets[i].rules);
+					}
+				} catch (e) {
+					this.error = e;
+					this.cssLoaded = false;
+					this.parsedClasses = {};
+				}
+			}
+		}
+	},
+	/*
+	 * This function parses the set of rules from a standard stylesheet
+	 *
+	 * @param	array		cssRules: the array of rules of a stylesheet
+	 * @return	void
+	 */
+	parseRules: function (cssRules) {
+		for (var rule = 0; rule < cssRules.length; rule++) {
+				// Style rule
+			if (cssRules[rule].selectorText) {
+				this.parseSelectorText(cssRules[rule].selectorText);
+			} else {
+					// Import rule
+				if (cssRules[rule].styleSheet) {
+					this.parseRules(cssRules[rule].styleSheet.cssRules);
+				}
+					// Media rule
+				if (cssRules[rule].cssRules) {
+					this.parseRules(cssRules[rule].cssRules);
+				}
+			}
+		}
+	},
+	/*
+	 * This function parses the set of rules from an IE stylesheet
+	 *
+	 * @param	array		cssRules: the array of rules of a stylesheet
+	 * @return	void
+	 */
+	parseIeRules: function (cssRules) {
+		for (var rule = 0; rule < cssRules.length; rule++) {
+				// Import rule
+			if (cssRules[rule].imports) {
+				this.parseIeRules(cssRules[rule].imports);
+			}
+				// Style rule
+			if (cssRules[rule].rules) {
+				this.parseRules(cssRules[rule].rules);
+			}
+		}
+	},
+	/*
+	 * This function parses a selector rule
+	 *
+	 * @param 	string		selectorText: the text of the rule to parsed
+	 * @return	void
+	 */
+	parseSelectorText: function (selectorText) {
+		var cssElements = [],
+			cssElement = [],
+			nodeName, className,
+			pattern = /(\S*)\.(\S+)/;
+		if (selectorText.search(/:+/) == -1) {
+				// Split equal styles
+			cssElements = selectorText.split(',');
+			for (var k = 0; k < cssElements.length; k++) {
+					// Match all classes (<element name (optional)>.<class name>) in selector rule
+				var s = cssElements[k], index;
+				while ((index = s.search(pattern)) > -1) {
+					var match = pattern.exec(s.substring(index));
+					s = s.substring(index+match[0].length);
+					nodeName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : 'all';
+					className = match[2];
+					if (className && !HTMLArea.reservedClassNames.test(className)) {
+						if (((nodeName != 'all') && (!this.tags || !this.tags[nodeName]))
+							|| ((nodeName == 'all') && (!this.tags || !this.tags[nodeName]) && this.showTagFreeClasses)
+							|| (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses && this.tags[nodeName].allowedClasses.test(className))) {
+							if (!this.parsedClasses[nodeName]) {
+								this.parsedClasses[nodeName] = {};
+							}
+							cssName = className;
+							if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
+								cssName = this.prefixLabelWithClassName ? (className + ' - ' + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
+								cssName = this.postfixLabelWithClassName ? (cssName + ' - ' + className) : cssName;
+							}
+							this.parsedClasses[nodeName][className] = cssName;
+						}
+					}
+				}
+			}
+		}
+	},
+	/*
+	 * This function filters the class selectors allowed for each nodeName
+	 *
+	 * @return	void
+	 */
+	filterAllowedClasses: function() {
+		Ext.iterate(this.tags, function (nodeName) {
+			var allowedClasses = {};
+				// Get classes allowed for all tags
+			if (nodeName !== 'all' && Ext.isDefined(this.parsedClasses['all'])) {
+				if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
+					var allowed = this.tags[nodeName].allowedClasses;
+					Ext.iterate(this.parsedClasses['all'], function (cssClass, value) {
+						if (allowed.test(cssClass)) {
+							allowedClasses[cssClass] = value;
+						}
+					});
+				} else {
+					allowedClasses = this.parsedClasses['all'];
+				}
+			}
+				// Merge classes allowed for nodeName
+			if (Ext.isDefined(this.parsedClasses[nodeName])) {
+				if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
+					var allowed = this.tags[nodeName].allowedClasses;
+					Ext.iterate(this.parsedClasses[nodeName], function (cssClass, value) {
+						if (allowed.test(cssClass)) {
+							allowedClasses[cssClass] = value;
+						}
+					});
+				} else {
+					Ext.iterate(this.parsedClasses[nodeName], function (cssClass, value) {
+						allowedClasses[cssClass] = value;
+					});
+				}
+			}
+			this.parsedClasses[nodeName] = allowedClasses;
+		}, this);
+			// If showTagFreeClasses is set and there is no allowedClasses clause on a tag, merge classes allowed for all tags
+		if (this.showTagFreeClasses && Ext.isDefined(this.parsedClasses['all'])) {
+			Ext.iterate(this.parsedClasses, function (nodeName) {
+				if (nodeName !== 'all' && !this.tags[nodeName]) {
+					Ext.iterate(this.parsedClasses['all'], function (cssClass, value) {
+						this.parsedClasses[nodeName][cssClass] = value;
+					}, this);
+				}
+			}, this);
+		}
+	},
+	/*
+	 * This function sorts the class selectors for each nodeName
+	 *
+	 * @return	void
+	 */
+	sort: function() {
+		Ext.iterate(this.parsedClasses, function (nodeName, value) {
+			var classes = [];
+			var sortedClasses= {};
+				// Collect keys
+			Ext.iterate(value, function (cssClass) {
+				classes.push(cssClass);
+			});
+			function compare(a, b) {
+				x = value[a];
+				y = value[b];
+				return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+			}
+				// Sort keys by comparing texts
+			classes = classes.sort(compare);
+			for (var i = 0; i < classes.length; ++i) {
+				sortedClasses[classes[i]] = value[classes[i]];
+			}
+			this.parsedClasses[nodeName] = sortedClasses;
+		}, this);
+	}
+});
+/***************************************************
  *  TIPS ON FORM FIELDS AND MENU ITEMS
  ***************************************************/
 /*
@@ -4156,7 +4625,7 @@
 	 * @return	string		the localization of the label
 	 */
 	localize: function (label) {
-		return this.I18N[label] || HTMLArea.I18N.dialogs[label] || HTMLArea.I18N.tooltips[label] || HTMLArea.I18N.msg[label];
+		return this.I18N[label] || HTMLArea.localize(label);
 	},
 	/**
 	 * Load a Javascript file asynchronously
@@ -4167,22 +4636,8 @@
 	 * @return	boolean		true on success of the request submission
 	 */
 	getJavascriptFile: function (url, callback) {
-		var success = false;
 		this.appendToLog('getJavascriptFile', 'Requesting script ' + url);
-		Ext.Ajax.request({
-			method: 'GET',
-			url: url,
-			callback: callback,
-			success: function (response) {
-				success = true;
-			},
-			failure: function (response) {
-				this.editor.inhibitKeyboardInput = false;
-				this.appendToLog('getJavascriptFile', 'Unable to get ' + url + ' . Server reported ' + response.status);
-			},
-			scope: this
-		});
-		return success;
+		return this.editor.ajax.getJavascriptFile(url, callback, this);
 	},
 	/**
 	 * Post data to the server
@@ -4193,39 +4648,10 @@
 	 *
 	 * @return	boolean		true on success
 	 */
-	 postData: function (url, data, callback) {
-		var success = false;
-		data.charset = this.editorConfiguration.typo3ContentCharset ? this.editorConfiguration.typo3ContentCharset : 'utf-8';
-		var params = '';
-		Ext.iterate(data, function (parameter, value) {
-			params += (params.length ? '&' : '') + parameter + '=' + encodeURIComponent(value);
-		});
-		params += this.editorConfiguration.RTEtsConfigParams;
-		this.appendToLog('postData', 'Posting to ' + url + '. Data: ' + params);
-		Ext.Ajax.request({
-			method: 'POST',
-			headers: {
-				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
-			},
-			url: url,
-			params: params,
-			callback: Ext.isFunction(callback) ? callback: function (options, success, response) {
-				if (success) {
-					this.appendToLog('postData', 'Post request to ' + url + ' successful. Server response: ' + response.responseText);
-				} else {
-					this.appendToLog('postData', 'Post request to ' + url + ' failed. Server reported ' + response.status);
-				}
-			},
-			success: function (response) {
-				success = true;
-			},
-			failure: function (response) {
-				this.appendToLog('postData', 'Unable to post ' + url + ' . Server reported ' + response.status);
-			},
-			scope: this
-		});
-		return success;
-	 },
+	postData: function (url, data, callback) {
+	 	this.appendToLog('postData', 'Posting to ' + url + '. Data: ' + params);
+	 	return this.editor.ajax.postData(url, data, callback, this);
+	},
 	/**
 	 ***********************************************
 	 * THIS FUNCTION IS DEPRECATED AS OF TYPO3 4.4 *
@@ -4390,7 +4816,7 @@
 	 * @return	void
 	 */
 	appendToLog: function (functionName, text) {
-		HTMLArea._appendToLog('[' + this.name + '::' + functionName + ']: ' + text);
+		this.editor.appendToLog(this.name, functionName, text);
 	},
 	/*
 	 * Add a config element to config array if not empty
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockElements/block-elements.js	(copie de travail)
@@ -373,10 +373,10 @@
 						this.appendToLog("onButtonPress", e + "\n\nby execCommand(" + buttonId + ");");
 					}
 				} else if (this.isAllowedBlockElement("div")) {
-					if (/^div$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass[buttonId])) {
-						HTMLArea._addClass(parentElement, this.useClass[buttonId]);
-					} else if (!/^div$/i.test(parentElement.nodeName) && /^div$/i.test(parentElement.parentNode.nodeName) && !HTMLArea._hasClass(parentElement.parentNode, this.useClass[buttonId])) {
-						HTMLArea._addClass(parentElement.parentNode, this.useClass[buttonId]);
+					if (/^div$/i.test(parentElement.nodeName) && !HTMLArea.DOM.hasClass(parentElement, this.useClass[buttonId])) {
+						HTMLArea.DOM.addClass(parentElement, this.useClass[buttonId]);
+					} else if (!/^div$/i.test(parentElement.nodeName) && /^div$/i.test(parentElement.parentNode.nodeName) && !HTMLArea.DOM.hasClass(parentElement.parentNode, this.useClass[buttonId])) {
+						HTMLArea.DOM.addClass(parentElement.parentNode, this.useClass[buttonId]);
 					} else {
 						var bookmark = this.editor.getBookmark(range);
 						var newBlock = this.wrapSelectionInBlockElement("div", this.useClass[buttonId], null, true);
@@ -387,7 +387,7 @@
 				}
 				break;
 			case "Outdent" :
-				if (/^(ol|ul)$/i.test(parentElement.nodeName) && !HTMLArea._hasClass(parentElement, this.useClass.Indent)) {
+				if (/^(ol|ul)$/i.test(parentElement.nodeName) && !HTMLArea.DOM.hasClass(parentElement, this.useClass.Indent)) {
 					if (/^(li)$/i.test(parentElement.parentNode.nodeName)) {
 						if (Ext.isOpera) {
 							try {
@@ -433,7 +433,7 @@
 					}
 				} else if (this.isAllowedBlockElement("div")) {
 					for (var i = blockAncestors.length; --i >= 0;) {
-						if (HTMLArea._hasClass(blockAncestors[i], this.useClass.Indent)) {
+						if (HTMLArea.DOM.hasClass(blockAncestors[i], this.useClass.Indent)) {
 							var bookmark = this.editor.getBookmark(range);
 							var newBlock = this.wrapSelectionInBlockElement("div", false, blockAncestors[i]);
 								// If not directly under the div, we need to backtrack
@@ -447,7 +447,7 @@
 								newBlock.appendChild(parent);
 							}
 							newBlock.className = blockAncestors[i].className;
-							HTMLArea._removeClass(newBlock, this.useClass.Indent);
+							HTMLArea.DOM.removeClass(newBlock, this.useClass.Indent);
 							if (!newBlock.previousSibling) {
 								while (newBlock.hasChildNodes()) {
 									if (newBlock.firstChild.nodeType == 1) {
@@ -608,7 +608,7 @@
 		}
 		var blockElement = this.editor._doc.createElement(blockName);
 		if (useClass) {
-			HTMLArea._addClass(blockElement, useClass);
+			HTMLArea.DOM.addClass(blockElement, useClass);
 		}
 		var contextElement = endAncestors[0];
 		if (i) {
@@ -664,13 +664,13 @@
 				if (HTMLArea.isBlockElement(block)) {
 					switch (buttonId) {
 						case "Indent" :
-							if (!HTMLArea._hasClass(block, this.useClass[buttonId])) {
-								HTMLArea._addClass(block, this.useClass[buttonId]);
+							if (!HTMLArea.DOM.hasClass(block, this.useClass[buttonId])) {
+								HTMLArea.DOM.addClass(block, this.useClass[buttonId]);
 							}
 							break;
 						case "Outdent" :
-							if (HTMLArea._hasClass(block, this.useClass["Indent"])) {
-								HTMLArea._removeClass(block, this.useClass["Indent"]);
+							if (HTMLArea.DOM.hasClass(block, this.useClass["Indent"])) {
+								HTMLArea.DOM.removeClass(block, this.useClass["Indent"]);
 							}
 							break;
 						case "JustifyLeft"   :
@@ -683,7 +683,7 @@
 							if (this.standardBlockElements.test(buttonId.toLowerCase()) && buttonId.toLowerCase() == block.nodeName.toLowerCase()) {
 								this.cleanClasses(block);
 								if (className) {
-									HTMLArea._addClass(block, className);
+									HTMLArea.DOM.addClass(block, className);
 								}
 							}
 							break;
@@ -702,10 +702,10 @@
 	toggleAlignmentClass : function(block, buttonId) {
 		for (var alignmentButtonId in this.useClass) {
 			if (this.useClass.hasOwnProperty(alignmentButtonId) && alignmentButtonId !== "Indent") {
-				if (HTMLArea._hasClass(block, this.useClass[alignmentButtonId])) {
-					HTMLArea._removeClass(block, this.useClass[alignmentButtonId]);
+				if (HTMLArea.DOM.hasClass(block, this.useClass[alignmentButtonId])) {
+					HTMLArea.DOM.removeClass(block, this.useClass[alignmentButtonId]);
 				} else if (alignmentButtonId === buttonId) {
-					HTMLArea._addClass(block, this.useClass[alignmentButtonId]);
+					HTMLArea.DOM.addClass(block, this.useClass[alignmentButtonId]);
 				}
 			}
 		}
@@ -997,15 +997,15 @@
 			if (!HTMLArea.reservedClassNames.test(classNames[i])) {
 				if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
 					if (!this.tags[nodeName].allowedClasses.test(classNames[i])) {
-						HTMLArea._removeClass(node, classNames[i]);
+						HTMLArea.DOM.removeClass(node, classNames[i]);
 					}
 				} else if (this.tags && this.tags.all && this.tags.all.allowedClasses) {
 					if (!this.tags.all.allowedClasses.test(classNames[i])) {
-						HTMLArea._removeClass(node, classNames[i]);
+						HTMLArea.DOM.removeClass(node, classNames[i]);
 					}
 				}
 				if (this.formatBlockItems[nodeName] && this.formatBlockItems[nodeName].classList && this.formatBlockItems[nodeName].classList.test(classNames[i])) {
-					HTMLArea._removeClass(node, classNames[i]);
+					HTMLArea.DOM.removeClass(node, classNames[i]);
 				}
 			}
 		}
@@ -1050,7 +1050,7 @@
 							commandState = true;
 						} else {
 							for (var j = blockAncestors.length; --j >= 0;) {
-								if (HTMLArea._hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) {
+								if (HTMLArea.DOM.hasClass(blockAncestors[j], this.useClass.Indent) || /^(td|th)$/i.test(blockAncestors[j].nodeName)) {
 									commandState = true;
 									break;
 								}
@@ -1090,7 +1090,7 @@
 								button.setDisabled(false);
 								commandState = true;
 								for (var block = startAncestors[index]; block; block = block.nextSibling) {
-									commandState = commandState && HTMLArea._hasClass(block, this.useClass[button.itemId]);
+									commandState = commandState && HTMLArea.DOM.hasClass(block, this.useClass[button.itemId]);
 									if (block == endAncestors[index]) {
 										break;
 									}
@@ -1159,7 +1159,7 @@
 				// 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);
+				return item && item.tagName == nodeName && item.addClass && HTMLArea.DOM.hasClass(deepestBlockAncestor, item.addClass);
 			}, this);
 			if (index == -1) {
 					// ... or a standard one
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/BlockStyle/block-style.js	(copie de travail)
@@ -32,20 +32,14 @@
  * TYPO3 SVN ID: $Id$
  */
 HTMLArea.BlockStyle = HTMLArea.Plugin.extend({
-		
 	constructor : function(editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-	
 	/*
 	 * This function gets called by the class constructor
 	 */
-	configurePlugin : function(editor) {
-		this.cssLoaded = false;
-		this.cssTimeout = null;
-		this.cssParseCount = 0;
-		this.cssArray = new Object();
-		
+	configurePlugin: function (editor) {
+		this.cssArray = {};
 		this.classesUrl = this.editorConfiguration.classesUrl;
 		this.pageTSconfiguration = this.editorConfiguration.buttons.blockstyle;
 		this.tags = this.pageTSconfiguration.tags;
@@ -95,21 +89,19 @@
 		this.showTagFreeClasses = this.pageTSconfiguration.showTagFreeClasses || this.editorConfiguration.showTagFreeClasses;
 		this.prefixLabelWithClassName = this.pageTSconfiguration.prefixLabelWithClassName;
 		this.postfixLabelWithClassName = this.pageTSconfiguration.postfixLabelWithClassName;
-		
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.4",
-			developer	: "Stanislas Rolland",
-			developerUrl	: "http://www.sjbr.ca/",
-			copyrightOwner	: "Stanislas Rolland",
-			sponsor		: this.localize("Technische Universitat Ilmenau"),
-			sponsorUrl	: "http://www.tu-ilmenau.de/",
-			license		: "GPL"
+			version		: '2.0',
+			developer	: 'Stanislas Rolland',
+			developerUrl	: 'http://www.sjbr.ca/',
+			copyrightOwner	: 'Stanislas Rolland',
+			sponsor		: this.localize('Technische Universitat Ilmenau'),
+			sponsorUrl	: 'http://www.tu-ilmenau.de/',
+			license		: 'GPL'
 		};
 		this.registerPluginInformation(pluginInformation);
-		
 		/*
 		 * Registering the drop-down list
 		 */
@@ -139,11 +131,10 @@
 		this.registerDropDown(dropDownConfiguration);
 		return true;
 	},
-	
 	/*
-	 * This function gets called when some block style was selected in the drop-down list
+	 * This handler gets called when some block style was selected in the drop-down list
 	 */
-	onChange : function (editor, combo, record, index) {
+	onChange: function (editor, combo, record, index) {
 		var className = combo.getValue();
 		this.editor.focus();
 		var blocks = this.getSelectedBlocks();
@@ -160,16 +151,15 @@
 			}
 		}
 	},
-	
 	/*
 	 * This function applies the class change to the node
 	 */
-	applyClassChange : function (node, className) {
+	applyClassChange: function (node, className) {
 		if (className == "none") {
 			var classNames = node.className.trim().split(" ");
 			for (var i = classNames.length; --i >= 0;) {
 				if (!HTMLArea.reservedClassNames.test(classNames[i])) {
-					HTMLArea._removeClass(node, classNames[i]);
+					HTMLArea.DOM.removeClass(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]);
@@ -181,25 +171,24 @@
 			var nodeName = node.nodeName.toLowerCase();
 			if (this.tags && this.tags[nodeName] && this.tags[nodeName].allowedClasses) {
 				if (this.tags[nodeName].allowedClasses.test(className)) {
-					HTMLArea._addClass(node, className);
+					HTMLArea.DOM.addClass(node, className);
 				}
 			} else if (this.tags && this.tags.all && this.tags.all.allowedClasses) {
 				if (this.tags.all.allowedClasses.test(className)) {
-					HTMLArea._addClass(node, className);
+					HTMLArea.DOM.addClass(node, className);
 				}
 			} else {
-				HTMLArea._addClass(node, className);
+				HTMLArea.DOM.addClass(node, className);
 			}
 			if (nodeName === "table" && this.getPluginInstance('TableOperations')) {
 				this.getPluginInstance('TableOperations').reStyleTable(node);
 			}
 		}
 	},
-	
 	/*
 	 * This function gets the list of selected blocks
 	 */
-	getSelectedBlocks : function() {
+	getSelectedBlocks: function () {
 		var block, range, i = 0, blocks = [];
 		var statusBarSelection = this.editor.statusBar ? this.editor.statusBar.getSelection() : null;
 		if (Ext.isGecko) {
@@ -218,67 +207,54 @@
 		return blocks;
 	},
 	/*
-	 * This function gets called when the editor is generated
+	 * This handler 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 (!Ext.isIE) {
-			this.generate(this.editor, 'BlockStyle');
-		}
+		this.editor.iframe.mon(this.editor, 'HTMLAreaEventModeChange', this.onModeChange, this);
+			// Create CSS Parser object
+		this.blockStyles = new HTMLArea.CSS.Parser({
+			prefixLabelWithClassName: this.prefixLabelWithClassName,
+			postfixLabelWithClassName: this.postfixLabelWithClassName,
+			showTagFreeClasses: this.showTagFreeClasses,
+			tags: this.tags,
+			editor: this.editor
+		});
+			// Monitor css parsing being completed
+		this.editor.iframe.mon(this.blockStyles, 'HTMLAreaEventCssParsingComplete', this.onCssParsingComplete, this);
+		this.blockStyles.initiateParsing();
 	},
 	/*
-	 * This function gets called when the toolbar is being updated
+	 * This handler gets called when parsing of css classes is completed
 	 */
-	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
-		if (mode === 'wysiwyg') {
-			this.generate(this.editor, button.itemId);
+	onCssParsingComplete: function () {
+		if (this.blockStyles.isReady) {
+			this.cssArray = this.blockStyles.getClasses();
 		}
+		if (this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateValue('BlockStyle');
+		}
 	},
 	/*
-	 * This function gets called when the editor has changed its mode to "wysiwyg"
+	 * This handler gets called when the toolbar is being updated
 	 */
-	onModeChange: function(mode) {
-		if (this.getEditorMode() === "wysiwyg") {
-			this.generate(this.editor, "BlockStyle");
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateValue(button.itemId);
 		}
 	},
 	/*
-	 * 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
+	 * This handler gets called when the editor has changed its mode to "wysiwyg"
 	 */
-	generate: function(editor, dropDownId) {
-		if (this.cssLoaded && this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
-			this.updateValue(dropDownId);
-		} else {
-			if (this.cssTimeout) {
-				window.clearTimeout(this.cssTimeout);
-				this.cssTimeout = null;
-			}
-			if (this.classesUrl && (typeof(HTMLArea.classesLabels) === 'undefined')) {
-				this.getJavascriptFile(this.classesUrl, function (options, success, response) {
-					if (success) {
-						try {
-							if (typeof(HTMLArea.classesLabels) === 'undefined') {
-								eval(response.responseText);
-								this.appendToLog('generate', 'Javascript file successfully evaluated: ' + this.classesUrl);
-							}
-						} catch(e) {
-							this.appendToLog('generate', 'Error evaluating contents of Javascript file: ' + this.classesUrl);
-						}
-					}
-					this.buildCssArray(this.editor, dropDownId);
-				});
-			} else {
-				this.buildCssArray(this.editor, dropDownId);
-			}
+	onModeChange: function(mode) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateValue('BlockStyle');
 		}
 	},
-	
 	/*
 	 * This function updates the current value of the dropdown list
 	 */
-	updateValue : function(dropDownId) {
+	updateValue: function(dropDownId) {
 		var dropDown = this.getButton(dropDownId);
 		if (dropDown) {
 			var classNames = new Array();
@@ -290,7 +266,7 @@
 			}
 			if (parent) {
 				tagName = parent.nodeName.toLowerCase();
-				classNames = this.getClassNames(parent);
+				classNames = HTMLArea.DOM.getClassNames(parent);
 			}
 			if (tagName && tagName !== "body"){
 				this.buildDropDownOptions(dropDown, tagName);
@@ -301,34 +277,10 @@
 			}
 		}
 	},
-	
 	/*
-	 * This function returns an array containing the class names assigned to the node
-	 */
-	getClassNames : function (node) {
-		var classNames = new Array();
-		if (node) {
-			if (node.className && /\S/.test(node.className)) {
-				classNames = node.className.trim().split(" ");
-			}
-			if (HTMLArea.reservedClassNames.test(node.className)) {
-				var cleanClassNames = new Array();
-				var j = -1;
-				for (var i = 0; i < classNames.length; ++i) {
-					if (!HTMLArea.reservedClassNames.test(classNames[i])) {
-						cleanClassNames[++j] = classNames[i];
-					}
-				}
-				return cleanClassNames;
-			}
-		}
-		return classNames;
-	},
-	
-	/*
 	 * This function reinitializes the options of the dropdown
 	 */
-	initializeDropDown : function (dropDown) {
+	initializeDropDown: function (dropDown) {
 		var store = dropDown.getStore();
 		store.removeAll(false);
 		store.insert(0, new store.recordType({
@@ -337,94 +289,40 @@
 		}));
 		dropDown.setValue('none');
 	},
-	
 	/*
 	 * This function builds the options to be displayed in the dropDown box
 	 */
-	buildDropDownOptions : function (dropDown, tagName) {
+	buildDropDownOptions: function (dropDown, nodeName) {
 		var store = dropDown.getStore();
-		var cssArray = new Array();
 		this.initializeDropDown(dropDown);
-			// 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];
-					}
-				}
+		if (this.blockStyles.isReady) {
+			var allowedClasses = {};
+			if (Ext.isDefined(this.cssArray[nodeName])) {
+				allowedClasses = this.cssArray[nodeName];
+			} else if (this.showTagFreeClasses && Ext.isDefined(this.cssArray['all'])) {
+				allowedClasses = this.cssArray['all'];
 			}
-		}
-			// 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];
+			Ext.iterate(allowedClasses, function (cssClass, value) {
+				var style = null;
+				if (!this.editor.config.disablePCexamples) {
+					if (HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
+						style = HTMLArea.classesValues[cssClass];
+					} else if (/-[0-9]+$/.test(cssClass) && HTMLArea.classesValues[RegExp.leftContext + '-'])  {
+						style = HTMLArea.classesValues[RegExp.leftContext + '-'];
 					}
 				}
-			} 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;
+				store.add(new store.recordType({
+					text: value,
+					value: cssClass,
+					style: style
+				}));
+			}, this);
 		}
-		for (var cssClass in cssArray) {
-			if (cssArray.hasOwnProperty(cssClass) && cssArray[cssClass]) {
-				if (cssClass == 'none') {
-					store.getAt(0).set('text', cssArray[cssClass]);
-				} else {
-					var style = null;
-					if (!this.editor.config.disablePCexamples) {
-						if (HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) {
-							style = HTMLArea.classesValues[cssClass];
-						} else if (/-[0-9]+$/.test(cssClass) && HTMLArea.classesValues[RegExp.leftContext + '-'])  {
-							style = HTMLArea.classesValues[RegExp.leftContext + '-'];
-						}
-					}
-					store.add(new store.recordType({
-						text: cssArray[cssClass],
-						value: cssClass,
-						style: style
-					}));
-				}
-			}
-		}
 	},
-	
 	/*
 	 * This function sets the selected option of the dropDown box
 	 */
-	setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) {
+	setSelectedOption: function (dropDown, classNames, noUnknown, defaultClass) {
 		var store = dropDown.getStore();
 		dropDown.setValue('none');
 		if (classNames.length) {
@@ -454,173 +352,5 @@
 			});
 		}
 		dropDown.setDisabled(!(store.getCount()>1));
-	},
-	
-	/*
-	 * This function builds the main array of class selectors
-	 */
-	buildCssArray : function(editor, dropDownId) {
-		this.cssArray = this.parseStyleSheet();
-		if (!this.cssLoaded && (this.cssParseCount < 17)) {
-			this.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]);
-			this.cssParseCount++;
-		} else {
-			this.cssTimeout = null;
-			this.cssLoaded = true;
-			this.cssArray = this.sortCssArray(this.cssArray);
-			this.updateValue(dropDownId);
-		}
-	},
-	
-	/*
-	 * This function parses the stylesheets
-	 */
-	parseStyleSheet : function() {
-		var iframe = this.editor._iframe.contentWindow ? this.editor._iframe.contentWindow.document : this.editor._iframe.contentDocument;
-		var newCssArray = new Object();
-		this.cssLoaded = true;
-		for (var i = 0; i < iframe.styleSheets.length; i++) {
-			if (!Ext.isIE) {
-				try {
-					newCssArray = this.parseCssRule(iframe.styleSheets[i].cssRules, newCssArray);
-				} catch(e) {
-					this.cssLoaded = false;
-				}
-			} else {
-				try{
-						// @import StyleSheets (IE)
-					if (iframe.styleSheets[i].imports) {
-						newCssArray = this.parseCssIEImport(iframe.styleSheets[i].imports, newCssArray);
-					}
-					if (iframe.styleSheets[i].rules) {
-						newCssArray = this.parseCssRule(iframe.styleSheets[i].rules, newCssArray);
-					}
-				} catch(e) {
-					this.cssLoaded = false;
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
-	/*
-	 * This function parses IE import rules
-	 */
-	parseCssIEImport : function(cssIEImport, cssArray) {
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		for (var i=0; i < cssIEImport.length; i++) {
-			if (cssIEImport[i].imports) {
-				newCssArray = this.parseCssIEImport(cssIEImport[i].imports, newCssArray);
-			}
-			if (cssIEImport[i].rules) {
-				newCssArray = this.parseCssRule(cssIEImport[i].rules, newCssArray);
-			}
-		}
-		return newCssArray;
-	},
-	
-	/*
-	 * This function parses gecko css rules
-	 */
-	parseCssRule : function(cssRules, cssArray) {
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		for (var rule = 0; rule < cssRules.length; rule++) {
-				// StyleRule
-			if (cssRules[rule].selectorText) {
-				newCssArray = this.parseSelectorText(cssRules[rule].selectorText, newCssArray);
-			} else {
-					// ImportRule (Mozilla)
-				if (cssRules[rule].styleSheet) {
-					newCssArray = this.parseCssRule(cssRules[rule].styleSheet.cssRules, newCssArray);
-				}
-					// MediaRule (Mozilla)
-				if (cssRules[rule].cssRules) {
-					newCssArray = this.parseCssRule(cssRules[rule].cssRules, newCssArray);
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
-	/*
-	 * This function parses each selector rule
-	 */
-	parseSelectorText : function(selectorText, cssArray) {
-		var cssElements = new Array();
-		var cssElement = new Array();
-		var tagName, className;
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		if (selectorText.search(/:+/) == -1) {
-				// split equal Styles (Mozilla-specific) e.q. head, body {border:0px}
-				// for ie not relevant. returns allways one element
-			cssElements = selectorText.split(",");
-			for (var k = 0; k < cssElements.length; k++) {
-					// Match ALL classes (<element name (optional)>.<class name>) in selector rule
-				var s = cssElements[k],
-					pattern = /(\S*)\.(\S+)/,
-					index;
-				while ((index = s.search(pattern)) > -1) {
-					var match = pattern.exec(s.substring(index));
-					s = s.substring(index+match[0].length);
-
-					tagName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : "all";
-					className = match[2];
-
-					if (className && !HTMLArea.reservedClassNames.test(className)) {
-						if (((tagName != "all") && (!this.tags || !this.tags[tagName]))
-							|| ((tagName == "all") && (!this.tags || !this.tags[tagName]) && this.showTagFreeClasses)
-							|| (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses && this.tags[tagName].allowedClasses.test(className))) {
-							if (!newCssArray[tagName]) {
-								newCssArray[tagName] = new Object();
-							}
-							if (className) {
-								cssName = className;
-								if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
-									cssName = this.prefixLabelWithClassName ? (className + " - " + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
-									cssName = this.postfixLabelWithClassName ? (cssName + " - " + className) : cssName;
-								}
-							} else {
-								className = "none";
-								cssName = this.localize("Element style");
-							}
-							newCssArray[tagName][className] = cssName;
-						}
-					}
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
-	/*
-	 * This function sorts the main array of class selectors
-	 */
-	sortCssArray : function(cssArray) {
-		var newCssArray = new Object();
-		for (var tagName in cssArray) {
-			if (cssArray.hasOwnProperty(tagName)) {
-				newCssArray[tagName] = new Object();
-				var tagArrayKeys = new Array();
-				for (var cssClass in cssArray[tagName]) {
-					if (cssArray[tagName].hasOwnProperty(cssClass)) {
-						tagArrayKeys.push(cssClass);
-					}
-				}
-				function compare(a, b) {
-					x = cssArray[tagName][a];
-					y = cssArray[tagName][b];
-					return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-				}
-				tagArrayKeys = tagArrayKeys.sort(compare);
-				for (var i = 0; i < tagArrayKeys.length; ++i) {
-					newCssArray[tagName][tagArrayKeys[i]] = cssArray[tagName][tagArrayKeys[i]];
-				}
-			}
-		}
-		return newCssArray;
 	}
 });
-
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/InlineElements/inline-elements.js	(copie de travail)
@@ -357,7 +357,7 @@
 				classNames = newElement.className.trim().split(" ");
 				for (var i = 0; i < classNames.length; ++i) {
 					if (!allowedClasses.test(classNames[i])) {
-						HTMLArea._removeClass(newElement, classNames[i]);
+						HTMLArea.DOM.removeClass(newElement, classNames[i]);
 					}
 				}
 			}
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/Language/language.js	(copie de travail)
@@ -216,10 +216,10 @@
 	 */
 	toggleLanguageMarks : function (forceLanguageMarks) {
 		var body = this.editor._doc.body;
-		if (!HTMLArea._hasClass(body, 'htmlarea-show-language-marks')) {
-			HTMLArea._addClass(body,'htmlarea-show-language-marks');
+		if (!HTMLArea.DOM.hasClass(body, 'htmlarea-show-language-marks')) {
+			HTMLArea.DOM.addClass(body,'htmlarea-show-language-marks');
 		} else if (!forceLanguageMarks) {
-			HTMLArea._removeClass(body,'htmlarea-show-language-marks');
+			HTMLArea.DOM.removeClass(body,'htmlarea-show-language-marks');
 		}
 	},
 
@@ -408,7 +408,7 @@
 					}
 					break;
 				case 'ShowLanguageMarks':
-					button.setInactive(!HTMLArea._hasClass(this.editor._doc.body, 'htmlarea-show-language-marks'));
+					button.setInactive(!HTMLArea.DOM.hasClass(this.editor._doc.body, 'htmlarea-show-language-marks'));
 					break;
 				case 'Language':
 						// Updating the language drop-down
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/SpellChecker/spell-checker.js	(copie de travail)
@@ -485,13 +485,13 @@
 			element.onclick = null;
 			element.onmouseover = null;
 			element.onmouseout = null;
-			if (!leaveFixed || !HTMLArea._hasClass(element, 'htmlarea-spellcheck-fixed')) {
+			if (!leaveFixed || !HTMLArea.DOM.hasClass(element, 'htmlarea-spellcheck-fixed')) {
 				element.parentNode.insertBefore(element.firstChild, element);
 				element.parentNode.removeChild(element);
 			} else {
-				HTMLArea._removeClass(element, 'htmlarea-spellcheck-error');
-				HTMLArea._removeClass(element, 'htmlarea-spellcheck-same');
-				HTMLArea._removeClass(element, 'htmlarea-spellcheck-current');
+				HTMLArea.DOM.removeClass(element, 'htmlarea-spellcheck-error');
+				HTMLArea.DOM.removeClass(element, 'htmlarea-spellcheck-same');
+				HTMLArea.DOM.removeClass(element, 'htmlarea-spellcheck-current');
 			}
 		}, this);
 			// Cleanup event handlers on links
@@ -521,11 +521,11 @@
 		var id = 0;
 		var self = this;
 		Ext.each(contentWindow.document.getElementsByTagName('span'), function (span) {
-			if (HTMLArea._hasClass(span, 'htmlarea-spellcheck-error')) {
+			if (HTMLArea.DOM.hasClass(span, 'htmlarea-spellcheck-error')) {
 				this.misspelledWords.push(span);
 				span.onclick = function (event) { self.setCurrentWord(this, false); };
-				span.onmouseover = function (event) { HTMLArea._addClass(this, 'htmlarea-spellcheck-hover'); };
-				span.onmouseout = function (event) { HTMLArea._removeClass(this, 'htmlarea-spellcheck-hover'); };
+				span.onmouseover = function (event) { HTMLArea.DOM.addClass(this, 'htmlarea-spellcheck-hover'); };
+				span.onmouseout = function (event) { HTMLArea.DOM.removeClass(this, 'htmlarea-spellcheck-hover'); };
 				span.htmlareaId = id++;
 				span.htmlareaOriginalWord = span.firstChild.data;
 				span.htmlareaFixed = false;
@@ -533,7 +533,7 @@
 					this.allWords[span.htmlareaOriginalWord] = [];
 				}
 				this.allWords[span.htmlareaOriginalWord].push(span);
-			} else if (HTMLArea._hasClass(span, 'htmlarea-spellcheck-fixed')) {
+			} else if (HTMLArea.DOM.hasClass(span, 'htmlarea-spellcheck-fixed')) {
 				this.correctedWords.push(span);
 			}
 		}, this);
@@ -624,18 +624,18 @@
 		}
 			// De-highlight all occurrences of current word
 		if (this.currentElement) {
-			HTMLArea._removeClass(this.currentElement, 'htmlarea-spellcheck-current');
+			HTMLArea.DOM.removeClass(this.currentElement, 'htmlarea-spellcheck-current');
 			Ext.each(this.allWords[this.currentElement.htmlareaOriginalWord], function (word) {
-				HTMLArea._removeClass(word, 'htmlarea-spellcheck-same');
+				HTMLArea.DOM.removeClass(word, 'htmlarea-spellcheck-same');
 			});
 		}
 			// Highlight all occurrences of new current word
 		this.currentElement = element;
-		HTMLArea._addClass(this.currentElement, 'htmlarea-spellcheck-current');
+		HTMLArea.DOM.addClass(this.currentElement, 'htmlarea-spellcheck-current');
 		var occurrences = this.allWords[this.currentElement.htmlareaOriginalWord];
 		Ext.each(occurrences, function (word) {
 			if (word != this.currentElement) {
-				HTMLArea._addClass(word, 'htmlarea-spellcheck-same');
+				HTMLArea.DOM.addClass(word, 'htmlarea-spellcheck-same');
 			}
 		}, this);
 		this.dialog.find('itemId', 'replaceAll')[0].setDisabled(occurrences.length <= 1);
@@ -685,13 +685,13 @@
 	 * Handler invoked when the mouse moves over a misspelled word
 	 */
 	onWordMouseOver: function (event, element) {
-		HTMLArea._addClass(element, 'htmlarea-spellcheck-hover');
+		HTMLArea.DOM.addClass(element, 'htmlarea-spellcheck-hover');
 	},
 	/*
 	 * Handler invoked when the mouse moves out of a misspelled word
 	 */
 	onWordMouseOut: function (event, element) {
-		HTMLArea._removeClass(element, 'htmlarea-spellcheck-hover');
+		HTMLArea.DOM.removeClass(element, 'htmlarea-spellcheck-hover');
 	},
 	/*
 	 * Handler invoked when a suggestion is selected
@@ -711,17 +711,17 @@
 	onRevertClick: function () {
 		this.dialog.find('itemId', 'replacement')[0].setValue(this.currentElement.htmlareaOriginalWord);
 		this.replaceWord(this.currentElement);
-		HTMLArea._removeClass(this.currentElement, 'htmlarea-spellcheck-fixed');
-		HTMLArea._addClass(this.currentElement, 'htmlarea-spellcheck-error');
-		HTMLArea._addClass(this.currentElement, 'htmlarea-spellcheck-current');
+		HTMLArea.DOM.removeClass(this.currentElement, 'htmlarea-spellcheck-fixed');
+		HTMLArea.DOM.addClass(this.currentElement, 'htmlarea-spellcheck-error');
+		HTMLArea.DOM.addClass(this.currentElement, 'htmlarea-spellcheck-current');
 		return false;
 	},
 	/*
 	 * Replace the word contained in the element
 	 */
 	replaceWord: function (element) {
-		HTMLArea._removeClass(element, 'htmlarea-spellcheck-hover');
-		HTMLArea._addClass(element, 'htmlarea-spellcheck-fixed');
+		HTMLArea.DOM.removeClass(element, 'htmlarea-spellcheck-hover');
+		HTMLArea.DOM.addClass(element, 'htmlarea-spellcheck-fixed');
 		element.htmlareaFixed = true;
 		var replacement = this.dialog.find('itemId', 'replacement')[0].getValue();
 		if (element.innerHTML != replacement) {
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TableOperations/table-operations.js	(copie de travail)
@@ -264,11 +264,8 @@
 				}
 				break;
 		}
-		if (this.removedFieldsets.indexOf('style') == -1 && this.getButton('BlockStyle')) {
-			var blockStyle = this.getPluginInstance('BlockStyle');
-			if (blockStyle && blockStyle.cssLoaded) {
-				this.addConfigElement(this.buildStylingFieldsetConfig(element, buttonId), generalTabItems);
-			}
+		if (this.removedFieldsets.indexOf('style') == -1 && this.getPluginInstance('BlockStyle')) {
+			this.addConfigElement(this.buildStylingFieldsetConfig(element, buttonId), generalTabItems);
 		}
 		if (!Ext.isEmpty(generalTabItems)) {
 			tabItems.push({
@@ -525,16 +522,16 @@
 			    case "f_st_float":
 				switch (val) {
 				    case "not set":
-					HTMLArea._removeClass(table, this.floatRight);
-					HTMLArea._removeClass(table, this.floatLeft);
+					HTMLArea.DOM.removeClass(table, this.floatRight);
+					HTMLArea.DOM.removeClass(table, this.floatLeft);
 					break;
 				    case "right":
-					HTMLArea._removeClass(table, this.floatLeft);
-					HTMLArea._addClass(table, this.floatRight);
+					HTMLArea.DOM.removeClass(table, this.floatLeft);
+					HTMLArea.DOM.addClass(table, this.floatRight);
 					break;
 				    case "left":
-					HTMLArea._removeClass(table, this.floatRight);
-					HTMLArea._addClass(table, this.floatLeft);
+					HTMLArea.DOM.removeClass(table, this.floatRight);
+					HTMLArea.DOM.addClass(table, this.floatLeft);
 					break;
 				}
 				break;
@@ -685,7 +682,7 @@
 	 */
 	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'));
+			button.setInactive(!HTMLArea.DOM.hasClass(this.editor._doc.body, 'htmlarea-showtableborders'));
 		}
 	},
 	/*
@@ -1182,10 +1179,10 @@
 	 */
 	toggleBorders : function (forceBorders) {
 		var body = this.editor._doc.body;
-		if (!HTMLArea._hasClass(body, 'htmlarea-showtableborders')) {
-			HTMLArea._addClass(body,'htmlarea-showtableborders');
+		if (!HTMLArea.DOM.hasClass(body, 'htmlarea-showtableborders')) {
+			HTMLArea.DOM.addClass(body,'htmlarea-showtableborders');
 		} else if (!forceBorders) {
-			HTMLArea._removeClass(body,'htmlarea-showtableborders');
+			HTMLArea.DOM.removeClass(body,'htmlarea-showtableborders');
 		}
 	},
 	/*
@@ -1299,20 +1296,20 @@
 			odd = oddClass[type];
 			even = evenClass[type];
 			if (remove) {
-				HTMLArea._removeClass(row, odd);
-				HTMLArea._removeClass(row, even);
+				HTMLArea.DOM.removeClass(row, odd);
+				HTMLArea.DOM.removeClass(row, even);
 				// Check if i is even, and apply classes for both possible results
 			} else if (odd && even) {
 				if ((i % 2) == 0) {
-					if (HTMLArea._hasClass(row, even)) {
-						HTMLArea._removeClass(row, even);
+					if (HTMLArea.DOM.hasClass(row, even)) {
+						HTMLArea.DOM.removeClass(row, even);
 					}
-					HTMLArea._addClass(row, odd);
+					HTMLArea.DOM.addClass(row, odd);
 				} else {
-					if (HTMLArea._hasClass(row, odd)) {
-						HTMLArea._removeClass(row, odd);
+					if (HTMLArea.DOM.hasClass(row, odd)) {
+						HTMLArea.DOM.removeClass(row, odd);
 					}
-					HTMLArea._addClass(row, even);
+					HTMLArea.DOM.addClass(row, even);
 				}
 			}
 		}
@@ -1342,20 +1339,20 @@
 				odd = oddClass[type];
 				even = evenClass[type];
 				if (remove) {
-					if (odd) HTMLArea._removeClass(cell, odd);
-					if (even) HTMLArea._removeClass(cell, even);
+					if (odd) HTMLArea.DOM.removeClass(cell, odd);
+					if (even) HTMLArea.DOM.removeClass(cell, even);
 				} else if (odd && even) {
 						// Check if j+startAt is even, and apply classes for both possible results
 					if ((j % 2) == 0) {
-						if (HTMLArea._hasClass(cell, even)) {
-							HTMLArea._removeClass(cell, even);
+						if (HTMLArea.DOM.hasClass(cell, even)) {
+							HTMLArea.DOM.removeClass(cell, even);
 						}
-						HTMLArea._addClass(cell, odd);
+						HTMLArea.DOM.addClass(cell, odd);
 					} else{
-						if (HTMLArea._hasClass(cell, odd)) {
-							HTMLArea._removeClass(cell, odd);
+						if (HTMLArea.DOM.hasClass(cell, odd)) {
+							HTMLArea.DOM.removeClass(cell, odd);
 						}
-						HTMLArea._addClass(cell, even);
+						HTMLArea.DOM.addClass(cell, even);
 					}
 				}
 			}
@@ -1422,23 +1419,23 @@
 			lastRowClassName = rowLastClass[type];
 			if (remove) {
 				if (baseClassName) {
-					HTMLArea._removeClass(row, rowClassName);
+					HTMLArea.DOM.removeClass(row, rowClassName);
 				}
 				if (lastRowClassName && i == n-1) {
-					HTMLArea._removeClass(row, lastRowClassName);
+					HTMLArea.DOM.removeClass(row, lastRowClassName);
 				}
 			} else {
 				if (baseClassName) {
-					if (HTMLArea._hasClass(row, baseClassName, true)) {
-						HTMLArea._removeClass(row, baseClassName, true);
+					if (HTMLArea.DOM.hasClass(row, baseClassName, true)) {
+						HTMLArea.DOM.removeClass(row, baseClassName, true);
 					}
-					HTMLArea._addClass(row, rowClassName);
+					HTMLArea.DOM.addClass(row, rowClassName);
 				}
 				if (lastRowClassName) {
 					if (i == n-1) {
-						HTMLArea._addClass(row, lastRowClassName);
-					} else if (HTMLArea._hasClass(row, lastRowClassName)) {
-						HTMLArea._removeClass(row, lastRowClassName);
+						HTMLArea.DOM.addClass(row, lastRowClassName);
+					} else if (HTMLArea.DOM.hasClass(row, lastRowClassName)) {
+						HTMLArea.DOM.removeClass(row, lastRowClassName);
 					}
 				}
 			}
@@ -1471,23 +1468,23 @@
 				lastColumnClassName = columnLastClass[type];
 				if (remove) {
 					if (baseClassName) {
-						HTMLArea._removeClass(cell, columnClassName);
+						HTMLArea.DOM.removeClass(cell, columnClassName);
 					}
 					if (lastColumnClassName && j == n-1) {
-							HTMLArea._removeClass(cell, lastColumnClassName);
+							HTMLArea.DOM.removeClass(cell, lastColumnClassName);
 					}
 				} else {
 					if (baseClassName) {
-						if (HTMLArea._hasClass(cell, baseClassName, true)) {
-							HTMLArea._removeClass(cell, baseClassName, true);
+						if (HTMLArea.DOM.hasClass(cell, baseClassName, true)) {
+							HTMLArea.DOM.removeClass(cell, baseClassName, true);
 						}
-						HTMLArea._addClass(cell, columnClassName);
+						HTMLArea.DOM.addClass(cell, columnClassName);
 					}
 					if (lastColumnClassName) {
 						if (j == n-1) {
-							HTMLArea._addClass(cell, lastColumnClassName);
-						} else if (HTMLArea._hasClass(cell, lastColumnClassName)) {
-							HTMLArea._removeClass(cell, lastColumnClassName);
+							HTMLArea.DOM.addClass(cell, lastColumnClassName);
+						} else if (HTMLArea.DOM.hasClass(cell, lastColumnClassName)) {
+							HTMLArea.DOM.removeClass(cell, lastColumnClassName);
 						}
 					}
 				}
@@ -1521,7 +1518,7 @@
 			} else {
 				var firstRow = thead.rows[0];
 			}
-			HTMLArea._removeClass(firstRow, this.useHeaderClass);
+			HTMLArea.DOM.removeClass(firstRow, this.useHeaderClass);
 		} else {
 			if (thead) {
 				var rows = thead.rows;
@@ -1540,10 +1537,10 @@
 		}
 		if (headers == "both") {
 			var firstRow = tbody.rows[0];
-			HTMLArea._addClass(firstRow, this.useHeaderClass);
+			HTMLArea.DOM.addClass(firstRow, this.useHeaderClass);
 		} else if (headers != "top") {
 			var firstRow = tbody.rows[0];
-			HTMLArea._removeClass(firstRow, this.useHeaderClass);
+			HTMLArea.DOM.removeClass(firstRow, this.useHeaderClass);
 			this.remapRowCells(firstRow, "td");
 		}
 		if (headers == "top" || headers == "both") {
@@ -1613,7 +1610,7 @@
 				var classNames = newCell.className.trim().split(" ");
 				for (var i = classNames.length; --i >= 0;) {
 					if (!allowedClasses.test(classNames[i])) {
-						HTMLArea._removeClass(newCell, classNames[i]);
+						HTMLArea.DOM.removeClass(newCell, classNames[i]);
 					}
 				}
 			}
@@ -1818,7 +1815,7 @@
 				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)) {
+					if (HTMLArea.DOM.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';
@@ -1928,12 +1925,12 @@
 	 */
 	setStyleOptions: function (dropDown, element, nodeName, defaultClass) {
 		var blockStyle = this.getPluginInstance('BlockStyle');
-		if (dropDown && blockStyle && blockStyle.cssLoaded) {
+		if (dropDown && blockStyle) {
 			if (defaultClass) {
 				var classNames = new Array();
 				classNames.push(defaultClass);
 			} else {
-				var classNames = blockStyle.getClassNames(element);
+				var classNames = HTMLArea.DOM.getClassNames(element);
 			}
 			blockStyle.buildDropDownOptions(dropDown, nodeName);
 			blockStyle.setSelectedOption(dropDown, classNames, 'noUnknown', defaultClass);
Index: typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js
===================================================================
--- typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js	(r�vision 9247)
+++ typo3/sysext/rtehtmlarea/htmlarea/plugins/TextStyle/text-style.js	(copie de travail)
@@ -36,20 +36,14 @@
 	/*
 	 * Let the base class do some initialization work
 	 */
-	constructor : function(editor, pluginName) {
+	constructor: function (editor, pluginName) {
 		this.base(editor, pluginName);
 	},
-	
 	/*
 	 * This function gets called by the class constructor
 	 */
-	configurePlugin : function (editor) {
-		
-		this.cssLoaded = false;
-		this.cssTimeout = null;
-		this.cssParseCount = 0;
-		this.cssArray = new Object();
-		
+	configurePlugin: function (editor) {
+		this.cssArray = {};
 		this.classesUrl = this.editorConfiguration.classesUrl;
 		this.pageTSconfiguration = this.editorConfiguration.buttons.textstyle;
 		this.tags = this.pageTSconfiguration.tags;
@@ -94,21 +88,19 @@
 		if (Ext.isIE) {
 			this.addAllowedAttribute("className");
 		}
-		
 		/*
 		 * Registering plugin "About" information
 		 */
 		var pluginInformation = {
-			version		: "1.1",
-			developer	: "Stanislas Rolland",
-			developerUrl	: "http://www.sjbr.ca/",
-			copyrightOwner	: "Stanislas Rolland",
-			sponsor		: this.localize("Technische Universitat Ilmenau"),
-			sponsorUrl	: "http://www.tu-ilmenau.de/",
-			license		: "GPL"
+			version		: '2.0',
+			developer	: 'Stanislas Rolland',
+			developerUrl	: 'http://www.sjbr.ca/',
+			copyrightOwner	: 'Stanislas Rolland',
+			sponsor		: this.localize('Technische Universitat Ilmenau'),
+			sponsorUrl	: 'http://www.tu-ilmenau.de/',
+			license		: 'GPL'
 		};
 		this.registerPluginInformation(pluginInformation);
-		
 		/* 
 		 * Registering the dropdown list
 		 */
@@ -139,10 +131,9 @@
 		return true;
 	},
 	
-	isInlineElement : function (el) {
+	isInlineElement: function (el) {
 		return el && (el.nodeType === 1) && this.REInlineTags.test(el.nodeName.toLowerCase());
 	},
-
 	/*
 	 * This function adds an attribute to the array of allowed attributes on inline elements
 	 *
@@ -150,14 +141,13 @@
 	 *
 	 * @return	void
 	 */
-	addAllowedAttribute : function (attribute) {
+	addAllowedAttribute: function (attribute) {
 		this.allowedAttributes.push(attribute);
 	},
-
 	/*
 	 * This function gets called when some style in the drop-down list applies it to the highlighted textt
 	 */
-	onChange : function (editor, combo, record, index) {
+	onChange: function (editor, combo, record, index) {
 		var className = combo.getValue();
 		var classNames = null;
 		var fullNodeSelected = false;
@@ -196,7 +186,7 @@
 			if (className !== "none") {
 					// Add span element with class attribute
 				var newElement = editor._doc.createElement("span");
-				HTMLArea._addClass(newElement, className);
+				HTMLArea.DOM.addClass(newElement, className);
 				editor.wrapWithInlineElement(newElement, selection, range);
 				if (!Ext.isIE) {
 					range.detach();
@@ -207,10 +197,10 @@
 			if (parent && !HTMLArea.isBlockElement(parent)) {
 				if (className === "none" && parent.className && /\S/.test(parent.className)) {
 					classNames = parent.className.trim().split(" ");
-					HTMLArea._removeClass(parent, classNames[classNames.length-1]);
+					HTMLArea.DOM.removeClass(parent, classNames[classNames.length-1]);
 				}
 				if (className !== "none") {
-					HTMLArea._addClass(parent, className);
+					HTMLArea.DOM.addClass(parent, className);
 				}
 					// Remove the span tag if it has no more attribute
 				if ((parent.nodeName.toLowerCase() === "span") && !HTMLArea.hasAllowedAttributes(parent, this.allowedAttributes)) {
@@ -219,211 +209,56 @@
 			}
 		}
 	},
-
 	/*
 	 * 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");
+		this.editor.iframe.mon(this.editor, 'HTMLAreaEventModeChange', this.onModeChange, this);
+			// Create CSS Parser object
+		this.textStyles = new HTMLArea.CSS.Parser({
+			prefixLabelWithClassName: this.prefixLabelWithClassName,
+			postfixLabelWithClassName: this.postfixLabelWithClassName,
+			showTagFreeClasses: this.showTagFreeClasses,
+			tags: this.tags,
+			editor: this.editor
+		});
+			// Monitor css parsing being completed
+		this.editor.iframe.mon(this.textStyles, 'HTMLAreaEventCssParsingComplete', this.onCssParsingComplete, this);
+		this.textStyles.initiateParsing();
 	},
-	
 	/*
-	 * 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
+	 * This handler gets called when parsing of css classes is completed
 	 */
-	generate: function (editor, dropDownId) {
-		if (this.cssLoaded) {
-			this.updateToolbar(dropDownId);
-		} else {
-			if (this.cssTimeout) {
-				window.clearTimeout(this.cssTimeout);
-				this.cssTimeout = null;
-			}
-			if (this.classesUrl && (typeof(HTMLArea.classesLabels) === 'undefined')) {
-				this.getJavascriptFile(this.classesUrl, function (options, success, response) {
-					if (success) {
-						try {
-							if (typeof(HTMLArea.classesLabels) === 'undefined') {
-								eval(response.responseText);
-								this.appendToLog('generate', 'Javascript file successfully evaluated: ' + this.classesUrl);
-							}
-						} catch(e) {
-							this.appendToLog('generate', 'Error evaluating contents of Javascript file: ' + this.classesUrl);
-						}
-					}
-					this.buildCssArray(this.editor, dropDownId);
-				});
-			} else {
-				this.buildCssArray(this.editor, dropDownId);
-			}
+	onCssParsingComplete: function () {
+		if (this.textStyles.isReady) {
+			this.cssArray = this.textStyles.getClasses();
 		}
-	},
-	
-	buildCssArray : function(editor, dropDownId) {
-		this.cssArray = this.parseStyleSheet();
-		if (!this.cssLoaded && (this.cssParseCount < 17)) {
-			this.cssTimeout = this.buildCssArray.defer(200, this, [editor, dropDownId]);
-			this.cssParseCount++;
-		} else {
-			this.cssTimeout = null;
-			this.cssLoaded = true;
-			this.cssArray = this.sortCssArray(this.cssArray);
-			this.updateToolbar(dropDownId);
+		if (this.getEditorMode() === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateToolbar('TextStyle');
 		}
 	},
-	
-	parseStyleSheet : function() {
-		var iframe = this.editor._iframe.contentWindow ? this.editor._iframe.contentWindow.document : this.editor._iframe.contentDocument;
-		var newCssArray = new Object();
-		this.cssLoaded = true;
-		for (var i = 0; i < iframe.styleSheets.length; i++) {
-			if (!Ext.isIE) {
-				try {
-					newCssArray = this.parseCssRule(iframe.styleSheets[i].cssRules, newCssArray);
-				} catch(e) {
-					this.cssLoaded = false;
-				}
-			} else {
-				try{
-						// @import StyleSheets (IE)
-					if (iframe.styleSheets[i].imports) {
-						newCssArray = this.parseCssIEImport(iframe.styleSheets[i].imports, newCssArray);
-					}
-					if (iframe.styleSheets[i].rules) {
-						newCssArray = this.parseCssRule(iframe.styleSheets[i].rules, newCssArray);
-					}
-				} catch(e) {
-					this.cssLoaded = false;
-				}
-			}
+	/*
+	 * This handler gets called when the toolbar is being updated
+	 */
+	onUpdateToolbar: function (button, mode, selectionEmpty, ancestors) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateToolbar(button.itemId);
 		}
-		return newCssArray;
 	},
-	
-	parseCssIEImport : function(cssIEImport, cssArray) {
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		for (var i=0; i < cssIEImport.length; i++) {
-			if (cssIEImport[i].imports) {
-				newCssArray = this.parseCssIEImport(cssIEImport[i].imports, newCssArray);
-			}
-			if (cssIEImport[i].rules) {
-				newCssArray = this.parseCssRule(cssIEImport[i].rules, newCssArray);
-			}
-		}
-		return newCssArray;
-	},
-	
-	parseCssRule : function(cssRules, cssArray) {
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		for (var rule = 0; rule < cssRules.length; rule++) {
-				// StyleRule
-			if (cssRules[rule].selectorText) {
-				newCssArray = this.parseSelectorText(cssRules[rule].selectorText, newCssArray);
-			} else {
-					// ImportRule (Mozilla)
-				if (cssRules[rule].styleSheet) {
-					newCssArray = this.parseCssRule(cssRules[rule].styleSheet.cssRules, newCssArray);
-				}
-					// MediaRule (Mozilla)
-				if (cssRules[rule].cssRules) {
-					newCssArray = this.parseCssRule(cssRules[rule].cssRules, newCssArray);
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
-	parseSelectorText : function(selectorText, cssArray) {
-		var cssElements = new Array();
-		var cssElement = new Array();
-		var tagName, className;
-		var newCssArray = new Object();
-		newCssArray = cssArray;
-		if (selectorText.search(/:+/) == -1) {
-				// split equal Styles (Mozilla-specific) e.q. head, body {border:0px}
-				// for ie not relevant. returns allways one element
-			cssElements = selectorText.split(",");
-			for (var k = 0; k < cssElements.length; k++) {
-					// Match ALL classes (<element name (optional)>.<class name>) in selector rule
-				var s = cssElements[k],
-					pattern = /(\S*)\.(\S+)/,
-					index;
-				while ((index = s.search(pattern)) > -1) {
-					var match = pattern.exec(s.substring(index));
-					s = s.substring(index+match[0].length);
-
-					tagName = (match[1] && (match[1] != '*')) ? match[1].toLowerCase().trim() : "all";
-					className = match[2];
-
-					if (className && !HTMLArea.reservedClassNames.test(className)) {
-						if (((tagName != "all") && (!this.tags || !this.tags[tagName]))
-							|| ((tagName == "all") && (!this.tags || !this.tags[tagName]) && this.showTagFreeClasses)
-							|| (this.tags && this.tags[tagName] && this.tags[tagName].allowedClasses && this.tags[tagName].allowedClasses.test(className))) {
-							if (!newCssArray[tagName]) {
-								newCssArray[tagName] = new Object();
-							}
-							if (className) {
-								cssName = className;
-								if (HTMLArea.classesLabels && HTMLArea.classesLabels[className]) {
-									cssName = this.prefixLabelWithClassName ? (className + " - " + HTMLArea.classesLabels[className]) : HTMLArea.classesLabels[className];
-									cssName = this.postfixLabelWithClassName ? (cssName + " - " + className) : cssName;
-								}
-							} else {
-								className = 'none';
-								cssName = this.localize("Element style");
-							}
-							newCssArray[tagName][className] = cssName;
-						}
-					}
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
-	sortCssArray : function(cssArray) {
-		var newCssArray = new Object();
-		for (var tagName in cssArray) {
-			if (cssArray.hasOwnProperty(tagName)) {
-				newCssArray[tagName] = new Object();
-				var tagArrayKeys = new Array();
-				for (var cssClass in cssArray[tagName]) {
-					if (cssArray[tagName].hasOwnProperty(cssClass)) {
-						tagArrayKeys.push(cssClass);
-					}
-				}
-				function compare(a, b) {
-					x = cssArray[tagName][a];
-					y = cssArray[tagName][b];
-					return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-				}
-				tagArrayKeys = tagArrayKeys.sort(compare);
-				for (var i = 0; i < tagArrayKeys.length; ++i) {
-					newCssArray[tagName][tagArrayKeys[i]] = cssArray[tagName][tagArrayKeys[i]];
-				}
-			}
-		}
-		return newCssArray;
-	},
-	
 	/*
-	 * This function gets called when the toolbar is being updated
+	 * This handler gets called when the editor has changed its mode to "wysiwyg"
 	 */
-	onUpdateToolbar: function(button, mode, selectionEmpty, ancestors) {
-		if (mode === "wysiwyg" && this.editor.isEditable()) {
-			this.generate(this.editor, button.itemId);
+	onModeChange: function (mode) {
+		if (mode === 'wysiwyg' && this.editor.isEditable()) {
+			this.updateToolbar('TextStyle');
 		}
 	},
-	
 	/*
 	* This function gets called when the drop-down list needs to be refreshed
 	*/
-	updateToolbar : function(dropDownId) {
+	updateToolbar: function(dropDownId) {
 		var editor = this.editor;
 		if (this.getEditorMode() === "wysiwyg" && this.editor.isEditable()) {
 			var tagName = false, classNames = Array(), fullNodeSelected = false;
@@ -475,11 +310,10 @@
 			}
 		}
 	},
-
 	/*
 	 * This function reinitializes the options of the dropdown
 	 */
-	initializeDropDown : function (dropDown) {
+	initializeDropDown: function (dropDown) {
 		var store = dropDown.getStore();
 		store.removeAll(false);
 		store.insert(0, new store.recordType({
@@ -488,11 +322,10 @@
 		}));
 		dropDown.setValue('none');
 	},
-
 	/*
 	 * This function sets the selected option of the dropDown box
 	 */
-	setSelectedOption : function (dropDown, classNames, noUnknown, defaultClass) {
+	setSelectedOption: function (dropDown, classNames, noUnknown, defaultClass) {
 		var store = dropDown.getStore();
 		var index = store.findExact('value', classNames[classNames.length-1]);
 		if (index != -1) {
@@ -519,95 +352,36 @@
 			return true;
 		});
 	},
-
-	updateValue : function(dropDownId, tagName, classNames, selectionEmpty, fullNodeSelected, disabled) {
+	/*
+	 * This function updates the current value of the dropdown list
+	 */
+	updateValue: function (dropDownId, nodeName, classNames, selectionEmpty, fullNodeSelected, disabled) {
 		var editor = this.editor;
 		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];
-							}
-						}
+			if (this.textStyles.isReady) {
+				var allowedClasses = {};
+				if (this.REInlineTags.test(nodeName)) {
+					if (Ext.isDefined(this.cssArray[nodeName])) {
+						allowedClasses = this.cssArray[nodeName];
+					} else if (this.showTagFreeClasses && Ext.isDefined(this.cssArray['all'])) {
+						allowedClasses = this.cssArray['all'];
 					}
 				}
-					// 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];
-							}
-						}
-					}
-					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') {
-							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
-							}));
-						}
-					}
-				}
-				if (classNames.length && (selectionEmpty || fullNodeSelected)) {
-					this.setSelectedOption(dropDown, classNames);
-				}
+				Ext.iterate(allowedClasses, function (cssClass, value) {
+					store.add(new store.recordType({
+						text: value,
+						value: cssClass,
+						style: (!this.editor.config.disablePCexamples && HTMLArea.classesValues && HTMLArea.classesValues[cssClass] && !HTMLArea.classesNoShow[cssClass]) ? HTMLArea.classesValues[cssClass] : null
+					}));
+				}, this);
 			}
+			if (classNames.length && (selectionEmpty || fullNodeSelected)) {
+				this.setSelectedOption(dropDown, classNames);
+			}
 			dropDown.setDisabled(!(store.getCount()>1) || disabled);
 		}
-	},
-	/*
-	 * This function gets called when the editor has changed its mode to "wysiwyg"
-	 */
-	onModeChange: function(mode) {
-		if (mode === "wysiwyg" && this.editor.isEditable()) {
-			this.generate(this.editor, "TextStyle");
-		}
 	}
 });
-
