Index: /FCKeditor/trunk/_samples/html/sample08.html
===================================================================
--- /FCKeditor/trunk/_samples/html/sample08.html	(revision 301)
+++ /FCKeditor/trunk/_samples/html/sample08.html	(revision 302)
@@ -64,5 +64,5 @@
 
 	// Set the editor contents (replace the actual one).
-	oEditor.SetHTML( 'This is the <b>new content</b> I want in the editor.' ) ;
+	oEditor.SetData( 'This is the <b>new content</b> I want in the editor.' ) ;
 }
 
Index: /FCKeditor/trunk/_samples/html/sample13.html
===================================================================
--- /FCKeditor/trunk/_samples/html/sample13.html	(revision 301)
+++ /FCKeditor/trunk/_samples/html/sample13.html	(revision 302)
@@ -53,5 +53,5 @@
 		{
 			// Set the current text in the textarea to the editor.
-			oEditor.SetHTML( document.getElementById('_DataTextarea').value ) ;
+			oEditor.SetData( document.getElementById('_DataTextarea').value ) ;
 		}
 
Index: /FCKeditor/trunk/_test/automated/tests/fckdataprocessor.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/fckdataprocessor.html	(revision 302)
+++ /FCKeditor/trunk/_test/automated/tests/fckdataprocessor.html	(revision 302)
@@ -0,0 +1,173 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>FCKDataProcessor - Tests for JsUnit</title>
+	<script src="../../../editor/_source/fckscriptloader.js" type="text/javascript"></script>
+	<script type="text/javascript" src="tests.js"></script>
+	<script type="text/javascript" src="../_jsunit/app/jsUnitCore.js"></script>
+	<script type="text/javascript">
+
+var FCK = 
+{
+	IsDirty : function() { return true ; }
+}
+
+FCKScriptLoader.Load( 'FCKDataProcessor' ) ;
+
+	</script>
+	<script src="../../../fckconfig.js" type="text/javascript"></script>
+	<script type="text/javascript">
+
+function test_ConvertToHtml()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<html dir="ltr"><head><title></title></head><body>This is some <strong>sample text</strong>.</body></html>',
+		dataProcessor.ConvertToHtml( 'This is some <strong>sample text</strong>.' ) ) ;
+}
+
+function test_ConvertToHtml_Empty()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<html dir="ltr"><head><title></title></head><body></body></html>',
+		dataProcessor.ConvertToHtml( '' ) ) ;
+}
+
+function test_ConvertToHtml_Full()
+{
+	FCKConfig.FullPage = true ;
+
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<html dir="rtl"><head><title>My Test</title><style></style></head><body class="Test">This is some <strong>sample text</strong>.</body></html>',
+		dataProcessor.ConvertToHtml( '<html dir="rtl"><head><title>My Test</title><style></style></head><body class="Test">This is some <strong>sample text</strong>.</body></html>' ) ) ;
+
+	// Reset the config for other tests.
+	FCKConfig.FullPage = false ;
+}
+
+function test_ConvertToHtml_Full_Incomplete()
+{
+	FCKConfig.FullPage = true ;
+
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<html dir="ltr"><head><title></title></head><body>This is some <strong>sample text</strong>.</body></html>',
+		dataProcessor.ConvertToHtml( 'This is some <strong>sample text</strong>.' ) ) ;
+
+	// Reset the config for other tests.
+	FCKConfig.FullPage = false ;
+}
+
+function test_ConvertToHtml_Full_Empty()
+{
+	FCKConfig.FullPage = true ;
+
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<html dir="ltr"><head><title></title></head><body></body></html>',
+		dataProcessor.ConvertToHtml( '' ) ) ;
+
+	// Reset the config for other tests.
+	FCKConfig.FullPage = false ;
+}
+
+function test_ConvertToHtml_Settings()
+{
+	FCKConfig.ContentLangDirection = 'rtl' ;
+	FCKConfig.DocType = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' ;
+	FCKConfig.BodyId = 'TestId' ;
+	FCKConfig.BodyClass = 'TestClass'
+
+	var dataProcessor = new FCKDataProcessor() ;
+
+	if ( navigator.userAgent.indexOf( 'MSIE' ) > -1 )	// IE
+	{
+		assertEquals(
+			'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' +
+			'<html dir="rtl" style="overflow-y: scroll"><head><title></title></head><body id="TestId" class="TestClass">This is some <strong>sample text</strong>.</body></html>',
+			dataProcessor.ConvertToHtml( 'This is some <strong>sample text</strong>.' ) ) ;
+	}
+	else
+	{
+		assertEquals(
+			'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' +
+			'<html dir="rtl"><head><title></title></head><body id="TestId" class="TestClass">This is some <strong>sample text</strong>.</body></html>',
+			dataProcessor.ConvertToHtml( 'This is some <strong>sample text</strong>.' ) ) ;
+	}
+	// Reset the config for other tests.
+	FCKConfig.ContentLangDirection = 'ltr' ;
+	FCKConfig.DocType = '' ;
+	FCKConfig.BodyId = '' ;
+	FCKConfig.BodyClass = ''
+}
+
+function test_ConvertToDataFormat_Exclude_NoFormat()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<p>This is a <strong>test</strong>.</p><p>Another paragraph.</p>',
+		dataProcessor.ConvertToDataFormat( document.getElementById('xDiv1'), true ) ) ;
+}
+
+function test_ConvertToDataFormat_NoExclude_NoFormat()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<div id="xDiv1"><p>This is a <strong>test</strong>.</p><p>Another paragraph.</p></div>',
+		dataProcessor.ConvertToDataFormat( document.getElementById('xDiv1'), false ) ) ;
+}
+
+function test_ConvertToDataFormat_NoExclude_Format()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'<div id="xDiv1">\n<p>This is a <strong>test</strong>.</p>\n<p>Another paragraph.</p>\n</div>',
+		dataProcessor.ConvertToDataFormat( document.getElementById('xDiv1'), false, false, true ) ) ;
+}
+
+function test_ConvertToDataFormat_IgnoreEmpty()
+{
+	var dataProcessor = new FCKDataProcessor() ;
+
+	assertEquals(
+		'',
+		dataProcessor.ConvertToDataFormat( document.getElementById('xDiv2'), true, true ) ) ;
+}
+
+	</script>
+</head>
+<body>
+	<div id="xDiv1"><p>This is a <strong>test</strong>.</p><p>Another paragraph.</p></div>
+	<div id="xDiv2"><p>&nbsp;</p></div>
+</body>
+</html>
Index: /FCKeditor/trunk/_test/automated/tests/suite.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/suite.html	(revision 301)
+++ /FCKeditor/trunk/_test/automated/tests/suite.html	(revision 302)
@@ -33,7 +33,8 @@
 	var suite = new top.jsUnitTestSuite() ;
 
