Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 1047)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 1048)
@@ -175,91 +175,148 @@
 	},
 
+	/**
+	 * Checks if the start boundary of the current range is "visually" (like a
+	 * selection caret) at the beginning of the block. It means that some
+	 * things could be brefore the range, like spaces or empty inline elements,
+	 * but it would still be considered at the beginning of the block.
+	 */
 	CheckStartOfBlock : function()
 	{
-		var bIsStartOfBlock = this._Cache.IsStartOfBlock ;
+		var cache = this._Cache ;
+		var bIsStartOfBlock = cache.IsStartOfBlock ;
 
 		if ( bIsStartOfBlock != undefined )
 			return bIsStartOfBlock ;
 
-		// 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 ) ;
-
-		if ( oTestRange.CheckIsCollapsed() )
-			bIsStartOfBlock = true ;
+		// Take the block reference.
+		var block = this.StartBlock || this.StartBlockLimit ;
+
+		var container	= this._Range.startContainer ;
+		var offset		= this._Range.startOffset ;
+		var currentNode ;
+
+		if ( offset > 0 )
+		{
+			// First, check the start container. If it is a text node, get the
+			// substring of the node value before the range offset.
+			if ( container.nodeType == 3 )
+			{
+				var textValue = container.nodeValue.substr( 0, offset ).Trim() ;
+
+				// If we have some text left in the container, we are not at
+				// the end for the block.
+				if ( textValue.length != 0 )
+					return cache.IsStartOfBlock = false ;
+			}
+			else
+				currentNode = container.childNodes[ offset - 1 ] ;
+		}
+
+		// We'll not have a currentNode if the container was a text node, or
+		// the offset is zero.
+		if ( !currentNode )
+			currentNode = FCKDomTools.GetPreviousSourceNode( container, true, null, block ) ;
+
+		while ( currentNode )
+		{
+			switch ( currentNode.nodeType )
+			{
+				case 1 :
+					// It's not an inline element.
+					if ( !FCKListsLib.InlineChildReqElements[ currentNode.nodeName.toLowerCase() ] )
+						return cache.IsStartOfBlock = false ;
+
+					break ;
+
+				case 3 :
+					// It's a text node with real text.
+					if ( currentNode.nodeValue.Trim().length > 0 )
+						return cache.IsStartOfBlock = false ;
+			}
+
+			currentNode = FCKDomTools.GetPreviousSourceNode( currentNode, false, null, block ) ;
+		}
+
+		return cache.IsStartOfBlock = true ;
+	},
+
+	/**
+	 * Checks if the end boundary of the current range is "visually" (like a
+	 * selection caret) at the end of the block. It means that some things
+	 * could be after the range, like spaces, empty inline elements, or a
+	 * single <br>, but it would still be considered at the end of the block.
+	 */
+	CheckEndOfBlock : function( refreshSelection )
+	{
+		var isEndOfBlock = this._Cache.IsEndOfBlock ;
+
+		if ( isEndOfBlock != undefined )
+			return isEndOfBlock ;
+
+		// Take the block reference.
+		var block = this.EndBlock || this.EndBlockLimit ;
+
+		var container	= this._Range.endContainer ;
+		var offset			= this._Range.endOffset ;
+		var currentNode ;
+
+		// First, check the end container. If it is a text node, get the
+		// substring of the node value after the range offset.
+		if ( container.nodeType == 3 )
+		{
+			var textValue = container.nodeValue ;
+			if ( offset < textValue.length )
+			{
+				textValue = textValue.substr( offset ) ;
+
+				// If we have some text left in the container, we are not at
+				// the end for the block.
+				if ( textValue.Trim().length != 0 )
+					return this._Cache.IsEndOfBlock = false ;
+			}
+		}
 		else
-		{
-			// Inserts the contents of the range in a div tag.
-			var eToolDiv = oTestRange.Window.document.createElement( 'div' ) ;
-			oTestRange._Range.cloneContents().AppendTo( eToolDiv ) ;
-
-			// This line is why we don't use CheckIsEmpty() here...
-			// Because using RTrimNode() or TrimNode() would be incorrect - 
-			// TrimNode() and RTrimNode() would delete <br> nodes at the end of the div node,
-			// but for checking start of block they are actually meaningful. (Bug #1350)
-			FCKDomTools.LTrimNode( eToolDiv ) ;
-
-			bIsStartOfBlock = ( eToolDiv.innerHTML.length == 0 ) ;
-		}
-
-		oTestRange.Release() ;
-
-		return ( this._Cache.IsStartOfBlock = bIsStartOfBlock ) ;
-	},
-
-	CheckEndOfBlock : function( refreshSelection )
-	{
-		var bIsEndOfBlock = this._Cache.IsEndOfBlock ;
-
-		if ( bIsEndOfBlock != undefined )
-			return bIsEndOfBlock ;
-
-		// 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 ) ;
-
-		bIsEndOfBlock = oTestRange.CheckIsCollapsed() ;
-
-		if ( !bIsEndOfBlock )
-		{
-			// Inserts the contents of the range in a div tag.
-			var eToolDiv = this.Window.document.createElement( 'div' ) ;
-			oTestRange._Range.cloneContents().AppendTo( eToolDiv ) ;
-			FCKDomTools.TrimNode( eToolDiv ) ;
-
-			// Find out if we are in an empty tree of inline elements, like <b><i><span></span></i></b>
-			bIsEndOfBlock = true ;
-			var eLastChild = eToolDiv ;
-			while ( ( eLastChild = eLastChild.lastChild ) )
+			currentNode = container.childNodes[ offset ] ;
+
+		// We'll not have a currentNode if the container was a text node, of
+		// the offset is out the container children limits (after it probably).
+		if ( !currentNode )
+			currentNode = FCKDomTools.GetNextSourceNode( container, true, null, block ) ;
+
+		var hadBr = false ;
+
+		while ( currentNode )
+		{
+			switch ( currentNode.nodeType )
 			{
-				// Check the following:
-				//		1. Is there more than one node in the parents children?
-				//		2. Is the node not an element node?
-				//		3. Is it not a inline element.
-				if ( eLastChild.previousSibling || eLastChild.nodeType != 1 || FCKListsLib.InlineChildReqElements[ eLastChild.nodeName.toLowerCase() ] == null )
-				{
-					// So we are not in the end of the range.
-					bIsEndOfBlock = false ;
-					break ;
-				}
+				case 1 :
+					var nodeName = currentNode.nodeName.toLowerCase() ;
+
+					// It's an inline element.
+					if ( FCKListsLib.InlineChildReqElements[ nodeName ] )
+						break ;
+
+					// It is the first <br> found.
+					if ( nodeName == 'br' && !hadBr )
+					{
+						hadBr = true ;
+						break ;
+					}
+
+					return this._Cache.IsEndOfBlock = false ;
+
+				case 3 :
+					// It's a text node with real text.
+					if ( currentNode.nodeValue.Trim().length > 0 )
+						return this._Cache.IsEndOfBlock = false ;
 			}
-		}
-
-		oTestRange.Release() ;
+
+			currentNode = FCKDomTools.GetNextSourceNode( currentNode, false, null, block ) ;
+		}
 
 		if ( refreshSelection )
 			this.Select() ;
 
-		return this._Cache.IsEndOfBlock = bIsEndOfBlock ;
+		return this._Cache.IsEndOfBlock = true ;
 	},
 
