Index: /CKEditor/branches/features/paste/_source/plugins/enterkey/plugin.js
===================================================================
--- /CKEditor/branches/features/paste/_source/plugins/enterkey/plugin.js	(revision 4677)
+++ /CKEditor/branches/features/paste/_source/plugins/enterkey/plugin.js	(revision 4678)
@@ -18,42 +18,8 @@
 	});
 
-	var forceMode,
-		headerTagRegex = /^h[1-6]$/;
-
-	function shiftEnter( editor )
-	{
-		// On SHIFT+ENTER we want to enforce the mode to be respected, instead
-		// of cloning the current block. (#77)
-		forceMode = 1;
-
-		return enter( editor, editor.config.shiftEnterMode );
-	}
-
-	function enter( editor, mode )
-	{
-		// Only effective within document.
-		if ( editor.mode != 'wysiwyg' )
-			return false;
-
-		if ( !mode )
-			mode = editor.config.enterMode;
-
-		// Use setTimout so the keys get cancelled immediatelly.
-		setTimeout( function()
-			{
-				editor.fire( 'saveSnapshot' );	// Save undo step.
-				if ( mode == CKEDITOR.ENTER_BR || editor.getSelection().getStartElement().hasAscendant( 'pre', true ) )
-					enterBr( editor, mode );
-				else
-					enterBlock( editor, mode );
-
-				forceMode = 0;
-			}, 0 );
-
-		return true;
-	}
-
-	function enterBlock( editor, mode, range )
-	{
+	CKEDITOR.plugins.enterkey =
+	{
+		enterBlock : function( editor, mode, range )
+		{
 		// Get the range for the current selection.
 		range = range || getRange( editor );
@@ -208,104 +174,144 @@
 
 		range.select();
+	},
+		enterBr : function( editor, mode )
+		{
+			// Get the range for the current selection.
+			var range = getRange( editor ),
+				doc = range.document;
+
+			// Determine the block element to be used.
+			var blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' );
+
+			var isEndOfBlock = range.checkEndOfBlock();
+
+			var elementPath = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() );
+
+			var startBlock = elementPath.block,
+				startBlockTag = startBlock && elementPath.block.getName();
+
+			var isPre = false;
+
+			if ( !forceMode && startBlockTag == 'li' )
+			{
+				enterBlock( editor, mode, range );
+				return;
+			}
+
+			// If we are at the end of a header block.
+			if ( !forceMode && isEndOfBlock && headerTagRegex.test( startBlockTag ) )
+			{
+				// Insert a <br> after the current paragraph.
+				doc.createElement( 'br' ).insertAfter( startBlock );
+
+				// A text node is required by Gecko only to make the cursor blink.
+				if ( CKEDITOR.env.gecko )
+					doc.createText( '' ).insertAfter( startBlock );
+
+				// IE has different behaviors regarding position.
+				range.setStartAt( startBlock.getNext(), CKEDITOR.env.ie ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_START );
+			}
+			else
+			{
+				var lineBreak;
+
+				isPre = ( startBlockTag == 'pre' );
+
+				if ( isPre )
+					lineBreak = doc.createText( CKEDITOR.env.ie ? '\r' : '\n' );
+				else
+					lineBreak = doc.createElement( 'br' );
+
+				range.deleteContents();
+				range.insertNode( lineBreak );
+
+				// A text node is required by Gecko only to make the cursor blink.
+				// We need some text inside of it, so the bogus <br> is properly
+				// created.
+				if ( !CKEDITOR.env.ie )
+					doc.createText( '\ufeff' ).insertAfter( lineBreak );
+
+				// If we are at the end of a block, we must be sure the bogus node is available in that block.
+				if ( isEndOfBlock && !CKEDITOR.env.ie )
+					lineBreak.getParent().appendBogus();
+
+				// Now we can remove the text node contents, so the caret doesn't
+				// stop on it.
+				if ( !CKEDITOR.env.ie )
+					lineBreak.getNext().$.nodeValue = '';
+				// IE has different behavior regarding position.
+				if ( CKEDITOR.env.ie )
+					range.setStartAt( lineBreak, CKEDITOR.POSITION_AFTER_END );
+				else
+					range.setStartAt( lineBreak.getNext(), CKEDITOR.POSITION_AFTER_START );
+
+				// Scroll into view, for non IE.
+				if ( !CKEDITOR.env.ie )
+				{
+					var dummy = null;
+
+					// BR is not positioned in Opera and Webkit.
+					if ( !CKEDITOR.env.gecko )
+					{
+						dummy = doc.createElement( 'span' );
+						// We need have some contents for Webkit to position it
+						// under parent node. ( #3681)
+						dummy.setHtml('&nbsp;');
+					}
+					else
+						dummy = doc.createElement( 'br' );
+
+					dummy.insertBefore( lineBreak.getNext() );
+					dummy.scrollIntoView();
+					dummy.remove();
+				}
+			}
+
+			// This collapse guarantees the cursor will be blinking.
+			range.collapse( true );
+
+			range.select( isPre );
+		}
+	};
+
+	var plugin = CKEDITOR.plugins.enterkey,
+		enterBr = plugin.enterBr,
+		enterBlock = plugin.enterBlock,
+		forceMode,
+		headerTagRegex = /^h[1-6]$/;
+
+	function shiftEnter( editor )
+	{
+		// On SHIFT+ENTER we want to enforce the mode to be respected, instead
+		// of cloning the current block. (#77)
+		forceMode = 1;
+
+		return enter( editor, editor.config.shiftEnterMode );
 	}
 
