Index: /CKEditor/branches/features/v4-domiterator/_source/core/dom/range.js
===================================================================
--- /CKEditor/branches/features/v4-domiterator/_source/core/dom/range.js	(revision 7079)
+++ /CKEditor/branches/features/v4-domiterator/_source/core/dom/range.js	(revision 7080)
@@ -1355,4 +1355,10 @@
 							|| enlargeable && blockBoundary.contains( enlargeable ) );
 
+					if ( tailBr && !tailBr.getNext( nonWhitespaceOrBookmarkEval ) )
+					{
+						fromInside = 1;
+						blockBoundary = tailBr.getParent();
+					}
+
 					if ( ( unit == CKEDITOR.ENLARGE_BLOCKS || unit == CKEDITOR.ENLARGE_LIST_ITEMS ) && fromInside )
 					{
@@ -1367,10 +1373,10 @@
 									CKEDITOR.POSITION_BEFORE_END :
 									CKEDITOR.POSITION_BEFORE_START );
+
+						// We must include the <br> at the end of range if there's
+						// one and we're expanding list item contents
+						if ( tailBr )
+							this.setEndAfter( tailBr );
 					}
-
-					// We must include the <br> at the end of range if there's
-					// one and we're expanding list item contents
-					if ( tailBr )
-						this.setEndAfter( tailBr );
 			}
 		},
Index: /CKEditor/branches/features/v4-domiterator/_source/core/dom/walker.js
===================================================================
--- /CKEditor/branches/features/v4-domiterator/_source/core/dom/walker.js	(revision 7079)
+++ /CKEditor/branches/features/v4-domiterator/_source/core/dom/walker.js	(revision 7080)
@@ -339,5 +339,7 @@
 	CKEDITOR.dom.element.prototype.isBlockBoundary = function( customNodeNames )
 	{
-		var nodeNameMatches = CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$block, customNodeNames || {} );
+		var nodeNameMatches = customNodeNames ?
+			CKEDITOR.tools.extend( {}, CKEDITOR.dtd.$block, customNodeNames || {} ) :
+			CKEDITOR.dtd.$block;
 
 		// Don't consider floated formatting as block boundary, fall back to dtd check in that case. (#6297)
@@ -458,3 +460,14 @@
 	};
 
+	// Check whether this element is an empty block.
+	CKEDITOR.dom.element.prototype.isEmptyBlock = function()
+	{
+		if ( !this.isBlockBoundary() )
+			return false;
+
+		var range = new CKEDITOR.dom.range( this.getDocument() );
+		range.moveToPosition( this, CKEDITOR.POSITION_AFTER_START );
+		return range.checkStartOfBlock() && range.checkEndOfBlock();
+	};
+
 })();
Index: /CKEditor/branches/features/v4-domiterator/_source/plugins/blockquote/plugin.js
===================================================================
--- /CKEditor/branches/features/v4-domiterator/_source/plugins/blockquote/plugin.js	(revision 7079)
+++ /CKEditor/branches/features/v4-domiterator/_source/plugins/blockquote/plugin.js	(revision 7080)
@@ -48,5 +48,6 @@
 			var state = editor.getCommand( 'blockquote' ).state,
 				selection = editor.getSelection(),
-				range = selection && selection.getRanges( true )[0];
+				range = selection && selection.getRanges( true )[0],
+				enterBr = editor.config.enterMode == CKEDITOR.ENTER_BR;
 
 			if ( !range )
@@ -94,10 +95,10 @@
 			}
 