@@ -322,5 +379,5 @@
 			oBookmark.EndNode = eEndSpan ;
 		}
-		
+
 		// Update the range position.
 		if ( eEndSpan )
@@ -331,5 +388,5 @@
 		else
 			this.MoveToPosition( eStartSpan, 4 ) ;
-		
+
 		return oBookmark ;
 	},
@@ -532,5 +589,5 @@
 					if ( oNode.nodeType != 1 )
 						oNode = oNode.previousSibling ? null : oNode.parentNode ;
-					
+
 					if ( oNode )
 					{
@@ -671,4 +728,5 @@
 			var eStartBlock		= this.StartBlock ;
 			var eEndBlock		= this.EndBlock ;
+			var oElementPath	= null ;
 
 			if ( FCKConfig.EnterMode != 'br' )
@@ -696,4 +754,5 @@
 				if ( bIsEndOfBlock )
 				{
+					oElementPath = new FCKElementPath( this.StartContainer ) ;
 					this.MoveToPosition( eEndBlock, 4 ) ;
 					eEndBlock = null ;
@@ -701,4 +760,5 @@
 				else if ( bIsStartOfBlock )
 				{
+					oElementPath = new FCKElementPath( this.StartContainer ) ;
 					this.MoveToPosition( eStartBlock, 3 ) ;
 					eStartBlock = null ;
@@ -733,5 +793,6 @@
 				NextBlock		: eEndBlock,
 				WasStartOfBlock : bIsStartOfBlock,
-				WasEndOfBlock	: bIsEndOfBlock
+				WasEndOfBlock	: bIsEndOfBlock,
+				ElementPath		: oElementPath
 			} ;
 		}
@@ -789,24 +850,24 @@
 		return !!this._Range ;
 	},
-	
+
 	GetTouchedStartNode : function()
 	{
 		var range = this._Range ;
 		var container = range.startContainer ;
-		
+
 		if ( range.collapsed || container.nodeType != 1 )
 			return container ;
-		
+
 		return container.childNodes[ range.startOffset ] || container ;
 	},