+	suite.addTestPage( '../tests/fckdataprocessor.html' ) ;
+	suite.addTestPage( '../tests/fckdomrange.html' ) ;
 	suite.addTestPage( '../tests/fcktools.html' ) ;
 	suite.addTestPage( '../tests/fckw3crange.html' ) ;
-	suite.addTestPage( '../tests/fckdomrange.html' ) ;
 
 	return suite ;
Index: /FCKeditor/trunk/_whatsnew.html
===================================================================
--- /FCKeditor/trunk/_whatsnew.html	(revision 301)
+++ /FCKeditor/trunk/_whatsnew.html	(revision 302)
@@ -35,6 +35,7 @@
 		New Features and Improvements:</p>
 	<ul>
-		<li>It is now possible to set the default target when creating links, with the new "<strong>DefaultLinkTarget</strong>"
-			setting.</li>
+		<li>The editor now uses the <strong>Data Processor</strong> technology, which makes
+			it possible to handle different input formats. A sample of it may be found at "editor/plugins/bbcode/_sample",
+			that shows some simple BBCode support.</li>
 	</ul>
 	<p>
Index: /FCKeditor/trunk/editor/_source/classes/fckdataprocessor.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdataprocessor.js	(revision 302)
+++ /FCKeditor/trunk/editor/_source/classes/fckdataprocessor.js	(revision 302)
@@ -0,0 +1,127 @@
+﻿/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * The Data Processor is responsible for transforming the input and output data
+ * in the editor. For more info:
+ * http://dev.fckeditor.net/wiki/Components/DataProcessor
+ *
+ * The default implementation offers the base XHTML compatibility features of
+ * FCKeditor. Further Data Processors may be implemented for other purposes.
+ *
+ */
+
+var FCKDataProcessor = function()
+{}
+
+FCKDataProcessor.prototype =
+{
+	/*
+	 * Returns a string representing the HTML format of "data". The returned
+	 * value will be loaded in the editor.
+	 * The HTML must be from <html> to </html>, including <head>, <body> and
+	 * eventually the DOCTYPE.
+	 * Note: HTML comments may already be part of the data because of the
+	 * pre-processing made with ProtectedSource.
+	 *     @param {String} data The data to be converted in the
+	 *            DataProcessor specific format.
+	 */
+	ConvertToHtml : function( data )
+	{
+		// The default data processor must handle two different cases depending
+		// on the FullPage setting. Custom Data Processors will not be
+		// compatible with FullPage, much probably.
+		if ( FCKConfig.FullPage )
+		{
+			// Save the DOCTYPE.
+			FCK.DocTypeDeclaration = data.match( FCKRegexLib.DocTypeTag ) ;
+
+			// Check if the <body> tag is available.
+			if ( !FCKRegexLib.HasBodyTag.test( data ) )
+				data = '<body>' + data + '</body>' ;
+
+			// Check if the <html> tag is available.
+			if ( !FCKRegexLib.HtmlOpener.test( data ) )
+				data = '<html dir="' + FCKConfig.ContentLangDirection + '">' + data + '</html>' ;
+
+			// Check if the <head> tag is available.
+			if ( !FCKRegexLib.HeadOpener.test( data ) )
+				data = data.replace( FCKRegexLib.HtmlOpener, '$&<head><title></title></head>' ) ;
+
+			return data ;
+		}
+		else
+		{
+			var html =
+				FCKConfig.DocType +
+				'<html dir="' + FCKConfig.ContentLangDirection + '"' ;
+
+			// On IE, if you are using a DOCTYPE different of HTML 4 (like
+			// XHTML), you must force the vertical scroll to show, otherwise
+			// the horizontal one may appear when the page needs vertical scrolling.
+			// TODO : Check it with IE7 and make it IE6- if it is the case.
+			if ( FCKBrowserInfo.IsIE && FCKConfig.DocType.length > 0 && !FCKRegexLib.Html4DocType.test( FCKConfig.DocType ) )
+				html += ' style="overflow-y: scroll"' ;
+
+			html += '><head><title></title></head><body' ;
+
+			// Add id and class to the body.
+			if ( FCKConfig.BodyId.length > 0 )
+				html += ' id="' + FCKConfig.BodyId + '"' ;
+			if ( FCKConfig.BodyClass.length > 0 )
+				html += ' class="' + FCKConfig.BodyClass + '"' ;
+
+			html +=
+				'>' +
+				data +
+				'</body></html>' ;
+
+			return html ;
+		}
+	},
+
+	/*
+	 * Converts a DOM (sub-)tree to a string in the data format.
+	 *     @param {Object} rootNode The node that contains the DOM tree to be
+	 *            converted to the data format.
+	 *     @param {Boolean} excludeRoot Indicates that the root node must not
+	 *            be included in the conversion, only its children.
+	 *     @param {Boolean} format Indicates that the data must be formatted
+	 *            for human reading. Not all Data Processors may provide it.
+	 */
+	ConvertToDataFormat : function( rootNode, excludeRoot, ignoreIfEmptyParagraph, format )
+	{
+		var data = FCKXHtml.GetXHTML( rootNode, !excludeRoot, format ) ;
+
+		if ( ignoreIfEmptyParagraph && FCKRegexLib.EmptyOutParagraph.test( data ) )
+			return '' ;
+
+		return data ;
+	},
+
+	/*
+	 * Makes any necessary changes to a piece of HTML for insertion in the
+	 * editor selection position.
+	 *     @param {String} html The HTML to be fixed.
+	 */
+	FixHtml : function( html )
+	{
+		return html ;
+	}
+} ;
Index: /FCKeditor/trunk/editor/_source/classes/fckeditingarea.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckeditingarea.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/classes/fckeditingarea.js	(revision 302)
@@ -66,8 +66,4 @@
 		else if ( !secondCall )
 		{
-			// If nothing in the body, place a BOGUS tag so the cursor will appear.
-			if ( FCKBrowserInfo.IsGecko )
-				html = html.replace( /(<body[^>]*>)\s*(<\/body>)/i, '$1' + GECKO_BOGUS + '$2' ) ;
-
 			// Gecko moves some tags out of the body to the head, so we must use
 			// innerHTML to set the body contents (SF BUG 1526154).
@@ -83,5 +79,12 @@
 					oMatch[3] ;					// This is the HTML from the </body> tag, inclusive.
 
-				this._BodyHTML = oMatch[2] ;	// This is the BODY tag contents.
+				var sBody = oMatch[2].Trim() ;	// This is the BODY tag contents.
+
+				// If nothing in the body, place a BOGUS tag so the cursor will appear.
+				if ( FCKBrowserInfo.IsGecko && ( sBody.length == 0 || FCKRegexLib.EmptyParagraph.test( sBody ) ) )
+					sBody = GECKO_BOGUS ;
+
+				this._BodyHTML = sBody ;
+
 			}
 			else