-	function enterBr( editor, mode )
-	{
-		// Get the range for the current selection.
-		var range = getRange( editor ),
-			doc = range.document;
-
-		// Determine the block element to be used.
-		var blockTag = ( mode == CKEDITOR.ENTER_DIV ? 'div' : 'p' );
-
-		var isEndOfBlock = range.checkEndOfBlock();
-
-		var elementPath = new CKEDITOR.dom.elementPath( editor.getSelection().getStartElement() );
-
-		var startBlock = elementPath.block,
-			startBlockTag = startBlock && elementPath.block.getName();
-
-		var isPre = false;
-
-		if ( !forceMode && startBlockTag == 'li' )
-		{
-			enterBlock( editor, mode, range );
-			return;
-		}
-
-		// If we are at the end of a header block.
-		if ( !forceMode && isEndOfBlock && headerTagRegex.test( startBlockTag ) )
-		{
-			// Insert a <br> after the current paragraph.
-			doc.createElement( 'br' ).insertAfter( startBlock );
-
-			// A text node is required by Gecko only to make the cursor blink.
-			if ( CKEDITOR.env.gecko )
-				doc.createText( '' ).insertAfter( startBlock );
-
-			// IE has different behaviors regarding position.
-			range.setStartAt( startBlock.getNext(), CKEDITOR.env.ie ? CKEDITOR.POSITION_BEFORE_START : CKEDITOR.POSITION_AFTER_START );
-		}
-		else
-		{
-			var lineBreak;
-
-			isPre = ( startBlockTag == 'pre' );
-
-			if ( isPre )
-				lineBreak = doc.createText( CKEDITOR.env.ie ? '\r' : '\n' );
-			else
-				lineBreak = doc.createElement( 'br' );
-
-			range.deleteContents();
-			range.insertNode( lineBreak );
-
-			// A text node is required by Gecko only to make the cursor blink.
-			// We need some text inside of it, so the bogus <br> is properly
-			// created.
-			if ( !CKEDITOR.env.ie )
-				doc.createText( '\ufeff' ).insertAfter( lineBreak );
-
-			// If we are at the end of a block, we must be sure the bogus node is available in that block.
-			if ( isEndOfBlock && !CKEDITOR.env.ie )
-				lineBreak.getParent().appendBogus();
-
-			// Now we can remove the text node contents, so the caret doesn't
-			// stop on it.
-			if ( !CKEDITOR.env.ie )
-				lineBreak.getNext().$.nodeValue = '';
-			// IE has different behavior regarding position.
-			if ( CKEDITOR.env.ie )
-				range.setStartAt( lineBreak, CKEDITOR.POSITION_AFTER_END );
-			else
-				range.setStartAt( lineBreak.getNext(), CKEDITOR.POSITION_AFTER_START );
-
-			// Scroll into view, for non IE.
-			if ( !CKEDITOR.env.ie )
-			{
-				var dummy = null;
-
-				// BR is not positioned in Opera and Webkit.
-				if ( !CKEDITOR.env.gecko )
-				{
-					dummy = doc.createElement( 'span' );
-					// We need have some contents for Webkit to position it
-					// under parent node. ( #3681)
-					dummy.setHtml('&nbsp;');
-				}
+	function enter( editor, mode )
+	{
+		// Only effective within document.
+		if ( editor.mode != 'wysiwyg' )
+			return false;
+
+		if ( !mode )
+			mode = editor.config.enterMode;
+
+		// Use setTimout so the keys get cancelled immediatelly.
+		setTimeout( function()
+			{
+				editor.fire( 'saveSnapshot' );	// Save undo step.
+				if ( mode == CKEDITOR.ENTER_BR || editor.getSelection().getStartElement().hasAscendant( 'pre', true ) )
+					enterBr( editor, mode );
 				else
-					dummy = doc.createElement( 'br' );
-
-				dummy.insertBefore( lineBreak.getNext() );
-				dummy.scrollIntoView();
-				dummy.remove();
-			}
-		}
-
-		// This collapse guarantees the cursor will be blinking.
-		range.collapse( true );
-
-		range.select( isPre );
+					enterBlock( editor, mode );
+
+				forceMode = 0;
+			}, 0 );
+
+		return true;
 	}
+
 
 	function getRange( editor )
Index: /CKEditor/branches/features/paste/_source/plugins/pastetext/plugin.js
===================================================================
--- /CKEditor/branches/features/paste/_source/plugins/pastetext/plugin.js	(revision 4677)
+++ /CKEditor/branches/features/paste/_source/plugins/pastetext/plugin.js	(revision 4678)
@@ -53,4 +53,25 @@
 	};
 