-	
+
 	GetTouchedEndNode : function()
 	{
 		var range = this._Range ;
 		var container = range.endContainer ;
-		
+
 		if ( range.collapsed || container.nodeType != 1 )
 			return container ;
-		
+
 		return container.childNodes[ range.endOffset - 1 ] || container ;
 	}
Index: /FCKeditor/trunk/editor/_source/classes/fckenterkey.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckenterkey.js	(revision 1047)
+++ /FCKeditor/trunk/editor/_source/classes/fckenterkey.js	(revision 1048)
@@ -116,5 +116,5 @@
 	var parentPath = new FCKElementPath( parentElement ) ;
 	var sMode = mode || this.EnterMode ;
-	
+
 	if ( sMode == 'br' || parentPath.Block && parentPath.Block.tagName.toLowerCase() == 'pre' )
 		return this._ExecuteEnterBr() ;
@@ -342,5 +342,5 @@
 		var eCurrentCell = FCKTools.GetElementAscensor( oCurrentBlock, 'td' );
 
-		var eNext = FCKDomTools.GetNextSourceElement( oCurrentBlock, true, [ oRange.StartBlockLimit.nodeName ], 
+		var eNext = FCKDomTools.GetNextSourceElement( oCurrentBlock, true, [ oRange.StartBlockLimit.nodeName ],
 				['UL','OL','TR'] ) ;
 
@@ -401,5 +401,7 @@
 
 	var oSplitInfo = oRange.SplitBlock() ;
-	
+
+	// FCKDebug.OutputObject( oSplitInfo ) ;
+
 	if ( oSplitInfo )
 	{
@@ -431,4 +433,5 @@
 
 			var eNewBlock ;
+			var eFocusElement ;
 
 			if ( ePreviousBlock )
@@ -437,21 +440,32 @@
 
 				// If is a header tag, or we are in a Shift+Enter (#77),
-				// create a new block element.
-				if ( this._HasShift || (/^H[1-6]$/).test( sPreviousBlockTag ) )
-					eNewBlock = this.Window.document.createElement( blockTag ) ;
-				else
+				// create a new block element (later in the code).
+				if ( !this._HasShift && !(/^H[1-6]$/).test( sPreviousBlockTag ) )
 				{
 					// Otherwise, duplicate the previous block.
 					eNewBlock = FCKDomTools.CloneElement( ePreviousBlock ) ;
-
-					this._RecreateEndingTree( ePreviousBlock, eNewBlock ) ;
 				}
 			}
 			else if ( eNextBlock )
-			{
 				eNewBlock = FCKDomTools.CloneElement( eNextBlock ) ;
-			}
-			else
+
+			if ( !eNewBlock )
 				eNewBlock = this.Window.document.createElement( blockTag ) ;
+
+			// Recreate the inline elements tree, which was available
+			// before the hitting enter, so the same styles will be
+			// available in the new block.
+			var elementPath = oSplitInfo.ElementPath ;
+			var eFocusElement = eNewBlock ;
+			for ( var i = 0, len = elementPath.Elements.length ; i < len ; i++ )
+			{
+				var element = elementPath.Elements[i] ;
+
+				if ( element == elementPath.Block || element == elementPath.BlockLimit )
+					break ;
+
+				if ( FCKListsLib.InlineChildReqElements[ element.nodeName.toLowerCase() ] )
+					eFocusElement = eFocusElement.appendChild( FCKDomTools.CloneElement( element ) ) ;
+			}
 
 			if ( FCKBrowserInfo.IsGeckoLike )
@@ -469,4 +483,5 @@
 			}
 
+			// Move the selection to the new block.
 			oRange.MoveToElementEditStart( bIsStartOfBlock && !bIsEndOfBlock ? eNextBlock : eNewBlock ) ;
 
@@ -569,14 +584,4 @@
 }
 
-// Recreate the elements tree at the end of the source block, at the beginning
-// of the target block. Eg.:
-//	If source = <p><u>Some</u> sample <b><i>text</i></b></p> then target = <p><b><i></i></b></p>
-//	If source = <p><u>Some</u> sample text</p> then target = <p></p>
-FCKEnterKey.prototype._RecreateEndingTree = function( source, target )
-{
-	while ( ( source = source.lastChild ) && source.nodeType == 1 && FCKListsLib.InlineChildReqElements[ source.nodeName.toLowerCase() ] != null )
-		target = target.insertBefore( FCKDomTools.CloneElement( source ), target.firstChild ) ;
-}
-
 // Outdents a LI, maintaining the selection defined on a range.
 FCKEnterKey.prototype._OutdentWithSelection = function( li, range )
@@ -595,5 +600,5 @@
 	var startOk = false ;
 	var endOk = false ;