Index: /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/commandclasses/fck_othercommands.js	(revision 302)
@@ -186,5 +186,5 @@
 {
 	FCKUndo.SaveUndoStep() ;
-	FCK.SetHTML( '' ) ;
+	FCK.SetData( '' ) ;
 	FCKUndo.Typing = true ;
 }
Index: /FCKeditor/trunk/editor/_source/fckscriptloader.js
===================================================================
--- /FCKeditor/trunk/editor/_source/fckscriptloader.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/fckscriptloader.js	(revision 302)
@@ -92,17 +92,25 @@
 FCKScriptLoader.AddScript( 'FCKConstants' ) ;
 FCKScriptLoader.AddScript( 'FCKJSCoreExtensions' ) ;
+
+FCKScriptLoader.AddScript( 'FCKDataProcessor'	, 'classes/'	, ['FCKConfig','FCKBrowserInfo','FCKRegexLib','FCKXHtml'] ) ;
+FCKScriptLoader.AddScript( 'FCKDocumentFragment', 'classes/'	, ['FCKDomTools'], FCK_SPECIFIC ) ;
+FCKScriptLoader.AddScript( 'FCKDomRange'		, 'classes/'	, ['FCKBrowserInfo','FCKJSCoreExtensions','FCKW3CRange','FCKElementPath','FCKDomTools','FCKTools','FCKDocumentFragment'], FCK_GENERIC_SPECIFIC ) ;
+FCKScriptLoader.AddScript( 'FCKElementPath'		, 'classes/'	, ['FCKListsLib'], FCK_GENERIC ) ;
+FCKScriptLoader.AddScript( 'FCKEnterKey'		, 'classes/'	, ['FCKDomRange','FCKDomTools','FCKTools','FCKKeystrokeHandler','FCKListHandler'], FCK_GENERIC ) ;
 FCKScriptLoader.AddScript( 'FCKImagePreloader'	, 'classes/' ) ;
+FCKScriptLoader.AddScript( 'FCKKeystrokeHandler', 'classes/'	, ['FCKConstants','FCKBrowserInfo','FCKTools'], FCK_GENERIC ) ;
+FCKScriptLoader.AddScript( 'FCKW3CRange'		, 'classes/'	, ['FCKDomTools','FCKTools','FCKDocumentFragment'], FCK_GENERIC ) ;
+
 FCKScriptLoader.AddScript( 'FCKBrowserInfo'		, 'internals/'	, ['FCKJSCoreExtensions'] ) ;
-FCKScriptLoader.AddScript( 'FCKConfig'			, 'internals/' ) ;
-FCKScriptLoader.AddScript( 'FCKListsLib'		, 'internals/' ) ;
+FCKScriptLoader.AddScript( 'FCKCodeFormatter'	, 'internals/' ) ;
+FCKScriptLoader.AddScript( 'FCKConfig'			, 'internals/'	, ['FCKConstants'] ) ;
 FCKScriptLoader.AddScript( 'FCKDebug'			, 'internals/'	, ['FCKConfig'] ) ;
 FCKScriptLoader.AddScript( 'FCKDomTools'		, 'internals/'	, ['FCKJSCoreExtensions'], FCK_GENERIC ) ;
+FCKScriptLoader.AddScript( 'FCKListsLib'		, 'internals/' ) ;
+FCKScriptLoader.AddScript( 'FCKListHandler'		, 'internals/'	, ['FCKJSCoreExtensions','FCKDomTools','FCKTools'], FCK_GENERIC ) ;
+FCKScriptLoader.AddScript( 'FCKRegexLib'		, 'internals/' ) ;
 FCKScriptLoader.AddScript( 'FCKTools'			, 'internals/'	, ['FCKJSCoreExtensions','FCKBrowserInfo'], FCK_GENERIC_SPECIFIC ) ;