-			var iterator = range.createIterator(),
-				block;
-			iterator.enlargeBr = editor.config.enterMode != CKEDITOR.ENTER_BR;
-
 			if ( state == CKEDITOR.TRISTATE_OFF )
 			{
+				var iterator = range.createIterator(),
+					block;
+				iterator.enlargeBr = !enterBr;
+
 				var paragraphs = [];
 				while ( ( block = iterator.getNextParagraph() ) )
@@ -177,106 +178,47 @@
 			else if ( state == CKEDITOR.TRISTATE_ON )
 			{
-				var moveOutNodes = [],
-					database = {};
-
-				while ( ( block = iterator.getNextParagraph() ) )
-				{
-					var bqParent = null,
-						bqChild = null;
-					while ( block.getParent() )
-					{
-						if ( block.getParent().getName() == 'blockquote' )
-						{
-							bqParent = block.getParent();
-							bqChild = block;
-							break;
-						}
-						block = block.getParent();
-					}
-
-					// Remember the blocks that were recorded down in the moveOutNodes array
-					// to prevent duplicates.
-					if ( bqParent && bqChild && !bqChild.getCustomData( 'blockquote_moveout' ) )
-					{
-						moveOutNodes.push( bqChild );
-						CKEDITOR.dom.element.setMarker( database, bqChild, 'blockquote_moveout', true );
-					}
-				}
-
-				CKEDITOR.dom.element.clearAllMarkers( database );
-
-				var movedNodes = [],
-					processedBlockquoteBlocks = [];
-
-				database = {};
-				while ( moveOutNodes.length > 0 )
-				{
-					var node = moveOutNodes.shift();
-					bqBlock = node.getParent();
-
-					// 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.getPrevious() )
-						node.remove().insertBefore( bqBlock );
-					else if ( !node.getNext() )
-						node.remove().insertAfter( bqBlock );
-					else
-					{
-						node.breakParent( node.getParent() );
-						processedBlockquoteBlocks.push( node.getNext() );
-					}
-
-					// Remember the blockquote node so we can clear it later (if it becomes empty).
-					if ( !bqBlock.getCustomData( 'blockquote_processed' ) )
-					{
-						processedBlockquoteBlocks.push( bqBlock );
-						CKEDITOR.dom.element.setMarker( database, bqBlock, 'blockquote_processed', true );
-					}
-
-					movedNodes.push( node );
-				}
-
-				CKEDITOR.dom.element.clearAllMarkers( database );
-
-				// Clear blockquote nodes that have become empty.
-				for ( i = processedBlockquoteBlocks.length - 1 ; i >= 0 ; i-- )
-				{
-					bqBlock = processedBlockquoteBlocks[i];
-					if ( noBlockLeft( bqBlock ) )
-						bqBlock.remove();
-				}
-
-				if ( editor.config.enterMode == CKEDITOR.ENTER_BR )
-				{
-					var firstTime = true;
-					while ( movedNodes.length )
-					{
-						node = movedNodes.shift();
-
-						if ( node.getName() == 'div' )
-						{
-							docFrag = new CKEDITOR.dom.documentFragment( editor.document );
-							var needBeginBr = firstTime && node.getPrevious() &&
-									!( node.getPrevious().type == CKEDITOR.NODE_ELEMENT && node.getPrevious().isBlockBoundary() );
-							if ( needBeginBr )
-								docFrag.append( editor.document.createElement( 'br' ) );
-
-							var needEndBr = node.getNext() &&
-								!( node.getNext().type == CKEDITOR.NODE_ELEMENT && node.getNext().isBlockBoundary() );
-							while ( node.getFirst() )
-								node.getFirst().remove().appendTo( docFrag );
-
-							if ( needEndBr )
-								docFrag.append( editor.document.createElement( 'br' ) );
-
-							docFrag.replace( node );
-							firstTime = false;
-						}
-					}
-				}
+				var blockquote = range.getCommonAncestor().getAscendant( 'blockquote', 1 );
+
+				range.enlarge( enterBr ? CKEDITOR.ENLARGE_LIST_ITEMS : CKEDITOR.ENLARGE_BLOCKS );
+
+				// Fixing the case where blockquote element itself is enlarged, don't leak outside of it.
+				// e.g. <blockquote>no other block</blockquote>.
+				if ( range.startContainer.contains( blockquote ) )
+					range.setStartAt( blockquote, CKEDITOR.POSITION_AFTER_START );
+				if ( range.endContainer.contains( blockquote ) )
+					range.setEndAt( blockquote, CKEDITOR.POSITION_BEFORE_END );
+
+				var isStart = range.checkBoundaryOfElement( blockquote, CKEDITOR.START ),
+					isEnd = range.checkBoundaryOfElement( blockquote, CKEDITOR.END ),
+					frag = range.extractContents();
+
+				if ( isStart )
+					frag.insertBefore( blockquote );
+				else if ( isEnd )
+					frag.insertAfterNode( blockquote );
+				else
+				{
+					var marker = editor.document.createElement( 'span' );
+					range.insertNode( marker );
+					marker.breakParent( blockquote );
+					frag.replace( marker );
+				}
+
+				if ( blockquote.isEmptyBlock() )
+					blockquote.remove();
 			}
 
 			selection.selectBookmarks( bookmarks );
+
+			// Fix those moved out pseudo paragraphs in block enter mode.
+			if ( !enterBr )
+			{
+				bookmarks = selection.createBookmarks();
+				range = selection.getRanges()[ 0 ];
+				var iterator = range.createIterator();
+				while ( iterator.getNextParagraph() );
+				selection.selectBookmarks( bookmarks );
+			}
+
 			editor.focus();
 		}