-	
+
 	/*
 	FCKDebug.Output( 'sc='+range.StartContainer.nodeName+
Index: /FCKeditor/trunk/editor/_source/internals/fckdomtools.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckdomtools.js	(revision 1047)
+++ /FCKeditor/trunk/editor/_source/internals/fckdomtools.js	(revision 1048)
@@ -265,5 +265,5 @@
 	 * Get the next DOM node available in source order.
 	 */
-	GetNextSourceNode : function( currentNode, startFromSibling, nodeType, stopSearchElement )
+	GetNextSourceNode : function( currentNode, startFromSibling, nodeType, stopSearchNode )
 	{
 		if ( !currentNode )
@@ -276,12 +276,15 @@
 		else
 		{
+			if ( stopSearchNode && currentNode == stopSearchNode )
+				return null ;
+
 			node = currentNode.nextSibling ;
-			
-			if ( !node && ( !stopSearchElement || stopSearchElement != currentNode.parentNode ) )
-				return this.GetNextSourceNode( currentNode.parentNode, true, nodeType, stopSearchElement ) ;
+
+			if ( !node && ( !stopSearchNode || stopSearchNode != currentNode.parentNode ) )
+				return this.GetNextSourceNode( currentNode.parentNode, true, nodeType, stopSearchNode ) ;
 		}
 
 		if ( nodeType && node && node.nodeType != nodeType )
-			return this.GetNextSourceNode( node, false, nodeType, stopSearchElement ) ;
+			return this.GetNextSourceNode( node, false, nodeType, stopSearchNode ) ;
 
 		return node ;
@@ -291,5 +294,5 @@
 	 * Get the next DOM node available in source order.
 	 */
-	GetPreviousSourceNode : function( currentNode, startFromSibling, nodeType )
+	GetPreviousSourceNode : function( currentNode, startFromSibling, nodeType, stopSearchNode )
 	{
 		if ( !currentNode )
@@ -301,8 +304,16 @@
 			node = currentNode.lastChild ;
 		else
-			node = ( currentNode.previousSibling || this.GetPreviousSourceNode( currentNode.parentNode, true, nodeType ) ) ;
-
+		{
+			if ( stopSearchNode && currentNode == stopSearchNode )
+				return null ;
+
+			node = currentNode.previousSibling ;
+
+			if ( !node && ( !stopSearchNode || stopSearchNode != currentNode.parentNode ) )
+				return this.GetPreviousSourceNode( currentNode.parentNode, true, nodeType, stopSearchNode ) ;
+		}
+		
 		if ( nodeType && node && node.nodeType != nodeType )
-			return this.GetPreviousSourceNode( node, false, nodeType ) ;
+			return this.GetPreviousSourceNode( node, false, nodeType, stopSearchNode ) ;
 
 		return node ;
@@ -452,5 +463,5 @@
 			if ( FCKBrowserInfo.IsIE && attributes[i].nodeName == 'class' )
 			{
-				// IE has a strange bug. If calling removeAttribute('className'), 
+				// IE has a strange bug. If calling removeAttribute('className'),
 				// the attributes collection will still contain the "class"
 				// attribute, which will be marked as "specified", even if the
@@ -578,7 +589,7 @@
 			{
 				var candidate = parentNode.childNodes[i] ;
-				if ( normalized === true && 
-						candidate.nodeType == 3 && 
-						candidate.previousSibling && 
+				if ( normalized === true &&
+						candidate.nodeType == 3 &&
+						candidate.previousSibling &&
 						candidate.previousSibling.nodeType == 3 )
 					continue;
@@ -773,5 +784,5 @@
 				if ( currentListItem.nodeType == 11 )
 				{
-					if ( currentListItem.lastChild && 
+					if ( currentListItem.lastChild &&
 							currentListItem.lastChild.getAttribute &&
 							currentListItem.lastChild.getAttribute( 'type' ) == '_moz' )
@@ -847,5 +858,5 @@
 		return node ;
 	},
-	
+
 	/**
 	 * Checks if an element has no "useful" content inside of it
@@ -859,5 +870,5 @@
 		var child = element.firstChild ;
 		var elementChild ;
-		
+
 		while ( child )
 		{
@@ -866,5 +877,5 @@
 				if ( elementChild || !FCKListsLib.InlineNonEmptyElements[ child.nodeName.toLowerCase() ] )
 					return false ;
-				
+
 				if ( !elementCheckCallback || elementCheckCallback( child ) === true )
 					elementChild = child ;
@@ -872,8 +883,8 @@
 			else if ( child.nodeType == 3 && child.nodeValue.length > 0 )
 				return false ;
-			
+
 			child = child.nextSibling ;
 		}
-		
+
 		return elementChild ? this.CheckIsEmptyElement( elementChild, elementCheckCallback ) : true ;
 	},