-FCKScriptLoader.AddScript( 'FCKElementPath'		, 'classes/'	, ['FCKListsLib'], FCK_GENERIC ) ;
-FCKScriptLoader.AddScript( 'FCKDocumentFragment', 'classes/'	, ['FCKDomTools'], FCK_SPECIFIC ) ;
-FCKScriptLoader.AddScript( 'FCKDomRange'		, 'classes/'	, ['FCKBrowserInfo','FCKJSCoreExtensions','FCKW3CRange','FCKElementPath','FCKDomTools','FCKTools','FCKDocumentFragment'], FCK_GENERIC_SPECIFIC ) ;
-FCKScriptLoader.AddScript( 'FCKEnterKey'		, 'classes/'	, ['FCKDomRange','FCKDomTools','FCKTools','FCKKeystrokeHandler','FCKListHandler'], FCK_GENERIC ) ;
-FCKScriptLoader.AddScript( 'FCKKeystrokeHandler', 'classes/'	, ['FCKConstants','FCKBrowserInfo','FCKTools'], FCK_GENERIC ) ;
-FCKScriptLoader.AddScript( 'FCKListHandler'		, 'internals/'	, ['FCKJSCoreExtensions','FCKDomTools','FCKTools'], FCK_GENERIC ) ;
-FCKScriptLoader.AddScript( 'FCKW3CRange'		, 'classes/'	, ['FCKDomTools','FCKTools','FCKDocumentFragment'], FCK_GENERIC ) ;
+FCKScriptLoader.AddScript( 'FCKXHtml'			, 'internals/'	, ['FCKBrowserInfo','FCKCodeFormatter','FCKConfig','FCKDomTools','FCKListsLib','FCKRegexLib','FCKTools','FCKXHtmlEntities'], FCK_GENERIC_SPECIFIC ) ;
+FCKScriptLoader.AddScript( 'FCKXHtmlEntities'	, 'internals/'	, ['FCKConfig'] ) ;
+
 // ####################################
Index: /FCKeditor/trunk/editor/_source/internals/fck.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/internals/fck.js	(revision 302)
@@ -26,9 +26,10 @@
 var FCK =
 {
-	Name		: FCKURLParams[ 'InstanceName' ],
-	Status		: FCK_STATUS_NOTLOADED,
-	EditMode	: FCK_EDITMODE_WYSIWYG,
-	Toolbar		: null,
-	HasFocus	: false,
+	Name			: FCKURLParams[ 'InstanceName' ],
+	Status			: FCK_STATUS_NOTLOADED,
+	EditMode		: FCK_EDITMODE_WYSIWYG,
+	Toolbar			: null,
+	HasFocus		: false,
+	DataProcessor	: new FCKDataProcessor(),
 
 	AttachToOnSelectionChange : function( functionPointer )
@@ -99,5 +100,5 @@
 
 		// Set the editor's startup contents
-		this.SetHTML( this.GetLinkedFieldValue(), true ) ;
+		this.SetData( this.GetLinkedFieldValue(), true ) ;
 	},
 
@@ -196,5 +197,5 @@
 	},
 
-	GetXHTML : function( format )
+	GetData : function( format )
 	{
 		// We assume that if the user is in source editing, the editor value must
@@ -205,35 +206,33 @@
 		this.FixBody() ;
 
-		var sXHTML ;
 		var oDoc = FCK.EditorDocument ;
-
 		if ( !oDoc )
 			return null ;
 
-		if ( FCKConfig.FullPage )
-		{
-			sXHTML = FCKXHtml.GetXHTML( oDoc.getElementsByTagName( 'html' )[0], true, format ) ;
-
+		var isFullPage = FCKConfig.FullPage ;
+
+		// Call the Data Processor to generate the output data.
+		var data = FCK.DataProcessor.ConvertToDataFormat(
+			isFullPage ? oDoc.getElementsByTagName( 'html' )[0] : oDoc.body,
+			!isFullPage,
+			FCKConfig.IgnoreEmptyParagraphValue,
+			format ) ;
+
+		// Restore protected attributes.
+		data = FCK.ProtectEventsRestore( data ) ;
+
+		if ( FCKBrowserInfo.IsIE )
+			data = data.replace( FCKRegexLib.ToReplace, '$1' ) ;
+
+		if ( isFullPage )
+		{
 			if ( FCK.DocTypeDeclaration && FCK.DocTypeDeclaration.length > 0 )
-				sXHTML = FCK.DocTypeDeclaration + '\n' + sXHTML ;
+				data = FCK.DocTypeDeclaration + '\n' + data ;
 
 			if ( FCK.XmlDeclaration && FCK.XmlDeclaration.length > 0 )
-				sXHTML = FCK.XmlDeclaration + '\n' + sXHTML ;
-		}
-		else
-		{
-			sXHTML = FCKXHtml.GetXHTML( oDoc.body, false, format ) ;
-
-			if ( FCKConfig.IgnoreEmptyParagraphValue && FCKRegexLib.EmptyOutParagraph.test( sXHTML ) )
-				sXHTML = '' ;
-		}
-
-		// Restore protected attributes.
-		sXHTML = FCK.ProtectEventsRestore( sXHTML ) ;
-
-		if ( FCKBrowserInfo.IsIE )
-			sXHTML = sXHTML.replace( FCKRegexLib.ToReplace, '$1' ) ;
-
-		return FCKConfig.ProtectedSource.Revert( sXHTML ) ;
+				data = FCK.XmlDeclaration + '\n' + data ;
+		}
+
+		return FCKConfig.ProtectedSource.Revert( data ) ;
 	},
 
