Index: /FCKeditor/trunk/_dev/browserbugs/opera/nbsp_innerHTML.html
===================================================================
--- /FCKeditor/trunk/_dev/browserbugs/opera/nbsp_innerHTML.html	(revision 51)
+++ /FCKeditor/trunk/_dev/browserbugs/opera/nbsp_innerHTML.html	(revision 51)
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+    <title>nbsp and innerHTML</title>
+    <script type="text/javascript">
+
+window.onload = function()
+{
+	alert( document.body.innerHTML ) ;
+}
+
+    </script>
+</head>
+<body>
+	[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
+</body>
+</html>
Index: /FCKeditor/trunk/_dev/browserbugs/safari/nbsp_innerHTML.html
===================================================================
--- /FCKeditor/trunk/_dev/browserbugs/safari/nbsp_innerHTML.html	(revision 51)
+++ /FCKeditor/trunk/_dev/browserbugs/safari/nbsp_innerHTML.html	(revision 51)
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head>
+    <title>nbsp and innerHTML</title>
+    <script type="text/javascript">
+
+window.onload = function()
+{
+	alert( document.body.innerHTML ) ;
+}
+
+    </script>
+</head>
+<body>
+	[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
+</body>
+</html>
Index: /FCKeditor/trunk/_test/automated/tests/fckdomrange.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/fckdomrange.html	(revision 51)
+++ /FCKeditor/trunk/_test/automated/tests/fckdomrange.html	(revision 51)
@@ -0,0 +1,650 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>FCKDomRange - Tests for JsUnit</title>
+	<script type="text/javascript" src="tests.js"></script>
+	<script type="text/javascript" src="../_jsunit/app/jsUnitCore.js"></script>
+	<script src="../../../editor/_source/fckscriptloader.js" type="text/javascript"></script>
+	<script type="text/javascript">
+
+FCKScriptLoader.Load( 'FCKDomRange' ) ;
+
+	</script>
+	<script type="text/javascript">
+
+function test_SetStart_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 1 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetStart_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 2 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetStart_3()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 3 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetStart_4()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 4 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetEnd_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetEnd( document.getElementById('_Span'), 1 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetEnd_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetEnd( document.getElementById('_Span'), 2 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetEnd_3()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetEnd( document.getElementById('_Span'), 3 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_SetEnd_4()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetEnd( document.getElementById('_Span'), 4 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_CheckIsCollapsed()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P'), 1 ) ;
+	
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_Collapse()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P'), 1 ) ;
+	range.SetEnd( document.getElementById('_Span'), 2 ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+	
+	range.Collapse( true ) ;
+	
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_DeleteContents()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P'), 1 ) ;
+	range.SetEnd( document.getElementById('_Strong'), 2 ) ;
+	
+	range.DeleteContents() ;
+
+	assertEquals( 'HTML after deletion', '<strong id=_strong></strong> markup. examples of commonly found content are:', GetTestInnerHtml( document.getElementById( '_P' ) ) ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_ExtractContents()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P2'), 1 ) ;
+	range.SetEnd( document.getElementById('_Em'), 2 ) ;
+	
+	var docFrag = range.ExtractContents() ;
+
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+
+	assertEquals( 'Extracted HTML', 'in the test we will try to recreate this document using the editor tools. to make sure tables can be inserted <em id=_em>properly</em>', GetTestInnerHtml( tmpDiv ) ) ;
+	assertEquals( 'HTML after extraction', '<em id=_em></em> we re-visit banana import statistics from 1998.', GetTestInnerHtml( document.getElementById( '_P2' ) ) ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_P2'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P2'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	
+	assertEquals( 'EndContainer', document.getElementById('_P2'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P2'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_Clone()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P2'), 1 ) ;
+	range.SetEnd( document.getElementById('_Em'), 2 ) ;
+	
+	var clone = range.Clone() ;
+	clone.SetStart( document.getElementById('_P'), 1 ) ;
+	clone.Collapse( true ) ;
+
+	assertEquals( 'range.StartContainer', document.getElementById('_P2'), range.StartContainer ) ;
+	assertEquals( 'range.StartBlock', document.getElementById('_P2'), range.StartBlock ) ;
+	assertEquals( 'range.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'range.EndContainer', document.getElementById('_Em'), range.EndContainer ) ;
+	assertEquals( 'range.EndBlock', document.getElementById('_P2'), range.EndBlock ) ;
+	assertEquals( 'range.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'range.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	assertEquals( 'clone.StartContainer', document.getElementById('_P'), clone.StartContainer ) ;
+	assertEquals( 'clone.StartBlock', document.getElementById('_P'), clone.StartBlock ) ;
+	assertEquals( 'clone.StartBlockLimit', document.body, clone.StartBlockLimit ) ;
+	assertEquals( 'clone.EndContainer', document.getElementById('_P'), clone.EndContainer ) ;
+	assertEquals( 'clone.EndBlock', document.getElementById('_P'), clone.EndBlock ) ;
+	assertEquals( 'clone.EndBlockLimit', document.body, clone.EndBlockLimit ) ;
+	assertTrue( 'clone.CheckIsCollapsed', clone.CheckIsCollapsed() ) ;
+}
+
+function test_MoveToNodeContents()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_Strong') ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_Strong'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'EndContainer', document.getElementById('_Strong'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_MoveToElementStart()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToElementStart( document.getElementById('_Strong') ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_Strong'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'EndContainer', document.getElementById('_Strong'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertTrue( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_InsertNode()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToElementStart( document.getElementById('_Strong') ) ;
+	
+	var eNewNode = document.createElement( 'span' ) ;
+	eNewNode.innerHTML = 'test' ;
+	range.InsertNode( eNewNode ) ;
+
+	assertEquals( 'HTML after insertion', '<span>test</span>proper', GetTestInnerHtml( document.getElementById( '_Strong' ) ) ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_Strong'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'EndContainer', document.getElementById('_Strong'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+}
+
+function test_CheckIsEmpty_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToElementStart( document.getElementById('_Strong') ) ;
+	
+	assertTrue( range.CheckIsEmpty() ) ;
+}
+
+function test_CheckIsEmpty_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_Strong') ) ;
+	
+	assertFalse( range.CheckIsEmpty() ) ;
+}
+
+function test_CheckIsEmpty_3()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_Pnbsp') ) ;
+
+	assertFalse( range.CheckIsEmpty() ) ;
+}
+
+function test_CheckIsEmpty_4()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_Pspaces') ) ;
+
+	assertTrue( range.CheckIsEmpty() ) ;
+}
+
+function test_CheckStartOfBlock_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_P') ) ;
+
+	assertTrue( range.CheckStartOfBlock() ) ;
+}
+
+function test_CheckStartOfBlock_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_P').firstChild ) ;
+
+	assertTrue( range.CheckStartOfBlock() ) ;
+}
+
+function test_CheckStartOfBlock_3()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span').nextSibling, 1 ) ;
+
+	assertFalse( range.CheckStartOfBlock() ) ;
+}
+
+function test_CheckEndOfBlock_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_P') ) ;
+
+	assertTrue( range.CheckEndOfBlock() ) ;
+}
+
+function test_CheckEndOfBlock_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_P').lastChild, 2 ) ;
+
+	assertTrue( range.CheckEndOfBlock() ) ;
+}
+
+function test_CheckEndOfBlock_3()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span').nextSibling, 1 ) ;
+
+	assertFalse( range.CheckEndOfBlock() ) ;
+}
+
+function test_MoveToBookmark_1()
+{
+	var bodyHtml = document.body.innerHTML ;
+
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 1 ) ;
+	range.SetEnd( document.getElementById('_P'), 2 ) ;
+	
+	assertEquals( '1.StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( '1.StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( '1.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '1.EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( '1.EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( '1.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( '1.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+	
+	var bookmark = range.CreateBookmark() 
+	
+	range.MoveToElementStart( document.getElementById('_P2') ) ;
+
+	assertEquals( '2.StartContainer', document.getElementById('_P2'), range.StartContainer ) ;
+	assertEquals( '2.StartBlock', document.getElementById('_P2'), range.StartBlock ) ;
+	assertEquals( '2.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '2.EndContainer', document.getElementById('_P2'), range.EndContainer ) ;
+	assertEquals( '2.EndBlock', document.getElementById('_P2'), range.EndBlock ) ;
+	assertEquals( '2.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertTrue( '2.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	range.MoveToBookmark( bookmark ) ;
+
+	assertEquals( '3.StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( '3.StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( '3.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '3.EndContainer', document.getElementById('_P'), range.EndContainer ) ;
+	assertEquals( '3.EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( '3.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( '3.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	// The body HTML must remain unchanged.
+	assertEquals( bodyHtml, document.body.innerHTML ) ;
+}
+
+function test_MoveToBookmark_2()
+{
+	var bodyHtml = document.body.innerHTML ;
+
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_Span'), 1 ) ;
+	
+	assertEquals( '1.StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( '1.StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( '1.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '1.EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( '1.EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( '1.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertTrue( '1.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+	
+	var bookmark = range.CreateBookmark() 
+	
+	range.MoveToNodeContents( document.getElementById('_P2') ) ;
+
+	assertEquals( '2.StartContainer', document.getElementById('_P2'), range.StartContainer ) ;
+	assertEquals( '2.StartBlock', document.getElementById('_P2'), range.StartBlock ) ;
+	assertEquals( '2.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '2.EndContainer', document.getElementById('_P2'), range.EndContainer ) ;
+	assertEquals( '2.EndBlock', document.getElementById('_P2'), range.EndBlock ) ;
+	assertEquals( '2.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( '2.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	range.MoveToBookmark( bookmark ) ;
+
+	assertEquals( '3.StartContainer', document.getElementById('_Span'), range.StartContainer ) ;
+	assertEquals( '3.StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( '3.StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( '3.EndContainer', document.getElementById('_Span'), range.EndContainer ) ;
+	assertEquals( '3.EndBlock', document.getElementById('_P'), range.EndBlock ) ;
+	assertEquals( '3.EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertTrue( '3.CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	// The body HTML must remain unchanged.
+	assertEquals( bodyHtml, document.body.innerHTML ) ;
+}
+
+function test_Expand_1()
+{
+	var range = new FCKDomRange( window ) ;
+	range.SetStart( document.getElementById('_A'), 1 ) ;
+	range.SetEnd( document.getElementById('_Img'), 3 ) ;
+	
+	range.Expand( 'block_contents' ) ;
+
+	assertEquals( 'StartContainer', document.getElementById('_P'), range.StartContainer ) ;
+	assertEquals( 'StartBlock', document.getElementById('_P'), range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'EndContainer', document.getElementById('_P3'), range.EndContainer ) ;
+	assertEquals( 'EndBlock', document.getElementById('_P3'), range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	assertTrue( 'CheckStartOfBlock', range.CheckStartOfBlock() ) ;
+	assertTrue( 'CheckEndOfBlock', range.CheckEndOfBlock() ) ;
+}
+
+function test_Expand_2()
+{
+	var range = new FCKDomRange( window ) ;
+	range.MoveToNodeContents( document.getElementById('_StrongNoPara') ) ;
+	
+	range.Expand( 'block_contents' ) ;
+
+	assertEquals( 'StartContainer', document.body, range.StartContainer ) ;
+	assertNull( 'StartBlock', range.StartBlock ) ;
+	assertEquals( 'StartBlockLimit', document.body, range.StartBlockLimit ) ;
+	assertEquals( 'EndContainer', document.body, range.EndContainer ) ;
+	assertNull( 'EndBlock', range.EndBlock ) ;
+	assertEquals( 'EndBlockLimit', document.body, range.EndBlockLimit ) ;
+	assertFalse( 'CheckIsCollapsed', range.CheckIsCollapsed() ) ;
+
+	var docFrag = range.ExtractContents() ;
+
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+
+	assertEquals( 'Range HTML', 'this text has no block tag. it should be corrected when working with the enter key set to p or div tags. the <strong id=_strongnopara>br configuration</strong> should not make changes instead.', GetTestInnerHtml( tmpDiv ) ) ;
+}
+
+	</script>
+	<script type="text/javascript">
+
+var _BodyHtml ;
+
+function setUpPage()
+{
+	_BodyHtml = document.body.innerHTML ;
+	setUpPageStatus = 'complete' ;
+}
+
+// JsUnit special function called before every test start.
+function setUp()
+{
+	// Reset the body (because of changes by test functions).
+	document.body.innerHTML = _BodyHtml ;	
+}
+
+// Use window.onload to call a test outside JsUnit (for debugging).
+// The "tests.js" script must be commented.
+//window.onload = function()
+//{
+//	test_MoveToBookmark() ;
+//}
+
+	</script>
+</head>
+<body>
+	<h1>
+		Test page for FCKeditor
+	</h1>
+	<p id="_P">
+		This document contains various markup features commonly used by content editors
+		or "<span id="_Span" lang="fr">r&eacute;dacteurs de contenu</span>" as they are
+		called in <a id="_A" href="http://en.wikipedia.org/wiki/France" title="Wikipedia article about France">
+			France</a>.<br />
+		It is important that a <acronym id="_Acronym" title="what you see is what you get">WYSIWYG</acronym>
+		tool has features that are easily available for the editor. If not, there is a risk
+		that content won't receive <strong id="_Strong">proper</strong> markup. Examples
+		of commonly found content are:</p>
+	<p id="_Pnbsp">
+		&nbsp;
+	</p>
+	<p id="_Pspaces">
+	</p>
+	<ol>
+		<li>Headings</li>
+		<li style="color: Red">Links (with optional title) </li>
+		<li>Lists (like this one)
+			<ul>
+				<li>including nested lists </li>
+			</ul>
+		</li>
+		<li>Tables
+			<ul>
+				<li>caption</li>
+				<li>headers</li>
+				<li>summary</li>
+			</ul>
+		</li>
+		<li>Language information</li>
+		<li>Acronyms and abbreviations</li>
+		<li>Emphasis and strong emphasis </li>
+		<li>Quotes, inline and block </li>
+		<li>Images</li>
+	</ol>
+	<hr />
+	<h2 style="background-color: Silver">
+		Test procedure
+	</h2>
+	This text has no block tag. It should be corrected when working with the enter key
+	set to "p" or "div" tags. The "br" configuration should not make changes instead.
+	<p id="_P2">
+		In the test we will try to recreate this document using the editor tools. To make
+		sure tables can be inserted <em id="_Em">properly</em> we re-visit banana import
+		statistics from 1998.
+	</p>
+	<p id="_P3">
+		This paragraph has and image at the very end of its contents.<img id="_Img" src="img.gif"
+			alt="" />
+	</p>
+	This text has no block tag. It should be corrected when working with the enter key
+	set to "p" or "div" tags. The <strong id="_StrongNoPara">"br" configuration</strong>
+	should not make changes instead.
+	<p>
+		In the test we will try to recreate this document using the editor tools. To make
+		sure tables can be inserted <em>properly</em> we re-visit banana import statistics
+		from 1998.
+	</p>
+	<table summary="Sweden was the top importing country by far in 1998.">
+		<caption>
+			Top banana importers 1998 (value of banana imports in millions of US dollars per
+			million people)<br />
+			<br />
+		</caption>
+		<tr>
+			<th scope="col">
+				Country</th>
+			<th scope="col">
+				Millions of US dollars per million people</th>
+		</tr>
+		<tr>
+			<td>
+				Sweden</td>
+			<td>
+				17.12</td>
+		</tr>
+		<tr>
+			<td>
+				United&nbsp;Kingdom</td>
+			<td>
+				8.88</td>
+		</tr>
+		<tr>
+			<td>
+				Germany</td>
+			<td>
+				8.36</td>
+		</tr>
+		<tr>
+			<td>
+				Italy</td>
+			<td>
+				5.96</td>
+		</tr>
+		<tr>
+			<td>
+				United States</td>
+			<td>
+				4.78</td>
+		</tr>
+	</table>
+	<p>
+		For block quotes we will have a look at <a href="http://fawny.org/rhcp.html">what Joe
+			Clark says about redheads</a>:</p>
+	<blockquote cite="http://fawny.org/rhcp.html#me">
+		<p>
+			"Since boyhood I&rsquo;ve always believed, at the deepest level, that redheads are
+			standard-bearers of the grandest and most wondrous human beauty."</p>
+	</blockquote>
+	<p>
+		<img src="img.gif" alt="" /></p>
+	<p>
+		The above is the FCKeditor logo loaded from the FCKeditor.net web site.</p>
+</body>
+</html>
Index: /FCKeditor/trunk/_test/automated/tests/fcktools.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/fcktools.html	(revision 50)
+++ /FCKeditor/trunk/_test/automated/tests/fcktools.html	(revision 51)
@@ -31,12 +31,12 @@
 }
 
-function test_GetParentWindow()
+function test_GetDocumentWindow()
 {
 	// In IE, the type of the returned window is different of window, but it is ok.
-	if ( FCKTools.GetParentWindow( document ) != window )
+	if ( FCKTools.GetDocumentWindow( document ) != window )
 	{
 		assertEquals(
 			window,
-			FCKTools.GetParentWindow( document ) ) ;
+			FCKTools.GetDocumentWindow( document ) ) ;
 	}
 }
@@ -55,4 +55,38 @@
 }
 
+function test_CloneObject()
+{
+	var original =
+	{
+		Text : 'Some Text',
+		Number : 10,
+		ArrayObject : [ 1, 3, 5 ]
+	}
+	
+	var clone = FCKTools.CloneObject( original ) ;
+	
+	assertEquals( 'original.Text', 'Some Text', original.Text ) ;
+	assertEquals( 'original.Number', 10, original.Number ) ;
+	assertEquals( 'original.ArrayObject.length', 3, original.ArrayObject.length) ;
+
+	assertEquals( 'clone.Text', 'Some Text', clone.Text ) ;
+	assertEquals( 'clone.Number', 10, clone.Number ) ;
+	assertEquals( 'clone.ArrayObject.length', 3, clone.ArrayObject.length) ;
+
+	clone.Text += ' Test' ;
+	clone.Number += 15 ;
+	clone.ArrayObject = new Array() ;
+	clone.ArrayObject.push( 2 ) ;
+
+	assertEquals( 'original.Text', 'Some Text', original.Text ) ;
+	assertEquals( 'original.Number', 10, original.Number ) ;
+	assertEquals( 'original.ArrayObject.length', 3, original.ArrayObject.length) ;
+
+	assertEquals( 'clone.Text', 'Some Text Test', clone.Text ) ;
+	assertEquals( 'clone.Number', 25, clone.Number ) ;
+	assertEquals( 'clone.ArrayObject.length', 1, clone.ArrayObject.length) ;
+
+}
+
 	</script>
 </head>
Index: /FCKeditor/trunk/_test/automated/tests/fckw3crange.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/fckw3crange.html	(revision 50)
+++ /FCKeditor/trunk/_test/automated/tests/fckw3crange.html	(revision 51)
@@ -397,4 +397,38 @@
 }
 
+function test_deleteContents_Other_3()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_B') ) ;
+	
+	range.deleteContents() ;
+
+	assertEquals( '', GetTestInnerHtml( document.getElementById('_B') ) ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_B'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_B'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 0, range.endOffset ) ;
+	assertTrue( 'range.collapsed', range.collapsed ) ;
+}
+
+function test_deleteContents_Other_4()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_P') ) ;
+	
+	range.deleteContents() ;
+	
+	assertEquals( '', GetTestInnerHtml( document.getElementById('_P') ) ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_P'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_P'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 0, range.endOffset ) ;
+	assertTrue( 'range.collapsed', range.collapsed ) ;
+}
+
 // W3C DOM Range Specs - Section 2.7 - Example 1
 function test_extractContents_W3C_1()
@@ -426,5 +460,5 @@
 
 	range.setStart( document.getElementById( '_B' ).firstChild, 1 ) ;
-	range.setEnd( document.getElementById( '_B' ).nextSibling, 1 ) ;
+	range.setEnd( document.getElementById( '_B' ).nextSibling, 2 ) ;
 	
 	var docFrag = range.extractContents() ;
@@ -433,6 +467,6 @@
 	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
 
-	assertEquals( 'Extracted HTML', '<b id=_b>ome</b> ', GetTestInnerHtml( tmpDiv ) ) ;	
-	assertEquals( 'HTML after extraction', 'this is <b id=_b>s</b>text.', GetTestInnerHtml( document.getElementById( '_P' ) ) ) ;
+	assertEquals( 'Extracted HTML', '<b id=_b>ome</b> t', GetTestInnerHtml( tmpDiv ) ) ;	
+	assertEquals( 'HTML after extraction', 'this is <b id=_b>s</b>ext.', GetTestInnerHtml( document.getElementById( '_P' ) ) ) ;
 
 	assertEquals( 'range.startContainer', document.getElementById( '_P' ), range.startContainer ) ;
@@ -533,4 +567,46 @@
 }
 
+function test_extractContents_Other_3()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_B') ) ;
+	
+	var docFrag = range.extractContents() ;
+	
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+	
+	assertEquals( 'Extracted HTML', 'some', GetTestInnerHtml( tmpDiv ) ) ;	
+	assertEquals( 'HTML after extraction', '', GetTestInnerHtml( document.getElementById('_B') ) ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_B'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_B'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 0, range.endOffset ) ;
+	assertTrue( 'range.collapsed', range.collapsed ) ;
+}
+
+function test_extractContents_Other_4()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_P') ) ;
+	
+	var docFrag = range.extractContents() ;
+	
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+
+	assertEquals( 'Extracted HTML', 'this is <b id=_b>some</b> text.', GetTestInnerHtml( tmpDiv ) ) ;	
+	assertEquals( 'HTML after extraction', '', GetTestInnerHtml( document.getElementById('_P') ) ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_P'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_P'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 0, range.endOffset ) ;
+	assertTrue( 'range.collapsed', range.collapsed ) ;
+}
+
 // W3C DOM Range Specs - Section 2.7 - Example 1
 function test_cloneContents_W3C_1()
@@ -567,5 +643,5 @@
 
 	range.setStart( document.getElementById( '_B' ).firstChild, 1 ) ;
-	range.setEnd( document.getElementById( '_B' ).nextSibling, 1 ) ;
+	range.setEnd( document.getElementById( '_B' ).nextSibling, 2 ) ;
 	
 	var bodyHtml = document.body.innerHTML ;
@@ -576,5 +652,5 @@
 	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
 
-	assertEquals( 'Cloned HTML', '<b id=_b>ome</b> ', GetTestInnerHtml( tmpDiv ) ) ;	
+	assertEquals( 'Cloned HTML', '<b id=_b>ome</b> t', GetTestInnerHtml( tmpDiv ) ) ;	
 
 	// The body HTML must remain unchanged.
@@ -585,5 +661,5 @@
 	assertEquals( 'range.startOffset', 1, range.startOffset ) ;
 	assertEquals( 'range.endContainer', document.getElementById( '_B' ).nextSibling, range.endContainer ) ;
-	assertEquals( 'range.endOffset', 1, range.endOffset ) ;
+	assertEquals( 'range.endOffset', 2, range.endOffset ) ;
 	assertFalse( 'range.collapsed', range.collapsed ) ;
 }
@@ -696,4 +772,54 @@
 	assertEquals( 'range.endContainer', document.body, range.endContainer ) ;
 	assertEquals( 'range.endOffset', 2, range.endOffset ) ;
+	assertFalse( 'range.collapsed', range.collapsed ) ;
+}
+
+function test_cloneContents_Other_3()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_B') ) ;
+	
+	var bodyHtml = document.body.innerHTML ;
+
+	var docFrag = range.cloneContents() ;
+	
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+	
+	assertEquals( 'Cloned HTML', 'some', GetTestInnerHtml( tmpDiv ) ) ;	
+
+	// The body HTML must remain unchanged.
+	assertEquals( bodyHtml, document.body.innerHTML ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_B'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_B'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 1, range.endOffset ) ;
+	assertFalse( 'range.collapsed', range.collapsed ) ;
+}
+
+function test_cloneContents_Other_4()
+{
+	var range = FCKW3CRange.CreateRange( document ) ;
+
+	range.selectNodeContents( document.getElementById('_P') ) ;
+	
+	var bodyHtml = document.body.innerHTML ;
+
+	var docFrag = range.cloneContents() ;
+	
+	var tmpDiv = document.createElement( 'div' ) ;
+	if ( docFrag.AppendTo ) docFrag.AppendTo( tmpDiv ) ; else tmpDiv.appendChild( docFrag ) ;
+	
+	assertEquals( 'Cloned HTML', 'this is <b id=_b>some</b> text.', GetTestInnerHtml( tmpDiv ) ) ;	
+
+	// The body HTML must remain unchanged.
+	assertEquals( bodyHtml, document.body.innerHTML ) ;
+
+	assertEquals( 'range.startContainer', document.getElementById('_P'), range.startContainer ) ;
+	assertEquals( 'range.startOffset', 0, range.startOffset ) ;
+	assertEquals( 'range.endContainer', document.getElementById('_P'), range.endContainer ) ;
+	assertEquals( 'range.endOffset', 3, range.endOffset ) ;
 	assertFalse( 'range.collapsed', range.collapsed ) ;
 }
@@ -778,5 +904,5 @@
 //window.onload = function()
 //{
-//	test_cloneContents_W3C_1() ;
+//	test_extractContents_Other_3() ;
 //}
 
Index: /FCKeditor/trunk/_test/automated/tests/suite.html
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/suite.html	(revision 50)
+++ /FCKeditor/trunk/_test/automated/tests/suite.html	(revision 51)
@@ -15,4 +15,5 @@
 	suite.addTestPage( '../tests/fcktools.html' ) ;
 	suite.addTestPage( '../tests/fckw3crange.html' ) ;
+	suite.addTestPage( '../tests/fckdomrange.html' ) ;
 	
 	return suite ;
Index: /FCKeditor/trunk/_test/automated/tests/tests.js
===================================================================
--- /FCKeditor/trunk/_test/automated/tests/tests.js	(revision 50)
+++ /FCKeditor/trunk/_test/automated/tests/tests.js	(revision 51)
@@ -7,4 +7,4 @@
 	// quotes, uppercased and linebreaks). Transform it in something usable for
 	// the tests assertions.
-	return element.innerHTML.replace( /"/g, '' ).toLowerCase().replace( /\n|\r/g, '' )
+	return element.innerHTML.replace( /"/g, '' ).toLowerCase().replace( />\s*(\n|\r)+\s*</g, '><' ).replace( /\s*(\n|\r)+\s*/g, ' ' ).replace( /(^\s+)|(\s+$)/g, '' )
 }
Index: /FCKeditor/trunk/_test/manual/fckdomrange/test1.html
===================================================================
--- /FCKeditor/trunk/_test/manual/fckdomrange/test1.html	(revision 50)
+++ /FCKeditor/trunk/_test/manual/fckdomrange/test1.html	(revision 51)
@@ -6,8 +6,14 @@
 	<script type="text/javascript">
 
+var FCK = new Object() ;
+
 FCKScriptLoader.Load( 'FCKDomRange' ) ;
+FCKScriptLoader.Load( 'FCKDebug' ) ;
 
 	</script>
 	<script type="text/javascript">
+
+FCKConfig.Debug = true ;
+FCKConfig.BasePath = '../../../editor/' ;
 
 var oRange ;
@@ -40,5 +46,8 @@
 	var eDiv = oRange.Window.document.createElement( 'div' ) ;
 	oRange.ExtractContents().AppendTo( eDiv ) ;
+	UpdateDetails() ;
 	alert( eDiv.innerHTML ) ;
+	AutoSelect() ;
+	oRange.Window.focus() ;
 }
 
@@ -54,4 +63,5 @@
 {
 	alert( oRange.CheckEndOfBlock() ) ;
+	AutoSelect() ;
 	oRange.Window.focus() ;
 }
@@ -59,5 +69,5 @@
 function Collapse()
 {
-	oRange.Collapse() ;
+	oRange.Collapse(true) ;
 	AutoSelect() ;
 	UpdateDetails() ;
Index: /FCKeditor/trunk/_test/manual/fckdomrange/test1_inner.html
===================================================================
--- /FCKeditor/trunk/_test/manual/fckdomrange/test1_inner.html	(revision 50)
+++ /FCKeditor/trunk/_test/manual/fckdomrange/test1_inner.html	(revision 51)
@@ -19,5 +19,5 @@
 <body>
 	<h1>
-		Sample document for editor area test<img src="http://www.fckeditor.net/images/logotop.gif" alt="" />
+		Test page for FCKeditor
 	</h1>
 	<p>
@@ -55,10 +55,6 @@
 		Test procedure
 	</h2>
-	
-		This text has no block tag. It goes directly in the body. 
-		In the test we will try to recreate this document using the editor tools. To make
-		sure tables can be inserted <em>properly</em> we re-visit banana import statistics
-		from 1998.
-	
+	This text has no block tag. It should be corrected when working with the enter key
+	set to "p" or "div" tags. The "br" configuration should not make changes instead.
 	<p>
 		In the test we will try to recreate this document using the editor tools. To make
@@ -66,8 +62,11 @@
 		from 1998.
 	</p>
-		This text has no block tag. It goes directly in the body. 
-		In the test we will try to recreate this document using the editor tools. To make
-		sure tables can be inserted <em>properly</em> we re-visit banana import statistics
-		from 1998.
+	<p>
+		This paragraph has and image at the very end of its contents.<img src="http://www.fckeditor.net/images/logotop.gif"
+			alt="" />
+	</p>
+	This text has no block tag. It should be corrected when working with the enter key
+	set to "p" or "div" tags. The <strong>"br" configuration</strong> should not make
+	changes instead.
 	<p>
 		In the test we will try to recreate this document using the editor tools. To make
Index: /FCKeditor/trunk/editor/_source/classes/fckdocumentfragment_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdocumentfragment_gecko.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckdocumentfragment_gecko.js	(revision 51)
@@ -15,7 +15,12 @@
 }
 
-// Append the contents of this Document Fragment to another element.
-FCKDocumentFragment.prototype.AppendTo = function( targetNode )
+FCKDocumentFragment.prototype =
 {
-	targetNode.appendChild( this.RootNode ) ;
+	TypeName : 'FCKDocumentFragment',		// @Packager.RemoveLine
+
+	// Append the contents of this Document Fragment to another element.
+	AppendTo : function( targetNode )
+	{
+		targetNode.appendChild( this.RootNode ) ;
+	}
 }
Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 51)
@@ -12,106 +12,388 @@
 }
 
-FCKDomRange.prototype.TypeName = 'FCKDomRange' ;		// @Packager.RemoveLine
-
-FCKDomRange.prototype.CheckStartOfBlock = function()
+FCKDomRange.prototype =
 {
-	// Create a clone of the current range.
-	var oTestRange = this.Clone() ;
-	
-	// Collapse it to its start point.
-	oTestRange.Collapse( true ) ;
-	
-	// Move the start boundary to the start of the block.
-	oTestRange.SetStart( oTestRange.StartBlock || oTestRange.StartBlockLimit, 1 ) ;
-	
-	var bIsStartOfBlock = oTestRange.CheckIsEmpty() ;
-
-	oTestRange.Release() ;
-	
-	return bIsStartOfBlock ;
-}
-
-FCKDomRange.prototype.CheckEndOfBlock = function()
-{
-	var bIsEndOfBlock = false ;
-
-	// Create a clone of the current range.
-	var oTestRange = this.Clone() ;
-	
-	// Collapse it to its end point.
-	oTestRange.Collapse( false ) ;
-	
-	// Move the end boundary to the end of the block.
-	oTestRange.SetEnd( oTestRange.EndBlock || oTestRange.EndBlockLimit, 2 ) ;
-
-	var bIsEndOfBlock = oTestRange.CheckIsEmpty() ;
-
-	oTestRange.Release() ;
-	
-	return bIsEndOfBlock ;
-}
-
-FCKDomRange.prototype.Release = function( preserveWindow )
-{
-	if ( !preserveWindow )
-		this.Window = null ;
-
-	this.StartContainer = null ;
-	this.StartBlock = null ;
-	this.StartBlockLimit = null ;
-	this.EndContainer = null ;
-	this.EndBlock = null ;
-	this.EndBlockLimit = null ;
-	this._Range = null ;
-}
-
-FCKDomRange.prototype.MoveToElementStart = function( targetElement )
-{
-	this.SetStart(targetElement,1) ;
-	this.SetEnd(targetElement,1) ;
-}
-
-FCKDomRange.prototype.CreateBookmark = function()
-{
-	var oBookmark = 
-	{
-		StartId	: 'fck_dom_range_start_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000),
-		EndId	: 'fck_dom_range_end_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000)
-	} ;
-
-	var oDoc = this.Window.document ;
-	
-	var eSpan = oDoc.createElement( 'span' ) ;
-	eSpan.id = oBookmark.EndId ;
-	eSpan.innerHTML = '&nbsp;' ;	// For IE, it must have something inside, otherwise it may be removed during operations.
-
-	var oClone = this.Clone() ;
-	oClone.Collapse( false ) ;
-	oClone.InsertNode( eSpan ) ;
-	
-	eSpan = oDoc.createElement( 'span' ) ;
-	eSpan.id = oBookmark.StartId ;
-	eSpan.innerHTML = '&nbsp;' ;	// For IE, it must have something inside, otherwise it may be removed during operations.
-
-	var oClone = this.Clone() ;
-	oClone.Collapse( true ) ;
-	oClone.InsertNode( eSpan ) ;
-	
-	return oBookmark ;
-}
-
-FCKDomRange.prototype.MoveToBookmark = function( bookmark, preserveBookmark )
-{
-	var oDoc = this.Window.document ;
-	var eStartSpan	=  oDoc.getElementById( bookmark.StartId ) ;
-	var eEndSpan	=  oDoc.getElementById( bookmark.EndId ) ;
-
-	this.SetStart( eStartSpan, 4 ) ;
-	this.SetEnd( eEndSpan, 3 ) ;
-	
-	if ( !preserveBookmark )
-	{
-		FCKDomTools.RemoveNode( eStartSpan ) ;
-		FCKDomTools.RemoveNode( eEndSpan ) ;
+	TypeName : 'FCKDomRange',		// @Packager.RemoveLine
+
+	_UpdateElementInfo : function()
+	{
+		if ( !this._Range )
+			this.Release( true ) ;
+		else
+		{
+			var eStart	= this._Range.startContainer ;
+			var eEnd	= this._Range.endContainer ;
+			
+			var oElementPath = new FCKElementPath( eStart ) ;
+			this.StartContainer		= oElementPath.LastElement ;
+			this.StartBlock			= oElementPath.Block ;
+			this.StartBlockLimit	= oElementPath.BlockLimit ;
+
+			if ( eStart != eEnd )
+				oElementPath = new FCKElementPath( eEnd ) ;
+			this.EndContainer		= oElementPath.LastElement ;			
+			this.EndBlock			= oElementPath.Block ;
+			this.EndBlockLimit		= oElementPath.BlockLimit ;
+		}
+	},
+
+	CreateRange : function()
+	{
+		return new FCKW3CRange( this.Window.document ) ;
+	},
+
+	DeleteContents : function()
+	{
+		if ( this._Range )
+		{
+			this._Range.deleteContents() ;
+			this._UpdateElementInfo() ;
+		}
+	},
+
+	ExtractContents : function()
+	{
+		if ( this._Range )
+		{
+			var docFrag = this._Range.extractContents() ;
+			this._UpdateElementInfo() ;
+			return docFrag ;
+		}
+	},
+
+	CheckIsCollapsed : function()
+	{
+		if ( this._Range )
+			return this._Range.collapsed ;
+	},
+
+	Collapse : function( toStart )
+	{
+		if ( this._Range )
+			this._Range.collapse( toStart ) ;
+		
+		this._UpdateElementInfo() ;
+	},
+
+	Clone : function()
+	{
+		var oClone = FCKTools.CloneObject( this ) ;
+
+		if ( this._Range )
+			oClone._Range = this._Range.cloneRange() ;
+		
+		return oClone ;
+	},
+
+	MoveToNodeContents : function( targetNode )
+	{
+		if ( !this._Range )
+			this._Range = this.CreateRange() ;
+
+		this._Range.selectNodeContents( targetNode ) ;
+
+		this._UpdateElementInfo() ;
+	},
+
+	MoveToElementStart : function( targetElement )
+	{
+		this.SetStart(targetElement,1) ;
+		this.SetEnd(targetElement,1) ;
+	},
+
+	InsertNode : function( node )
+	{
+		if ( this._Range )
+			this._Range.insertNode( node ) ;
+	},
+
+	CheckIsEmpty : function()
+	{
+		if ( this.CheckIsCollapsed() )
+			return true ;
+
+		// Inserts the contents of the range in a div tag.
+		var eToolDiv = this.Window.document.createElement( 'div' ) ;
+		this._Range.cloneContents().AppendTo( eToolDiv ) ;
+
+		// There must not be &nbsp; in the range, only "pure" spaces.
+		return (/^\s*$/).test( eToolDiv.innerHTML ) ;
+	},
+
+	CheckStartOfBlock : function()
+	{
+		// Create a clone of the current range.
+		var oTestRange = this.Clone() ;
+		
+		// Collapse it to its start point.
+		oTestRange.Collapse( true ) ;
+		
+		// Move the start boundary to the start of the block.
+		oTestRange.SetStart( oTestRange.StartBlock || oTestRange.StartBlockLimit, 1 ) ;
+		
+		var bIsStartOfBlock = oTestRange.CheckIsEmpty() ;
+
+		oTestRange.Release() ;
+		
+		return bIsStartOfBlock ;
+	},
+
+	CheckEndOfBlock : function()
+	{
+		var bIsEndOfBlock = false ;
+
+		// Create a clone of the current range.
+		var oTestRange = this.Clone() ;
+		
+		// Collapse it to its end point.
+		oTestRange.Collapse( false ) ;
+		
+		// Move the end boundary to the end of the block.
+		oTestRange.SetEnd( oTestRange.EndBlock || oTestRange.EndBlockLimit, 2 ) ;
+
+		var bIsEndOfBlock = oTestRange.CheckIsEmpty() ;
+
+		oTestRange.Release() ;
+		
+		return bIsEndOfBlock ;
+	},
+
+	CreateBookmark : function()
+	{
+		// Create the bookmark info (random IDs).
+		var oBookmark = 
+		{
+			StartId	: 'fck_dom_range_start_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000),
+			EndId	: 'fck_dom_range_end_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000)
+		} ;
+
+		var oDoc = this.Window.document ;
+		var eSpan ;
+		var oClone ;
+
+		// For collapsed ranges, add just the start marker.
+		if ( !this.CheckIsCollapsed() )
+		{
+			eSpan = oDoc.createElement( 'span' ) ;
+			eSpan.id = oBookmark.EndId ;
+			eSpan.innerHTML = '&nbsp;' ;	// For IE, it must have something inside, otherwise it may be removed during operations.
+
+			oClone = this.Clone() ;
+			oClone.Collapse( false ) ;
+			oClone.InsertNode( eSpan ) ;
+		}
+		
+		eSpan = oDoc.createElement( 'span' ) ;
+		eSpan.id = oBookmark.StartId ;
+		eSpan.innerHTML = '&nbsp;' ;	// For IE, it must have something inside, otherwise it may be removed during operations.
+
+		oClone = this.Clone() ;
+		oClone.Collapse( true ) ;
+		oClone.InsertNode( eSpan ) ;
+
+		return oBookmark ;
+	},
+
+	MoveToBookmark : function( bookmark, preserveBookmark )
+	{
+		var oDoc = this.Window.document ;
+		
+		var eStartSpan	=  oDoc.getElementById( bookmark.StartId ) ;
+		var eEndSpan	=  oDoc.getElementById( bookmark.EndId ) ;
+
+		this.SetStart( eStartSpan, 3 ) ;
+		
+		if ( !preserveBookmark )
+			FCKDomTools.RemoveNode( eStartSpan ) ;
+
+		// If collapsed, the start span will not be available.
+		if ( eEndSpan )
+		{
+			this.SetEnd( eEndSpan, 3 ) ;
+			
+			if ( !preserveBookmark )
+				FCKDomTools.RemoveNode( eEndSpan ) ;
+		}
+		else
+			this.Collapse( true ) ;
+	},
+
+	/*
+	 * Moves the position of the start boundary of the range to a specific position
+	 * relatively to a element.
+	 *		@position:
+	 *			1 = After Start		<target>^contents</target>
+	 *			2 = Before End		<target>contents^</target>
+	 *			3 = Before Start	^<target>contents</target>
+	 *			4 = After End		<target>contents</target>^
+	 */
+	SetStart : function( targetElement, position )
+	{
+		var oRange = this._Range ;
+		if ( !oRange )
+			oRange = this._Range = this.CreateRange() ;
+
+		switch( position )
+		{
+			case 1 :		// After Start		<target>^contents</target>	
+				oRange.setStart( targetElement, 0 ) ;
+				break ;
+
+			case 2 :		// Before End		<target>contents^</target>
+				oRange.setStart( targetElement, targetElement.childNodes.length ) ;
+				break ;
+
+			case 3 :		// Before Start		^<target>contents</target>
+				oRange.setStartBefore( targetElement ) ;
+				break ;
+			
+			case 4 :		// After End		<target>contents</target>^
+				oRange.setStartAfter( targetElement ) ;
+		}
+		this._UpdateElementInfo() ;
+	},
+
+	/*
+	 * Moves the position of the start boundary of the range to a specific position
+	 * relatively to a element.
+	 *		@position:
+	 *			1 = After Start		<target>^contents</target>
+	 *			2 = Before End		<target>contents^</target>
+	 *			3 = Before Start	^<target>contents</target>
+	 *			4 = After End		<target>contents</target>^
+	 */
+	SetEnd : function( targetElement, position )
+	{
+		var oRange = this._Range ;
+		if ( !oRange )
+			oRange = this._Range = this.CreateRange() ;
+		
+		switch( position )
+		{
+			case 1 :		// After Start		<target>^contents</target>
+				oRange.setEnd( targetElement, 0 ) ;
+				break ;
+
+			case 2 :		// Before End		<target>contents^</target>
+				oRange.setEnd( targetElement, targetElement.childNodes.length ) ;
+				break ;
+
+			case 3 :		// Before Start		^<target>contents</target>
+				oRange.setEndBefore( targetElement ) ;
+				break ;
+			
+			case 4 :		// After End		<target>contents</target>^
+				oRange.setEndAfter( targetElement ) ;
+		}
+		this._UpdateElementInfo() ;
+	},
+
+	Expand : function( unit )
+	{
+		switch ( unit )
+		{
+			case 'block_contents' :
+				if ( this.StartBlock )
+					this.SetStart( this.StartBlock, 1 ) ;
+				else
+				{
+					// Get the start node for the current range.
+					var oNode = this._Range.startContainer ;
+					
+					// If it is an element, get the current child node for the range (in the offset).
+					// If the offset node is not available, the the first one.
+					if ( oNode.nodeType == 1 )
+					{
+						if ( !( oNode = oNode.childNodes[ this._Range.startOffset ] ) )
+							oNode = oNode.firstChild ;
+					}
+					
+					// Not able to defined the current position.
+					if ( !oNode )
+						return ;
+					
+					// We must look for the left boundary, relative to the range
+					// start, which is limited by a block element.
+					while ( true )
+					{
+						var oSibling = oNode.previousSibling ;
+						
+						if ( !oSibling )
+						{
+							// Continue if we are not yet in the block limit (inside a <b>, for example).
+							if ( oNode.parentNode != this.StartBlockLimit )
+								oNode = oNode.parentNode ;
+							else
+								break ;
+						}
+						else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
+						{
+							// Continue if the sibling is not a block tag.
+							oNode = oSibling ;
+						}
+						else
+							break ;
+					}
+					
+					this._Range.setStartBefore( oNode ) ;
+				}
+				
+				if ( this.EndBlock )
+					this.SetEnd( this.EndBlock, 2 ) ;
+				else
+				{
+					var oNode = this._Range.endContainer ;
+					if ( oNode.nodeType == 1 )
+						oNode = oNode.childNodes[ this._Range.endOffset ] || oNode.lastChild ;
+					
+					if ( !oNode )
+						return ;
+					
+					// We must look for the right boundary, relative to the range
+					// end, which is limited by a block element.
+					while ( true )
+					{
+						var oSibling = oNode.nextSibling ;
+						
+						if ( !oSibling )
+						{
+							// Continue if we are not yet in the block limit (inide a <b>, for example).
+							if ( oNode.parentNode != this.EndBlockLimit )
+								oNode = oNode.parentNode ;
+							else
+								break ;
+						}
+						else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
+						{
+							// Continue if the sibling is not a block tag.
+							oNode = oSibling ;
+						}
+						else
+							break ;
+					}
+					
+					this._Range.setEndAfter( oNode ) ;
+				}
+
+				this._UpdateElementInfo() ;
+			break ;											// @Packager.Remove.Start
+			
+			default :
+				throw( 'Invalid unit "' + unit + '"' ) ;	// @Packager.Remove.End
+		}
+	},
+
+	Release : function( preserveWindow )
+	{
+		if ( !preserveWindow )
+			this.Window = null ;
+
+		this.StartContainer = null ;
+		this.StartBlock = null ;
+		this.StartBlockLimit = null ;
+		this.EndContainer = null ;
+		this.EndBlock = null ;
+		this.EndBlockLimit = null ;
+		this._Range = null ;
 	}
-}
+} ;
Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange_gecko.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange_gecko.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange_gecko.js	(revision 51)
@@ -8,26 +8,4 @@
 */
 
-FCKDomRange.prototype._UpdateElementInfo = function()
-{
-	if ( !this._Range )
-		this.Release( true ) ;
-	else
-	{
-		var eStart	= this._Range.startContainer ;
-		var eEnd	= this._Range.endContainer ;
-		
-		var oElementPath = new FCKElementPath( eStart ) ;
-		this.StartContainer		= oElementPath.LastElement ;
-		this.StartBlock			= oElementPath.Block ;
-		this.StartBlockLimit	= oElementPath.BlockLimit ;
-
-		if ( eStart != eEnd )
-			oElementPath = new FCKElementPath( eEnd ) ;
-		this.EndContainer		= oElementPath.LastElement ;			
-		this.EndBlock			= oElementPath.Block ;
-		this.EndBlockLimit		= oElementPath.BlockLimit ;
-	}
-}
-
 FCKDomRange.prototype.MoveToSelection = function()
 {
@@ -38,298 +16,40 @@
 	if ( oSel.rangeCount == 1 )
 	{
-		// Let's work with the clone, otherwise changes in the range could
-		// affect the current selection.
-		this._Range = oSel.getRangeAt(0).cloneRange() ;
+		this._Range = FCKW3CRange.CreateFromRange( this.Window.document, oSel.getRangeAt(0) ) ;
 		this._UpdateElementInfo() ;
 	}
 }
 
-FCKDomRange.prototype.CheckIsEmpty = function()
-{
-	var bIsEmpty = false ;
-
-	// Check if the range is empty or contains only spaces.
-	var sTestRangeContents = this._Range.toString() ;
-	if ( sTestRangeContents.Trim().length == 0 )
-	{
-		if ( !( bIsEmpty = ( sTestRangeContents.length == 0 ) ) )
-		{
-			// Inserts the contents of the range in a span tag.
-			var eToolSpan = this.Window.document.createElement( 'span' ) ;
-			eToolSpan.appendChild( this._Range.cloneContents() ) ;
-			
-			// There must not be &nbsp; in the range, only "pure" spaces.
-			if ( !(/(&nbsp;)|(<(IMG|OBJECT|EMBED|INPUT|SELECT|TEXTAREA))/i).test( eToolSpan.innerHTML ) )
-				bIsEmpty = true ;
-		}
-	}
-	// We'll be at the end of the block, if the range is empty or filled with spaces.
-	return bIsEmpty ;
-}
-
-FCKDomRange.prototype.DeleteContents = function()
-{
-	if ( this._Range )
-		this._Range.deleteContents() ;
-}
-
-FCKDomRange.prototype.ExtractContents = function()
-{
-	if ( this._Range )
-		return new FCKDocumentFragment( null, this._Range.extractContents() ) ;
-}
-
-FCKDomRange.prototype.CheckIsCollapsed = function()
-{
-	if ( this._Range )
-		return this._Range.collapsed ;
-}
-
-FCKDomRange.prototype.Collapse = function( toStart )
-{
-	if ( this._Range )
-		this._Range.collapse( toStart ) ;
-	
-	this._UpdateElementInfo() ;
-}
-
-FCKDomRange.prototype.Clone = function()
-{
-	var oClone = FCKTools.CloneObject( this ) ;
-
-	if ( oClone._Range )
-		oClone._Range = oClone._Range.cloneRange() ;
-	
-	return oClone ;
-}
-
-FCKDomRange.prototype.MoveToNodeContents = function( targetNode )
-{
-	if ( this._Range )
-		this._Range.selectNodeContents( targetNode ) ;
-}
-
 FCKDomRange.prototype.Select = function()
 {
-	if ( this._Range )
+	var oRange = this._Range ;
+	if ( oRange )
 	{
+		var oDocRange = this.Window.document.createRange() ;
+		oDocRange.setStart( oRange.startContainer, oRange.startOffset ) ;
+		
+		try
+		{
+			oDocRange.setEnd( oRange.endContainer, oRange.endOffset ) ;
+		}
+		catch ( e )
+		{
+			// There is a bug in Firefox implementation (it would be too easy
+			// otherwhise). The new start can't be after the end (W3C says it can).
+			// So, let's create a new range and collapse it to the desired point.
+			if ( e.toString().Contains( 'NS_ERROR_ILLEGAL_VALUE' ) )
+			{
+				oRange.collapse( true ) ;
+				oDocRange.setEnd( oRange.endContainer, oRange.endOffset ) ;
+			}
+			else
+				throw( e ) ;
+		}
+
 		var oSel = this.Window.getSelection() ;
 		oSel.removeAllRanges() ;
 		
 		// We must add a clone otherwise Firefox will have rendering issues.
-		oSel.addRange( this._Range.cloneRange() ) ;
+		oSel.addRange( oDocRange ) ;
 	}
 }
-
-FCKDomRange.prototype.InsertNode = function( node )
-{
-	if ( this._Range )
-		this._Range.insertNode( node ) ;
-}
-
-/*
- * Moves the position of the start boundary of the range to a specific position
- * relatively to a element.
- *		@position:
- *			1 = After Start		<target>^contents</target>
- *			2 = Before End		<target>contents^</target>
- *			3 = Before Start	^<target>contents</target>
- *			4 = After End		<target>contents</target>^
- */
-FCKDomRange.prototype.SetStart = function( targetElement, position )
-{
-	var oRange = this._Range ;
-	if ( !oRange )
-		oRange = this._Range = this.Window.document.createRange() ;
-
-	try
-	{
-		switch( position )
-		{
-			case 1 :		// After Start		<target>^contents</target>	
-				oRange.setStart( targetElement, 0 ) ;
-				break ;
-
-			case 2 :		// Before End		<target>contents^</target>
-				if ( targetElement.lastChild )
-					oRange.setStartAfter( targetElement.lastChild ) ;
-				else
-					oRange.setStart( targetElement, 0 ) ;
-				break ;
-
-			case 3 :		// Before Start		^<target>contents</target>
-				oRange.setStartBefore( targetElement ) ;
-				break ;
-			
-			case 4 :		// After End		<target>contents</target>^
-				oRange.setStartAfter( targetElement ) ;
-		}
-		this._UpdateElementInfo() ;
-	}
-	catch ( e )
-	{
-		// There is a bug in Firefox implementation (it would be too easy
-		// otherwhise). The new start can't be after the end (W3C says it can).
-		// So, let's create a new range and collapse it to the desired point.
-		if ( e.toString().Contains( 'NS_ERROR_ILLEGAL_VALUE' ) )
-		{
-			this.Release( true ) ;
-			this._Range = this.Window.document.createRange() ;
-			this.SetStart( targetElement, position ) ;
-		}
-		else
-			throw( e ) ;
-	}
-}
-
-/*
- * Moves the position of the start boundary of the range to a specific position
- * relatively to a element.
- *		@position:
- *			1 = After Start		<target>^contents</target>
- *			2 = Before End		<target>contents^</target>
- *			3 = Before Start	^<target>contents</target>
- *			4 = After End		<target>contents</target>^
- */
-FCKDomRange.prototype.SetEnd = function( targetElement, position )
-{
-	var oRange = this._Range ;
-	if ( !oRange )
-		oRange = this._Range = this.Window.document.createRange() ;
-	
-	try
-	{
-		switch( position )
-		{
-			case 1 :		// After Start		<target>^contents</target>
-				oRange.setEnd( targetElement, 0 ) ;
-				break ;
-
-			case 2 :		// Before End		<target>contents^</target>
-				if ( targetElement.lastChild )
-					oRange.setEndAfter( targetElement.lastChild ) ;
-				else
-					oRange.setEnd( targetElement, 0 ) ;
-				break ;
-
-			case 3 :		// Before Start		^<target>contents</target>
-				oRange.setEndBefore( targetElement ) ;
-				break ;
-			
-			case 4 :		// After End		<target>contents</target>^
-				oRange.setEndAfter( targetElement ) ;
-		}
-		this._UpdateElementInfo() ;
-	}
-	catch ( e )
-	{
-		if ( e.toString().Contains( 'NS_ERROR_ILLEGAL_VALUE' ) )
-		{
-			// There is a bug in Firefox implementation (it would be too easy
-			// otherwhise). The new start can't be after the end (W3C says it can).
-			// So, let's create a new range and collapse it to the desired point.
-			this.Release( true ) ;
-			this._Range = this.Window.document.createRange() ;
-			this.SetStart( targetElement, position ) ;
-		}
-		else
-			throw( e ) ;
-	}
-}
-
-FCKDomRange.prototype.Expand = function( unit )
-{
-	switch ( unit )
-	{
-		case 'block_contents' :
-			if ( this.StartBlock )
-				this.SetStart( this.StartBlock, 1 ) ;
-			else
-			{
-				// Get the start node for the current range.
-				var oNode = this._Range.startContainer ;
-				
-				// If it is an element, get the current child node for the range (in the offset).
-				// If the offset node is not available, the the first one.
-				if ( oNode.nodeType == 1 )
-				{
-					if ( !( oNode = oNode.childNodes[ this._Range.startOffset ] ) )
-						oNode = oNode.firstChild ;
-				}
-				
-				// Not able to defined the current position.
-				if ( !oNode )
-					return ;
-				
-				// We must look for the left boundary, relative to the range
-				// start, which is limited by a block element.
-				while ( true )
-				{
-					var oSibling = oNode.previousSibling ;
-					
-					if ( !oSibling )
-					{
-						// Continue if we are not yet in the block limit (inside a <b>, for example).
-						if ( oNode.parentNode != this.StartBlockLimit )
-							oNode = oNode.parentNode ;
-						else
-							break ;
-					}
-					else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
-					{
-						// Continue if the sibling is not a block tag.
-						oNode = oSibling ;
-					}
-					else
-						break ;
-				}
-				
-				this._Range.setStartBefore( oNode ) ;
-			}
-			
-			if ( this.EndBlock )
-				this.SetEnd( this.EndBlock, 2 ) ;
-			else
-			{
-				var oNode = this._Range.endContainer ;
-				if ( oNode.nodeType == 1 )
-				{
-					if ( !( oNode = oNode.childNodes[ this._Range.endOffset ] ) )
-						oNode = oNode.lastChild ;
-				}
-				
-				if ( !oNode )
-					return ;
-				
-				// We must look for the right boundary, relative to the range
-				// end, which is limited by a block element.
-				while ( true )
-				{
-					var oSibling = oNode.nextSibling ;
-					
-					if ( !oSibling )
-					{
-						// Continue if we are not yet in the block limit (inide a <b>, for example).
-						if ( oNode.parentNode != this.EndBlockLimit )
-							oNode = oNode.parentNode ;
-						else
-							break ;
-					}
-					else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
-					{
-						// Continue if the sibling is not a block tag.
-						oNode = oSibling ;
-					}
-					else
-						break ;
-				}
-				
-				this._Range.setEndAfter( oNode ) ;
-			}
-		
-		break ;											// @Packager.Remove.Start
-		
-		default :
-			throw( 'Invalid unit "' + unit + '"' ) ;	// @Packager.Remove.End
-	}
-}
Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange_ie.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange_ie.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange_ie.js	(revision 51)
@@ -8,110 +8,26 @@
 */
 
-FCKDomRange.prototype._UpdateElementInfo = function()
-{
-	if ( !this._Range )
-		this.Release( true ) ;
-	else
-	{
-		// Get a range for the start boundary.
-		var oStartRange = this._Range.duplicate() ;
-		oStartRange.collapse( true ) ;
-		
-		// Get a range for the end boundary.
-		var oEndRange = this._Range.duplicate() ;
-		oEndRange.collapse( false ) ;
-		
-		var eStart	= oStartRange.parentElement() ;
-		var eEnd	= oEndRange.parentElement() ;
-		
-		var oElementPath = new FCKElementPath( eStart ) ;
-		this.StartContainer		= oElementPath.LastElement ;
-		this.StartBlock			= oElementPath.Block ;
-		this.StartBlockLimit	= oElementPath.BlockLimit ;
-
-		if ( eStart != eEnd )
-			oElementPath = new FCKElementPath( eEnd ) ;
-		this.EndContainer		= oElementPath.LastElement ;			
-		this.EndBlock			= oElementPath.Block ;
-		this.EndBlockLimit		= oElementPath.BlockLimit ;
-	}
-}
-
 FCKDomRange.prototype.MoveToSelection = function()
 {
 	this.Release( true ) ;
 
-	var oSel = this.Window.document.selection  ;
+	this._Range = new FCKW3CRange( this.Window.document ) ;
+
+	var oSel = this.Window.document.selection ;
 	
 	if ( oSel.type != 'Control' )
 	{
-		this._Range = oSel.createRange() ;
+		// Set the start boundary.
+		eMarker = this._GetSelectionMarkerTag( true ) ;
+		this._Range.setStart( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ;
+		eMarker.parentNode.removeChild( eMarker ) ;
+
+		// Set the end boundary.
+		var eMarker = this._GetSelectionMarkerTag( false ) ;
+		this._Range.setEnd( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ;
+		eMarker.parentNode.removeChild( eMarker ) ;
+		
 		this._UpdateElementInfo() ;
 	}
-}
-
-FCKDomRange.prototype.CheckIsEmpty = function()
-{
-	var bIsEmpty = false ;
-
-	// Check if the range is empty or contains only spaces.
-	var sTestRangeContents = this._Range.text ;
-	if ( sTestRangeContents.Trim().length == 0 )
-	{
-		sTestRangeContents = this._Range.htmlText ;
-		if ( !( bIsEmpty = ( sTestRangeContents == 0 ) ) )
-		{
-			// There must not be &nbsp; in the range, only "pure" spaces.
-			if ( !(/(&nbsp;)|(<(IMG|OBJECT|EMBED|INPUT|SELECT|TEXTAREA))/i).test( sTestRangeContents ) )
-				bIsEmpty = true ;
-		}
-	}
-	// We'll be at the end of the block, if the range is empty or filled with spaces.
-	return bIsEmpty ;
-}
-
-FCKDomRange.prototype.DeleteContents = function()
-{
-	if ( this._Range )
-		this._Range.pasteHTML( '' ) ;
-}
-
-FCKDomRange.prototype.ExtractContents = function()
-{
-	if ( this._Range )
-	{
-		var oDocFrag = new FCKDocumentFragment( this.Window.document ) ;
-		oDocFrag.AppendHtml( this._Range.htmlText ) ;
-		this.DeleteContents() ;
-		return oDocFrag ;
-	}
-}
-
-FCKDomRange.prototype.CheckIsCollapsed = function()
-{
-	if ( this._Range )
-		return ( this._Range.compareEndPoints( 'StartToEnd', this._Range ) == 0 ) ;
-}
-
-FCKDomRange.prototype.Collapse = function( toStart )
-{
-	if ( this._Range )
-		this._Range.collapse( toStart ) ;
-}
-
-FCKDomRange.prototype.Clone = function()
-{
-	var oClone = FCKTools.CloneObject( this ) ;
-
-	if ( oClone._Range )
-		oClone._Range = oClone._Range.duplicate() ;
-	
-	return oClone ;
-}
-
-FCKDomRange.prototype.MoveToNodeContents = function( targetNode )
-{
-	if ( this._Range )
-		this._Range.moveToElementText( targetNode ) ;
 }
 
@@ -120,34 +36,38 @@
 	if ( this._Range )
 	{
-		// TODO : Check the following
-		if ( this.CheckIsCollapsed() && this.StartBlock && this.StartBlock.innerHTML.length == 0 )
-		{
-			this._Range.pasteHTML( '&nbsp;' ) ;
-			this._Range.select() ;
-		}
-		else
-			this._Range.select() ;
+		// Create marker tags for the start and end boundaries.
+		var eStartMarker	= this._GetRangeMarkerTag( true ) ;
+		var eEndMarker		= this._GetRangeMarkerTag( false ) ;
+
+		// Create the main range which will be used for the selection.
+		var oIERange = this.Window.document.body.createTextRange() ;
+		
+		// Position the range at the start boundary.
+		oIERange.moveToElementText( eStartMarker ) ;
+
+		// Create a tool range for the end.
+		var oIERangeEnd = this.Window.document.body.createTextRange() ;
+
+		// Position the tool range at the end.
+		oIERangeEnd.moveToElementText( eEndMarker ) ;
+		
+		// Move the end boundary of the main range to match the tool range.
+		oIERange.setEndPoint( 'EndToEnd', oIERangeEnd ) ;
+		
+		// Select the range.
+		oIERange.select() ;
+		
+		// Remove the markers (reset the position, because of the changes in the DOM tree).
+		this._Range.setStartBefore( eStartMarker ) ;
+		eStartMarker.parentNode.removeChild( eStartMarker ) ;
+		this._Range.setEndBefore( eEndMarker ) ;
+		eEndMarker.parentNode.removeChild( eEndMarker ) ;
 	}
 }
 
-FCKDomRange.prototype.InsertNode = function( node )
-{
-	if ( this._Range )
-	{
-		// Create a marker element in the start position of teh current range.
-		var eMarker = this.InsertMarkerTag( true ) ;
-		
-		// Insert the node.
-		FCKDomTools.InsertAfterNode( eMarker, node ) ;
-		
-		// Remove the marker.
-		eMarker.parentNode.removeChild( eMarker ) ;
-	}
-}
-
-FCKDomRange.prototype.InsertMarkerTag = function( toStart )
+FCKDomRange.prototype._GetSelectionMarkerTag = function( toStart )
 {
 	// Get a range for the start boundary.
-	var oRange = this._Range.duplicate() ;
+	var oRange = this.Window.document.selection.createRange() ;
 	oRange.collapse( toStart === true ) ;
 	
@@ -158,283 +78,20 @@
 }
 
-/*
- * Moves the position of the start boundary of the range to a specific position
- * relatively to a element.
- *		@position:
- *			1 = After Start		<target>^contents</target>
- *			2 = Before End		<target>contents^</target>
- *			3 = Before Start	^<target>contents</target>
- *			4 = After End		<target>contents</target>^
- */
-FCKDomRange.prototype.SetStart = function( targetElement, position )
+FCKDomRange.prototype._GetRangeMarkerTag = function( toStart )
 {
+	// Get a range for the start boundary.
 	var oRange = this._Range ;
-	if ( !oRange )
+	
+	// insertNode() will add the node at the beginning of the Range, updating
+	// the endOffset if necessary. So, we can work with the current range in this case.
+	if ( !toStart )
 	{
-		oRange = this._Range = this.Window.document.body.createTextRange() ;
-		oRange.collapse( true ) ;
+		oRange = oRange.cloneRange() ;
+		oRange.collapse( toStart === true ) ;
 	}
 	
-	var eTmpSpan = this.Window.document.createElement( 'span' ) ;
-	eTmpSpan.id = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ; 
-	eTmpSpan.innerHTML = '&nbsp;' ;
-
-	switch( position )
-	{
-		case 1 :		// After Start		<target>^contents</target>
-			targetElement.insertBefore( eTmpSpan, targetElement.firstChild ) ;
-		
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( false ) ;
-			
-			if ( oRange.compareEndPoints( 'EndToStart', oTargetRange ) == -1 )
-				oRange.setEndPoint( 'EndToStart', oTargetRange ) ;
-
-			oRange.setEndPoint( 'StartToStart', oTargetRange ) ;
-			break ;
-
-		case 2 :		// Before End		<target>contents^</target>
-			targetElement.appendChild( eTmpSpan ) ;
-			
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( true ) ;
-			
-			if ( oRange.compareEndPoints( 'EndToEnd', oTargetRange ) == -1 )
-				oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-			break ;
-
-		case 3 :		// Before Start		^<target>contents</target>
-			targetElement.parentNode.insertBefore( eTmpSpan, targetElement ) ;
-			
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( true ) ;
-			
-			if ( oRange.compareEndPoints( 'EndToStart', oTargetRange ) == -1 )
-				oRange.setEndPoint( 'EndToStart', oTargetRange ) ;
-
-			oRange.setEndPoint( 'StartToStart', oTargetRange ) ;
-			break ;
-		
-		case 4 :		// After End		<target>contents</target>^
-			FCKDomTools.InsertAfterNode( targetElement, eTmpSpan ) ;
-
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( targetElement ) ;
-			oTargetRange.collapse( false ) ;
-			
-			if ( oRange.compareEndPoints( 'EndToEnd', oTargetRange ) == -1 )
-				oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-	}
+	var eSpan = this.Window.document.createElement( 'span' ) ;
+	oRange.insertNode( eSpan ) ;
 	
-	if ( eTmpSpan.parentNode )
-		eTmpSpan.parentNode.removeChild( eTmpSpan ) ;
-
-	this._UpdateElementInfo() ;
+	return eSpan ;
 }
-
-/*
- * Moves the position of the start boundary of the range to a specific position
- * relatively to a element.
- *		@position:
- *			1 = After Start		<target>^contents</target>
- *			2 = Before End		<target>contents^</target>
- *			3 = Before Start	^<target>contents</target>
- *			4 = After End		<target>contents</target>^
- */
-FCKDomRange.prototype.SetEnd = function( targetElement, position )
-{
-var oRange = this._Range ;
-	if ( !oRange )
-	{
-		oRange = this._Range = this.Window.document.body.createTextRange() ;
-		oRange.collapse( true ) ;
-	}
-	
-	var eTmpSpan = this.Window.document.createElement( 'span' ) ;
-	eTmpSpan.id = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ; 
-	eTmpSpan.innerHTML = '&nbsp;' ;
-
-	switch( position )
-	{
-		case 1 :		// After Start		<target>^contents</target>
-			targetElement.insertBefore( eTmpSpan, targetElement.firstChild ) ;
-		
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( true ) ;
-			
-			if ( oRange.compareEndPoints( 'StartToEnd', oTargetRange ) == 1 )
-				oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-			break ;
-
-		case 2 :		// Before End		<target>contents^</target>
-			targetElement.appendChild( eTmpSpan ) ;
-			
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( false ) ;
-
-			if ( oRange.compareEndPoints( 'StartToEnd', oTargetRange ) == 1 )
-				oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-			break ;
-
-		case 3 :		// Before Start		^<target>contents</target>
-			targetElement.parentNode.insertBefore( eTmpSpan, targetElement ) ;
-			
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( eTmpSpan ) ;
-			oTargetRange.collapse( false ) ;
-			
-			if ( oRange.compareEndPoints( 'StartToEnd', oTargetRange ) == 1 )
-				oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-			break ;
-		
-		case 4 :		// After End		<target>contents</target>^
-			FCKDomTools.InsertAfterNode( targetElement, eTmpSpan ) ;
-
-			// Create a range for the element text.
-			var oTargetRange = this.Window.document.body.createTextRange() ;
-			oTargetRange.moveToElementText( targetElement ) ;
-			oTargetRange.collapse( true ) ;
-			
-			if ( oRange.compareEndPoints( 'StartToEnd', oTargetRange ) == 1 )
-				oRange.setEndPoint( 'StartToEnd', oTargetRange ) ;
-
-			oRange.setEndPoint( 'EndToEnd', oTargetRange ) ;
-	}
-	
-	if ( eTmpSpan.parentNode )
-		eTmpSpan.parentNode.removeChild( eTmpSpan ) ;
-
-	this._UpdateElementInfo() ;
-}
-
-//FCKDomRange.prototype.CreateBookmark = function()
-//{
-//	if ( this._Range )
-//		return this._Range.getBookmark() ;
-//}
-
-//FCKDomRange.prototype.MoveToBookmark = function( bookmark )
-//{
-//	if ( !this._Range )
-//		this._Range = this.Window.document.body.createTextRange() ;
-
-//	this._Range.moveToBookmark( bookmark ) ;
-//}
-
-FCKDomRange.prototype.Expand = function( unit )
-{
-	switch ( unit )
-	{
-		case 'block_contents' :
-			if ( this.StartBlock )
-				this.SetStart( this.StartBlock, 1 ) ;
-			else
-			{
-				// Create a marker element in the start position of the current range.
-				var eMarker = this.InsertMarkerTag( true ) ;
-				var oNode = eMarker ;
-
-				// We must look for the left boundary, relative to the range
-				// start, which is limited by a block element.
-				while ( true )
-				{
-					var oSibling = oNode.previousSibling ;
-					
-					if ( !oSibling )
-					{
-						// Continue if we are not yet in the block limit (inside a <b>, for example).
-						if ( oNode.parentNode != this.StartBlockLimit )
-							oNode = oNode.parentNode ;
-						else
-							break ;
-					}
-					else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
-					{
-						// Continue if the sibling is not a block tag.
-						oNode = oSibling ;
-					}
-					else
-						break ;
-				}
-				
-				// Move the marker right before the resulting node.
-				if ( oNode != eMarker )
-					oNode.parentNode.insertBefore( eMarker.parentNode.removeChild( eMarker ), oNode ) ;
-
-				// Move the range start to the marker.
-				this.SetStart( eMarker, 4 ) ;
-				
-				// Remove the marker definitively.
-				eMarker.parentNode.removeChild( eMarker ) ;
-			}
-
-			if ( this.EndBlock )
-				this.SetEnd( this.EndBlock, 2 ) ;
-			else
-			{
-				// Create a marker element in the end position of the current range.
-				var eMarker = this.InsertMarkerTag( false ) ;
-				var oNode = eMarker ;
-
-				// We must look for the right boundary, relative to the range
-				// end, which is limited by a block element.
-				while ( true )
-				{
-					var oSibling = oNode.nextSibling ;
-					
-					if ( !oSibling )
-					{
-						// Continue if we are not yet in the block limit (inide a <b>, for example).
-						if ( oNode.parentNode != this.EndBlockLimit )
-							oNode = oNode.parentNode ;
-						else
-							break ;
-					}
-					else if ( oSibling.nodeType != 1 || !(/^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/).test( oSibling.nodeName.toUpperCase() ) )
-					{
-						// Continue if the sibling is not a block tag.
-						oNode = oSibling ;
-					}
-					else
-						break ;
-				}
-				
-				// Move the marker right before the resulting node.
-				if ( oNode != eMarker )
-					FCKDomTools.InsertAfterNode( oNode, eMarker.parentNode.removeChild( eMarker ) ) ;
-				
-				// Move the range before to the marker.
-				this.SetEnd( eMarker, 3 ) ;
-				
-				// Remove the marker definitively.
-				eMarker.parentNode.removeChild( eMarker ) ;
-			}
-		
-			break ;										// @Packager.Remove.Start
-		
-		default :
-			throw( 'Invalid unit "' + unit + '"' ) ;	// @Packager.Remove.End
-	}
-}
Index: /FCKeditor/trunk/editor/_source/classes/fckenterkey.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckenterkey.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckenterkey.js	(revision 51)
@@ -265,8 +265,11 @@
 		{
 			// Delete the current selection.
-			oRange.DeleteContents() ;
-			
-			// Get the new selection (it is collapsed at this point).
-			oRange.MoveToSelection() ;
+			if ( !oRange.CheckIsEmpty() )
+			{
+				oRange.DeleteContents() ;
+			
+				// Get the new selection (it is collapsed at this point).
+			//	oRange.MoveToSelection() ;
+			}
 			
 			var eNewBlock ;
@@ -278,4 +281,7 @@
 			var bIsStartOfBlock	= oRange.CheckStartOfBlock() ;
 			var bIsEndOfBlock	= oRange.CheckEndOfBlock() ;
+
+			FCKDebug.Output( 'bIsStartOfBlock: ' + bIsStartOfBlock ) ;
+			FCKDebug.Output( 'bIsEndOfBlock: ' + bIsEndOfBlock ) ;
 
 			if ( bIsStartOfBlock && !bIsEndOfBlock )
@@ -365,18 +371,20 @@
 					
 					// Place the extracted contents in the duplicated block.
-					eDocFrag.AppendTo( eNewBlock ) ;					
+					eDocFrag.AppendTo( eNewBlock ) ;
+					
+					FCKDebug.Output( eNewBlock.innerHTML ) ;
 				}
 
 				if ( eNewBlock )
 				{
-					// Place the new block after the current block element.
-					if ( FCKBrowserInfo.IsIE )
-					{
-						// You gona think I'm crazy, but in IE we have to do
-						// this way to make it work properly with LI in some cases.
-						eStartBlock.parentNode.insertBefore( eNewBlock, eStartBlock ) ;		
-						eNewBlock.swapNode( eStartBlock	) ;	
-					}
-					else
+//					// Place the new block after the current block element.
+//					if ( FCKBrowserInfo.IsIE )
+//					{
+//						// You gona think I'm crazy, but in IE we have to do
+//						// this way to make it work properly with LI in some cases.
+//						eStartBlock.parentNode.insertBefore( eNewBlock, eStartBlock ) ;		
+//						eNewBlock.swapNode( eStartBlock	) ;	
+//					}
+//					else
 						FCKDomTools.InsertAfterNode( eStartBlock, eNewBlock ) ;
 
Index: /FCKeditor/trunk/editor/_source/classes/fckw3crange.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckw3crange.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/classes/fckw3crange.js	(revision 51)
@@ -38,4 +38,12 @@
 }
 
+FCKW3CRange.CreateFromRange = function( parentDocument, sourceRange )
+{
+	var range = FCKW3CRange.CreateRange( parentDocument ) ;
+	range.setStart( sourceRange.startContainer, sourceRange.startOffset ) ;
+	range.setEnd( sourceRange.endContainer, sourceRange.endOffset ) ;
+	return range ;
+}
+
 FCKW3CRange.prototype = 
 {
@@ -47,4 +55,7 @@
 	},
 
+	// W3C requires a check for the new position. If it is after the end
+	// boundary, the range should be collapsed to the new start. It seams we
+	// will not need this check for our use of this class so we can ignore it for now.
 	setStart : function( refNode, offset )
 	{
@@ -61,4 +72,7 @@
 	},
 	
+	// W3C requires a check for the new position. If it is before the start
+	// boundary, the range should be collapsed to the new end. It seams we
+	// will not need this check for our use of this class so we can ignore it for now.
 	setEnd : function( refNode, offset )
 	{
@@ -139,5 +153,5 @@
 		{
 			// Simply insert the new node before the current start node.
-			startContainer.insertBefore( newNode, startContainer.childNodes[ startOffset ] ) ;
+			startContainer.insertBefore( newNode, startContainer.childNodes[ startOffset ] || null ) ;
 
 			// Check if it is necessary to update the end boundary.
@@ -168,4 +182,5 @@
 	},
 
+	// The selection may be lost when clonning (due to the splitText() call).
 	cloneContents : function()
 	{
@@ -204,5 +219,5 @@
 			if ( endNode.childNodes.length > 0 )
 			{
-				// If the offset points after the last node, we let's use
+				// If the offset points after the last node, let's use
 				// the last one, but mark it for removal.
 				if ( endOffset > endNode.childNodes.length - 1 )
@@ -236,4 +251,22 @@
 					startNode = startNode.childNodes[ startOffset ].previousSibling ;
 			}
+		}
+
+		// There is a special case where a node contents with just one child is in the range:
+		// selectNodeContents( node ) -> node.childNodes.lenght == 1
+		if ( startNode == endNode && removeStartNode && removeEndNode )
+		{
+			if ( action == 2 )
+				docFrag.RootNode.appendChild( startNode.cloneNode( true ) ) ;
+			else
+			{
+				startNode.parentNode.removeChild( startNode ) ;
+				
+				if ( action == 1 )
+					docFrag.RootNode.appendChild( startNode ) ;
+				
+				this.collapse( true ) ;
+			}
+			return ;
 		}
 		
@@ -388,5 +421,5 @@
 				startNode.parentNode.removeChild( startNode ) ;
 
-			if( removeEndNode )
+			if( removeEndNode && endNode.parentNode )
 				endNode.parentNode.removeChild( endNode ) ;
 		}
@@ -395,5 +428,5 @@
 	cloneRange : function()
 	{
-		return FCKTools.CloneObject( this ) ;
+		return FCKW3CRange.CreateFromRange( this._Document, this ) ;
 	},
 
Index: /FCKeditor/trunk/editor/_source/fckscriptloader.js
===================================================================
--- /FCKeditor/trunk/editor/_source/fckscriptloader.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/fckscriptloader.js	(revision 51)
@@ -84,5 +84,5 @@
 FCKScriptLoader.AddScript( 'FCKElementPath'		, 'classes/'	, [], FCK_GENERIC ) ;
 FCKScriptLoader.AddScript( 'FCKDocumentFragment', 'classes/'	, ['FCKDomTools'], FCK_SPECIFIC ) ;
-FCKScriptLoader.AddScript( 'FCKDomRange'		, 'classes/'	, ['FCKBrowserInfo','FCKJSCoreExtensions','FCKElementPath','FCKDomTools','FCKTools','FCKDocumentFragment'], FCK_GENERIC_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 ) ;
Index: /FCKeditor/trunk/editor/_source/internals/fcktools.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fcktools.js	(revision 50)
+++ /FCKeditor/trunk/editor/_source/internals/fcktools.js	(revision 51)
@@ -42,11 +42,11 @@
 }
 
-FCKTools.GetDocumentWindow = function( doc )
+FCKTools.GetDocumentWindow = function( document )
 {
 	// With Safari, there is not way to retrieve the window from the document, so we must fix it.
-	if ( FCKBrowserInfo.IsSafari && !doc.parentWindow )
+	if ( FCKBrowserInfo.IsSafari && !document.parentWindow )
 		this.FixDocumentParentWindow( window.top ) ;
 	
-	return doc.parentWindow || doc.defaultView ;
+	return document.parentWindow || document.defaultView ;
 }
 
@@ -65,5 +65,5 @@
 FCKTools.GetParentWindow = function( document )
 {
-	return document.contentWindow ? document.contentWindow : document.parentWindow ;
+	return document.contentWindow || document.parentWindow ;
 }
 
@@ -171,5 +171,7 @@
 FCKTools.IsStrictMode = function( document )
 {
-	return ( document.compatMode && document.compatMode == "CSS1Compat" ) ;
+	// There is no compatMode in Safari, but it seams that it always behave as
+	// CSS1Compat, so let's assume it as the default.
+	return ( 'CSS1Compat' == ( document.compatMode || 'CSS1Compat' ) ) ;
 }
 
Index: /FCKeditor/trunk/editor/fckdebug.html
===================================================================
--- /FCKeditor/trunk/editor/fckdebug.html	(revision 50)
+++ /FCKeditor/trunk/editor/fckdebug.html	(revision 51)
@@ -52,5 +52,5 @@
 			try 
 			{
-				var sVal = anyObject[ prop ] ? anyObject[ prop ] + '' : '[null]' ;
+				var sVal = anyObject[ prop ] != null ? anyObject[ prop ] + '' : '[null]' ;
 				message += '<b>' + prop + '</b> : ' + sVal.replace(/</g, '&lt;') + '<br>' ;
 			} 
