Index: /FCKeditor/trunk/editor/_source/commandclasses/fckblockquotecommand.js
===================================================================
--- /FCKeditor/trunk/editor/_source/commandclasses/fckblockquotecommand.js	(revision 852)
+++ /FCKeditor/trunk/editor/_source/commandclasses/fckblockquotecommand.js	(revision 853)
@@ -41,41 +41,126 @@
 		if ( state == FCK_TRISTATE_OFF )
 		{
-			range.Expand( 'block_contents' ) ;
-			range.SetStart( range.StartContainer, 3 ) ;
-			range.SetEnd( range.EndContainer, 4 ) ;
-			var oldStart = range.StartContainer ;
-			var oldEnd = range.EndContainer ;
-			var docFrag = range.ExtractContents() ;
-			var quoteBlock = range.Window.document.createElement( 'blockquote' ) ;
-			docFrag.AppendTo( quoteBlock ) ;
-			range.InsertNode( quoteBlock ) ;
-			if ( ! oldStart.lastChild )
-				oldStart.parentNode.removeChild( oldStart ) ;
-			if ( ! oldEnd.lastChild )
-				oldEnd.parentNode.removeChild( oldEnd ) ;
+			iterator.EnforceRealBlocks = true ;
+			var paragraphs = [] ;
+			while ( ( block = iterator.GetNextParagraph() ) )
+				paragraphs.push( block ) ;
+
+			// Make sure all paragraphs have the same parent.
+			var commonParent = paragraphs[0].parentNode ;
+			var tmp = [] ;
+			for ( var i = 0 ; i < paragraphs.length ; i++ )
+			{
+				block = paragraphs[i] ;
+				commonParent = FCKDomTools.GetCommonParents( block.parentNode, commonParent ).pop() ;
+			}
+			var lastBlock = null ;
+			while ( paragraphs.length > 0 )
+			{
+				block = paragraphs.shift() ;
+				while ( block.parentNode != commonParent )
+					block = block.parentNode ;
+				if ( block != lastBlock )
+					tmp.push( block ) ;
+				lastBlock = block ;
+			}
+
+			// If any of the selected blocks is a blockquote, remove it to prevent nested blockquotes.
+			while ( tmp.length > 0 )
+			{
+				block = tmp.shift() ;
+				if ( block.nodeName.IEquals( 'blockquote' ) )
+				{
+					var docFrag = block.ownerDocument.createDocumentFragment() ;
+					while ( block.firstChild )
+					{
+						docFrag.appendChild( block.removeChild( block.firstChild ) ) ;
+						paragraphs.push( docFrag.lastChild ) ;
+					}
+					block.parentNode.replaceChild( docFrag, block ) ;
+				}
+				else
+					paragraphs.push( block ) ;
+			}
+
+			// Now we have all the blocks to be included in a new blockquote node.
+			var bqBlock = range.Window.document.createElement( 'blockquote' ) ;
+			commonParent.insertBefore( bqBlock, paragraphs[0] ) ;
+			while ( paragraphs.length > 0 )
+			{
+				block = paragraphs.shift() ;
+				bqBlock.appendChild( block ) ;
+			}
 		}
 		else if ( state == FCK_TRISTATE_ON )
 		{
-			var bqBlocks = [] ;
+			var moveOutNodes = [] ;
 			while ( ( block = iterator.GetNextParagraph() ) )
 			{
-				var bqParent = this._GetBlockquoteParent( block ) ;
-				if ( ! bqParent )
-					continue ;
+				var bqParent = null ;
+				var bqChild = null ;
+				while ( block.parentNode )
+				{
+					if ( block.parentNode.nodeName.IEquals( 'blockquote' ) )
+					{
+						bqParent = block.parentNode ;
+						bqChild = block ;
+						break ;
+					}
+					block = block.parentNode ;
+				}
 
-				if ( bqParent._FCK_AREADY_ADDED )
-					continue ;
-
-				bqBlocks.push( bqParent ) ;
-				bqParent._FCK_AREADY_ADDED = true ;
+				if ( bqParent && bqChild )
+					moveOutNodes.push( bqChild ) ;
 			}
 
-			while ( bqBlocks.length > 0 )
+			var movedNodes = [] ;
+			while ( moveOutNodes.length > 0 )
 			{
-				var blockquote = bqBlocks.shift() ;
-				var fragment = blockquote.ownerDocument.createDocumentFragment() ;
-				while ( blockquote.firstChild )
-					fragment.appendChild( blockquote.removeChild( blockquote.firstChild ) ) ;
-				blockquote.parentNode.replaceChild( fragment, blockquote ) ;
+				var node = moveOutNodes.shift() ;
+				var bqBlock = node.parentNode ;
+
+				// If the node is located at the beginning or the end, just take it out without splitting.
+				// Otherwise, split the blockquote node and move the paragraph in between the two blockquote nodes.
+				if ( node == node.parentNode.firstChild )
+				{
+					bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock ) ;
+					if ( ! bqBlock.firstChild )
+						bqBlock.parentNode.removeChild( bqBlock ) ;
+				}
+				else if ( node == node.parentNode.lastChild )
+				{
+					bqBlock.parentNode.insertBefore( bqBlock.removeChild( node ), bqBlock.nextSibling ) ;
+					if ( ! bqBlock.firstChild )
+						bqBlock.parentNode.removeChild( bqBlock ) ;
+				}
+				else
+					FCKDomTools.BreakParent( node, node.parentNode, range ) ;
+
+				movedNodes.push( node ) ;
+			}
+
+			if ( FCKConfig.EnterMode.IEquals( 'br' ) )
+			{
+				while ( movedNodes.length )
+				{
+					var node = movedNodes.shift() ;
+					var firstTime = true ;
+					if ( node.nodeName.IEquals( 'div' ) )
+					{
+						var docFrag = node.ownerDocument.createDocumentFragment() ;
+						var needBeginBr = firstTime && node.previousSibling && 
+							!FCKListsLib.BlockBoundaries[node.previousSibling.nodeName.toLowerCase()] ;
+						if ( firstTime && needBeginBr )
+							docFrag.appendChild( node.ownerDocument.createElement( 'br' ) ) ;
+						var needEndBr = node.nextSibling && 
+							!FCKListsLib.BlockBoundaries[node.nextSibling.nodeName.toLowerCase()] ;
+						while ( node.firstChild )
+							docFrag.appendChild( node.removeChild( node.firstChild ) ) ;
+						if ( needEndBr )
+							docFrag.appendChild( node.ownerDocument.createElement( 'br' ) ) ;
+						node.parentNode.replaceChild( docFrag, node ) ;
+						firstTime = false ;
+					}
+				}
 			}
 		}
@@ -104,9 +189,4 @@
 		}
 		return FCK_TRISTATE_OFF ;
-	},
-
-	_GetBlockquoteParent : function( node )
-	{
-		return FCKDomTools.GetCommonParentNode( node, node, 'blockquote' ) ;
 	}
 } ;