@@ -300,5 +299,5 @@
 		if ( FCKBrowserInfo.IsIE )
 			sTags += sTags.length > 0 ? '|ABBR' : 'ABBR' ;
-		
+
 		var oRegex ;
 		if ( sTags.length > 0 )
@@ -310,5 +309,5 @@
 			html = html.replace( oRegex, '<\/FCK:$1>' ) ;
 		}
-		
+
 		// Protect some empty elements. We must do it separately becase the
 		// original tag may not contain the closing slash, like <hr>:
@@ -328,5 +327,5 @@
 	},
 
-	SetHTML : function( html, resetIsDirty )
+	SetData : function( data, resetIsDirty )
 	{
 		this.EditingArea.Mode = FCK.EditMode ;
@@ -334,104 +333,63 @@
 		if ( FCK.EditMode == FCK_EDITMODE_WYSIWYG )
 		{
-			html = FCKConfig.ProtectedSource.Protect( html ) ;
+			// Save the resetIsDirty for later use (async)
+			this._ForceResetIsDirty = ( resetIsDirty === true ) ;
+
+			// Protect parts of the code that must remain untouched (and invisible)
+			// during editing.
+			data = FCKConfig.ProtectedSource.Protect( data ) ;
+
+			// Call the Data Processor to transform the data.
+			data = FCK.DataProcessor.ConvertToHtml( data ) ;
 
 			// Fix for invalid self-closing tags (see #152).
-			html = html.replace( FCKRegexLib.InvalidSelfCloseTags, '$1></$2>' ) ;
-
-			html = FCK.ProtectEvents( html ) ;
-			html = FCK.ProtectUrls( html ) ;
-			html = FCK.ProtectTags( html ) ;
+			data = data.replace( FCKRegexLib.InvalidSelfCloseTags, '$1></$2>' ) ;
+
+			// Protect event attributes (they could get fired in the editing area).
+			data = FCK.ProtectEvents( data ) ;
+
+			// Protect some things from the browser itself.
+			data = FCK.ProtectUrls( data ) ;
+			data = FCK.ProtectTags( data ) ;
 
 			// Firefox can't handle correctly the editing of the STRONG and EM tags.
 			// We must replace them with B and I.
+			// TODO : remove this check  if possible, as soon as the new style system is in use.
 			if ( FCKBrowserInfo.IsGecko )
 			{
-				html = html.replace( FCKRegexLib.StrongOpener, '<b$1' ) ;
-				html = html.replace( FCKRegexLib.StrongCloser, '<\/b>' ) ;
-				html = html.replace( FCKRegexLib.EmOpener, '<i$1' ) ;
-				html = html.replace( FCKRegexLib.EmCloser, '<\/i>' ) ;
+				data = data.replace( FCKRegexLib.StrongOpener, '<b$1' ) ;
+				data = data.replace( FCKRegexLib.StrongCloser, '<\/b>' ) ;
+				data = data.replace( FCKRegexLib.EmOpener, '<i$1' ) ;
+				data = data.replace( FCKRegexLib.EmCloser, '<\/i>' ) ;
 			}
 
-			this._ForceResetIsDirty = ( resetIsDirty === true ) ;
-
-			var sHtml = '' ;
-
-			if ( FCKConfig.FullPage )
-			{
-				// The HTML must be fixed if the <head> is not available.
-				if ( !FCKRegexLib.HeadOpener.test( html ) )
-				{
-					// Check if the <html> is available.
-					if ( !FCKRegexLib.HtmlOpener.test( html ) )
-						html = '<html dir="' + FCKConfig.ContentLangDirection + '">' + html + '</html>' ;
-
-					// Add the <head>.
-					html = html.replace( FCKRegexLib.HtmlOpener, '$&<head></head>' ) ;
-				}
-
-				// Save the DOCTYPE.
-				FCK.DocTypeDeclaration = html.match( FCKRegexLib.DocTypeTag ) ;
-
-				if ( FCKBrowserInfo.IsIE )
-					sHtml = FCK._GetBehaviorsStyle() ;
-				else if ( FCKConfig.ShowBorders )
-					sHtml = '<link href="' + FCKConfig.FullBasePath + 'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
-
-				sHtml += '<link href="' + FCKConfig.FullBasePath + 'css/fck_internal.css' + '" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
-
-				// Attention: do not change it before testing it well (sample07)!
-				// This is tricky... if the head ends with <meta ... content type>,
-				// Firefox will break. But, it works if we include the temporary
-				// links as the last elements in the HEAD.
-				sHtml = html.replace( FCKRegexLib.HeadCloser, sHtml + '$&' ) ;
-
-				// Insert the base tag (FCKConfig.BaseHref), if not exists in the source.
-				// The base must be the first tag in the HEAD, to get relative
-				// links on styles, for example.
-				if ( FCK.TempBaseTag.length > 0 && !FCKRegexLib.HasBaseTag.test( html ) )
-					sHtml = sHtml.replace( FCKRegexLib.HeadOpener, '$&' + FCK.TempBaseTag ) ;
-			}
-			else
-			{
-				sHtml =
-					FCKConfig.DocType +
-					'<html dir="' + FCKConfig.ContentLangDirection + '"' ;
-
-				// On IE, if you are use a DOCTYPE differenft of HTML 4 (like
-				// XHTML), you must force the vertical scroll to show, otherwise
-				// the horizontal one may appear when the page needs vertical scrolling.
-				if ( FCKBrowserInfo.IsIE && !FCKRegexLib.Html4DocType.test( FCKConfig.DocType ) )
-					sHtml += ' style="overflow-y: scroll"' ;
-
-				sHtml +=
-					'><head><title></title>' +
-					_FCK_GetEditorAreaStyleTags() +
-					'<link href="' + FCKConfig.FullBasePath + 'css/fck_internal.css' + '" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
-
-				if ( FCKBrowserInfo.IsIE )
-					sHtml += FCK._GetBehaviorsStyle() ;
-				else if ( FCKConfig.ShowBorders )
-					sHtml += '<link href="' + FCKConfig.FullBasePath + 'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
-
-				sHtml += FCK.TempBaseTag ;
-
-				// Add ID and Class to the body
-				var sBodyTag = '<body' ;
-				if ( FCKConfig.BodyId && FCKConfig.BodyId.length > 0 )
-					sBodyTag += ' id="' + FCKConfig.BodyId + '"' ;
-				if ( FCKConfig.BodyClass && FCKConfig.BodyClass.length > 0 )
-					sBodyTag += ' class="' + FCKConfig.BodyClass + '"' ;
-				sHtml += '</head>' + sBodyTag + '>' ;
-
-				if ( FCKBrowserInfo.IsGecko && ( html.length == 0 || FCKRegexLib.EmptyParagraph.test( html ) ) )
-					sHtml += GECKO_BOGUS ;
-				else
-					sHtml += html ;
-
-				sHtml += '</body></html>' ;
-			}
-
+			// Insert the base tag (FCKConfig.BaseHref), if not exists in the source.
+			// The base must be the first tag in the HEAD, to get relative
+			// links on styles, for example.
+			if ( FCK.TempBaseTag.length > 0 && !FCKRegexLib.HasBaseTag.test( data ) )
+				data = data.replace( FCKRegexLib.HeadOpener, '$&' + FCK.TempBaseTag ) ;
+
+			// Build the HTML for the additional things we need on <head>.
+			var sHeadExtra = '' ;
+
+			if ( !FCKConfig.FullPage )
+				sHeadExtra += _FCK_GetEditorAreaStyleTags() ;
+
+			if ( FCKBrowserInfo.IsIE )
+				sHeadExtra += FCK._GetBehaviorsStyle() ;
+			else if ( FCKConfig.ShowBorders )
+				sHeadExtra += '<link href="' + FCKConfig.FullBasePath + 'css/fck_showtableborders_gecko.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
+
+			sHeadExtra += '<link href="' + FCKConfig.FullBasePath + 'css/fck_internal.css" rel="stylesheet" type="text/css" _fcktemp="true" />' ;
+
+			// Attention: do not change it before testing it well (sample07)!
+			// This is tricky... if the head ends with <meta ... content type>,
+			// Firefox will break. But, it works if we place our extra stuff as
+			// the last elements in the HEAD.
+			data = data.replace( FCKRegexLib.HeadCloser, sHeadExtra + '$&' ) ;
+
+			// Load the HTML in the editing area.
 			this.EditingArea.OnLoad = _FCK_EditingArea_OnLoad ;
-			this.EditingArea.Start( sHtml ) ;
+			this.EditingArea.Start( data ) ;
 		}
 		else
@@ -443,5 +401,5 @@
 
 			this.EditingArea.OnLoad = null ;
-			this.EditingArea.Start( html ) ;
+			this.EditingArea.Start( data ) ;
 
 			// Enables the context menu in the textarea.
@@ -589,5 +547,5 @@
 		FCK.EditMode = bIsWysiwyg ? FCK_EDITMODE_SOURCE : FCK_EDITMODE_WYSIWYG ;
 
-		FCK.SetHTML( sHtml, !bIsDirty ) ;
+		FCK.SetData( sHtml, !bIsDirty ) ;
 
 		// Set the Focus.
@@ -628,6 +586,10 @@
 
 FCK.Events	= new FCKEvents( FCK ) ;
-// GetHTML is Deprecated : returns the same value as GetXHTML.
-FCK.GetHTML	= FCK.GetXHTML ;
+
+// DEPRECATED in favor or "GetData".
+FCK.GetHTML	= FCK.GetXHTML = FCK.GetData ;
+
+// DEPRECATED in favor of "SetData".
+FCK.SetHTML = FCK.SetData ;
 
 // Replace all events attributes (like onclick).
Index: /FCKeditor/trunk/editor/_source/internals/fck_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck_gecko.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/internals/fck_gecko.js	(revision 302)
@@ -28,5 +28,5 @@
 FCK.InitializeBehaviors = function()
 {
-	// When calling "SetHTML", the editing area IFRAME gets a fixed height. So we must recaulculate it.
+	// When calling "SetData", the editing area IFRAME gets a fixed height. So we must recaulculate it.
 	if ( FCKBrowserInfo.IsGecko )		// Not for Safari/Opera.
 		Window_OnResize() ;
@@ -150,8 +150,8 @@
 	// Firefox can't handle correctly the editing of the STRONG and EM tags.
 	// We must replace them with B and I.
-		html = html.replace( FCKRegexLib.StrongOpener, '<b$1' ) ;
-		html = html.replace( FCKRegexLib.StrongCloser, '<\/b>' ) ;
-		html = html.replace( FCKRegexLib.EmOpener, '<i$1' ) ;
-		html = html.replace( FCKRegexLib.EmCloser, '<\/i>' ) ;
+	html = html.replace( FCKRegexLib.StrongOpener, '<b$1' ) ;
+	html = html.replace( FCKRegexLib.StrongCloser, '<\/b>' ) ;
+	html = html.replace( FCKRegexLib.EmOpener, '<i$1' ) ;
+	html = html.replace( FCKRegexLib.EmCloser, '<\/i>' ) ;
 
 	// Delete the actual selection.
Index: /FCKeditor/trunk/editor/_source/internals/fckregexlib.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckregexlib.js	(revision 301)
+++ /FCKeditor/trunk/editor/_source/internals/fckregexlib.js	(revision 302)
@@ -24,5 +24,5 @@
 var FCKRegexLib =
 {
-// This is the Regular expression used by the SetHTML method for the "&apos;" entity.
+// This is the Regular expression used by the SetData method for the "&apos;" entity.
 AposEntity		: /&apos;/gi ,
 
@@ -42,4 +42,5 @@
 
 HasBaseTag		: /<base /i ,
+HasBodyTag		: /<body[\s|>]/i ,
 
 HtmlOpener		: /<html\s?[^>]*>/i ,
@@ -70,6 +71,4 @@
 EmOpener		: /<EM([ \>])/gi ,
 EmCloser		: /<\/EM>/gi ,
-//AbbrOpener		: /<ABBR([ \>])/gi ,
-//AbbrCloser		: /<\/ABBR>/gi ,
 
 GeckoEntitiesMarker : /#\?-\:/g ,
Index: /FCKeditor/trunk/editor/dialog/fck_source.html
===================================================================
--- /FCKeditor/trunk/editor/dialog/fck_source.html	(revision 301)
+++ /FCKeditor/trunk/editor/dialog/fck_source.html	(revision 302)
@@ -50,5 +50,5 @@
 		oEditor.FCKUndo.SaveUndoStep() ;
 
-	FCK.SetHTML( document.getElementById('txtSource').value, false ) ;
+	FCK.SetData( document.getElementById('txtSource').value, false ) ;
 
 	return true ;
Index: /FCKeditor/trunk/editor/dialog/fck_spellerpages.html
===================================================================
--- /FCKeditor/trunk/editor/dialog/fck_spellerpages.html	(revision 301)
+++ /FCKeditor/trunk/editor/dialog/fck_spellerpages.html	(revision 302)
@@ -52,5 +52,5 @@
 {
 	if ( numberOCorrections > 0 )
-		oEditor.FCK.SetHTML( document.getElementById('txtHtml').value ) ;
+		oEditor.FCK.SetData( document.getElementById('txtHtml').value ) ;
 	window.parent.Cancel() ;
 }
Index: /FCKeditor/trunk/editor/dialog/fck_template.html
===================================================================
--- /FCKeditor/trunk/editor/dialog/fck_template.html	(revision 301)
+++ /FCKeditor/trunk/editor/dialog/fck_template.html	(revision 302)
@@ -192,5 +192,5 @@
 
 	if ( GetE('xChkReplaceAll').checked )
-		FCK.SetHTML( FCK._Templates[index].Html ) ;
+		FCK.SetData( FCK._Templates[index].Html ) ;
 	else
 		FCK.InsertHtml( FCK._Templates[index].Html ) ;
Index: /FCKeditor/trunk/editor/fckeditor.html
===================================================================
--- /FCKeditor/trunk/editor/fckeditor.html	(revision 301)
+++ /FCKeditor/trunk/editor/fckeditor.html	(revision 302)
@@ -64,4 +64,5 @@
 LoadScript( '_source/internals/fckurlparams.js' ) ;
 LoadScript( '_source/classes/fckevents.js' ) ;
+LoadScript( '_source/classes/fckdataprocessor.js' ) ;
 LoadScript( '_source/internals/fck.js' ) ;
 LoadScript( '_source/internals/fck_' + sSuffix + '.js' ) ;
Index: /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.config.js
===================================================================
--- /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.config.js	(revision 302)
+++ /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.config.js	(revision 302)
@@ -0,0 +1,26 @@
+﻿/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Sample custom configuration settings used by the BBCode plugin. It simply
+ * loads the plugin. All the rest is done by the plugin itself.
+ */
+
+// Add the BBCode plugin.
+FCKConfig.Plugins.Add( 'bbcode' ) ;
Index: /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.html
===================================================================
--- /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.html	(revision 302)
+++ /FCKeditor/trunk/editor/plugins/bbcode/_sample/sample.html	(revision 302)
@@ -0,0 +1,67 @@
+﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<!--
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * Sample page.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>FCKeditor - BBCode Sample</title>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<meta name="robots" content="noindex, nofollow" />
+	<link href="../../../../_samples/sample.css" rel="stylesheet" type="text/css" />
+	<script type="text/javascript" src="../../../../fckeditor.js"></script>
+</head>
+<body>
+	<h1>
+		FCKeditor - BBCode Sample</h1>
+	<p>
+		This is a sample of custom Data Processor implementation for (very) basic BBCode
+		syntax. Only <strong>[b]</strong>, <strong>[i]</strong>, <strong>[u]</strong> and
+		<strong>[url]</strong> may be used. It may be extended, but this is out of this
+		sample purpose.
+	</p>
+	<p>
+		Note that the input and output of the editor is not HTML, but BBCode
+	</p>
+	<hr />
+	<form action="../../../../_samples/html/sampleposteddata.asp" method="post" target="_blank">
+		<script type="text/javascript">
+<!--
+// Automatically calculates the editor base path based on the _samples directory.
+// This is usefull only for these samples. A real application should use something like this:
+// oFCKeditor.BasePath = '/fckeditor/' ;	// '/fckeditor/' is the default value.
+var sBasePath = document.location.pathname.substring(0,document.location.pathname.lastIndexOf('editor')) ;
+
+var oFCKeditor = new FCKeditor( 'FCKeditor1' ) ;
+oFCKeditor.BasePath	= sBasePath ;
+
+// Set the custom configurations file path (in this way the original file is mantained).
+oFCKeditor.Config['CustomConfigurationsPath'] = sBasePath + 'editor/plugins/bbcode/_sample/sample.config.js' ;
+
+oFCKeditor.Value = 'This is some [b]sample text[/b]. You are using [url=http://www.fckeditor.net/]FCKeditor[/url].' ;
+oFCKeditor.Create() ;
+//-->
+		</script>
+		<br />
+		<input type="submit" value="Submit" />
+	</form>
+</body>
+</html>
Index: /FCKeditor/trunk/editor/plugins/bbcode/fckplugin.js
===================================================================
--- /FCKeditor/trunk/editor/plugins/bbcode/fckplugin.js	(revision 302)
+++ /FCKeditor/trunk/editor/plugins/bbcode/fckplugin.js	(revision 302)
@@ -0,0 +1,123 @@
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * This is a sample implementation for a custom Data Processor for basic BBCode.
+ */
+
+FCK.DataProcessor =
+{
+	/*
+	 * Returns a string representing the HTML format of "data". The returned
+	 * value will be loaded in the editor.
+	 * The HTML must be from <html> to </html>, eventually including
+	 * the DOCTYPE.
+	 *     @param {String} data The data to be converted in the
+	 *            DataProcessor specific format.
+	 */
+	ConvertToHtml : function( data )
+	{
+		// Convert < and > to their HTML entities.
+        data = data.replace( /</g, '&lt;' ) ;
+        data = data.replace( />/g, '&gt;' ) ;
+
+        // Convert line breaks to <br>.
+        data = data.replace( /(?:\r\n|\n|\r)/g, '<br>' ) ;
+
+        // [url]
+        data = data.replace( /\[url\](.+?)\[\/url]/gi, '<a href="$1">$1</a>' ) ;
+        data = data.replace( /\[url\=([^\]]+)](.+?)\[\/url]/gi, '<a href="$1">$2</a>' ) ;
+
+        // [b]
+        data = data.replace( /\[b\](.+?)\[\/b]/gi, '<b>$1</b>' ) ;
+
+        // [i]
+        data = data.replace( /\[i\](.+?)\[\/i]/gi, '<i>$1</i>' ) ;
+
+        // [u]
+        data = data.replace( /\[u\](.+?)\[\/u]/gi, '<u>$1</u>' ) ;
+
+		return '<html><head><title></title></head><body>' + data + '</body></html>' ;
+	},
+
+	/*
+	 * Converts a DOM (sub-)tree to a string in the data format.
+	 *     @param {Object} rootNode The node that contains the DOM tree to be
+	 *            converted to the data format.
+	 *     @param {Boolean} excludeRoot Indicates that the root node must not
+	 *            be included in the conversion, only its children.
+	 *     @param {Boolean} format Indicates that the data must be formatted
+	 *            for human reading. Not all Data Processors may provide it.
+	 */
+	ConvertToDataFormat : function( rootNode, excludeRoot, ignoreIfEmptyParagraph, format )
+	{
+		var data = rootNode.innerHTML ;
+
+		// Convert <br> to line breaks.
+		data = data.replace( /<br(?=[ \/>]).*?>/gi, '\r\n') ;
+
+		// [url]
+		data = data.replace( /<a .*?href=(["'])(.+?)\1.*?>(.+?)<\/a>/gi, '[url=$2]$3[/url]') ;
+
+		// [b]
+		data = data.replace( /<(?:b|strong)>/gi, '[b]') ;
+		data = data.replace( /<\/(?:b|strong)>/gi, '[/b]') ;
+
+		// [i]
+		data = data.replace( /<(?:i|em)>/gi, '[i]') ;
+		data = data.replace( /<\/(?:i|em)>/gi, '[/i]') ;
+
+		// [u]
+		data = data.replace( /<u>/gi, '[u]') ;
+		data = data.replace( /<\/u>/gi, '[/u]') ;
+
+		// Remove remaining tags.
+		data = data.replace( /<[^>]+>/g, '') ;
+
+		return data ;
+	},
+
+	/*
+	 * Makes any necessary changes to a piece of HTML for insertion in the
+	 * editor selection position.
+	 *     @param {String} html The HTML to be fixed.
+	 */
+	FixHtml : function( html )
+	{
+		return html ;
+	}
+} ;
+
+// This Data Processor doesn't support <p>, so let's use <br>.
+FCKConfig.EnterMode = 'br' ;
+
+// To avoid pasting invalid markup (which is discarded in any case), let's
+// force pasting to plain text.
+FCKConfig.ForcePasteAsPlainText	= true ;
+
+// Rename the "Source" buttom to "BBCode".
+FCKToolbarItems.RegisterItem( 'Source', new FCKToolbarButton( 'Source', 'BBCode', null, FCK_TOOLBARITEM_ICONTEXT, true, true, 1 ) ) ;
+
+// Let's enforce the toolbar to the limits of this Data Processor. A custom
+// toolbar set may be defined in the configuration file with more or less entries.
+FCKConfig.ToolbarSets["Default"] = [
+	['Source'],
+	['Bold','Italic','Underline','-','Link'],
+	['About']
+] ;
Index: /FCKeditor/trunk/fckpackager.xml
===================================================================
--- /FCKeditor/trunk/fckpackager.xml	(revision 301)
+++ /FCKeditor/trunk/fckpackager.xml	(revision 302)
@@ -71,4 +71,5 @@
 		<File path="editor/_source/internals/fckurlparams.js" />
 		<File path="editor/_source/classes/fckevents.js" />
+		<File path="editor/_source/classes/fckdataprocessor.js" />
 		<File path="editor/_source/internals/fck.js" />
 		<File path="editor/_source/internals/fck_ie.js" />
@@ -156,4 +157,5 @@
 		<File path="editor/_source/internals/fckurlparams.js" />
 		<File path="editor/_source/classes/fckevents.js" />
+		<File path="editor/_source/classes/fckdataprocessor.js" />
 		<File path="editor/_source/internals/fck.js" />
 		<File path="editor/_source/internals/fck_gecko.js" />