+	var enterKeyPlugin = CKEDITOR.plugins.enterkey;
+
+	function doInsertText( doc, text )
+	{
+		// Native text insertion.
+		if( CKEDITOR.env.ie )
+		{
+			var selection = doc.selection;
+			if ( selection.type == 'Control' )
+				selection.clear();
+			selection.createRange().pasteHTML( text );
+		}
+		else
+			doc.execCommand( 'inserthtml', false, text );
+	}
+
+	function doEnter( editor, mode )
+	{
+		enterKeyPlugin[ mode == CKEDITOR.ENTER_BR ? 'enterBr' : 'enterBlock' ]( editor, mode );
+	}
+
 	// Register the plugin.
 	CKEDITOR.plugins.add( 'pastetext',
@@ -84,15 +105,51 @@
 		requires : [ 'clipboard' ]
 	});
+
+	var enterKeyPlugin = CKEDITOR.plugins.enterkey;
+
+	function doInsertText( doc, text )
+	{
+		// Native text insertion.
+		if( CKEDITOR.env.ie )
+		{
+			var selection = doc.selection;
+			if ( selection.type == 'Control' )
+				selection.clear();
+			selection.createRange().pasteHTML( text );
+		}
+		else
+			doc.execCommand( 'inserthtml', false, text );
+	}
+
+	function doEnter( editor, mode )
+	{
+		enterKeyPlugin[ mode == CKEDITOR.ENTER_BR ? 'enterBr' : 'enterBlock' ]( editor, mode );
+	}
+
+	CKEDITOR.editor.prototype.insertText = function( text )
+	{
+		var mode = this.getSelection().getStartElement().hasAscendant( 'pre', true ) ? CKEDITOR.ENTER_BR : this.config.enterMode,
+			doc = this.document.$,
+			self = this,
+			line;
+
+		text = CKEDITOR.tools.htmlEncode( text );
+
+		var startIndex = 0;
+		text.replace( /(?:\r\n)|\n|\r/g, function( match, lastIndex )
+		{
+			line = text.substring( startIndex, lastIndex );
+			startIndex = lastIndex + match.length;
+			line.length && doInsertText( doc, line );
+			// Line-break as an editor enter key result.
+			doEnter( self, mode );
+		} );
+
+		line = text.substring( startIndex, text.length );
+		line.length && doInsertText( doc, line );
+	};
+
 })();
 
-CKEDITOR.editor.prototype.insertText = function( text )
-{
-	text = CKEDITOR.tools.htmlEncode( text );
-
-	// TODO: Replace the following with fill line break processing (see V2).
-	text = text.replace( /(?:\r\n)|\n|\r/g, '<br>' );
-
-	this.insertHtml( text );
-};
 
 /**
