Index: /CKEditor/branches/features/contenteditable/_source/core/dom/node.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/core/dom/node.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/core/dom/node.js	(revision 5565)
@@ -658,4 +658,25 @@
 				}
 			}
+		},
+
+		isReadOnly : function()
+		{
+			var current = this;
+			while( current )
+			{
+				if ( current.type == CKEDITOR.NODE_ELEMENT )
+				{
+					if ( current.is ( 'body' ) )
+						break;
+
+					if ( current.getAttribute( 'contentEditable' ) == 'false' )
+						return true;
+					else if ( current.getAttribute( 'contentEditable' ) == 'false' )
+						break;
+				}
+				current = current.getParent();
+			}
+
+			return false;
 		}
 	}
Index: /CKEditor/branches/features/contenteditable/_source/plugins/blockquote/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/blockquote/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/blockquote/plugin.js	(revision 5565)
@@ -48,5 +48,5 @@
 			var state = editor.getCommand( 'blockquote' ).state,
 				selection = editor.getSelection(),
-				range = selection && selection.getRanges()[0];
+				range = selection && selection.getRanges( true )[0];
 
 			if ( !range )
Index: /CKEditor/branches/features/contenteditable/_source/plugins/enterkey/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/enterkey/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/enterkey/plugin.js	(revision 5565)
@@ -24,4 +24,6 @@
 			// Get the range for the current selection.
 			range = range || getRange( editor );
+			if ( !range )
+				return;
 
 			var doc = range.document;
@@ -189,4 +191,6 @@
 			// Get the range for the current selection.
 			range = range || getRange( editor );
+			if ( !range )
+				return;
 
 			var doc = range.document;
@@ -340,5 +344,5 @@
 	{
 		// Get the selection ranges.
-		var ranges = editor.getSelection().getRanges();
+		var ranges = editor.getSelection().getRanges( true );
 
 		// Delete the contents of all ranges except the first one.
Index: /CKEditor/branches/features/contenteditable/_source/plugins/indent/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/indent/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/indent/plugin.js	(revision 5565)
@@ -269,5 +269,8 @@
 		{
 			var selection = editor.getSelection(),
-				range = selection && selection.getRanges()[0];
+				range = selection && selection.getRanges( true )[0];
+
+			if ( !range )
+				return;
 
 			var startContainer = range.startContainer,
Index: /CKEditor/branches/features/contenteditable/_source/plugins/justify/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/justify/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/justify/plugin.js	(revision 5565)
@@ -74,5 +74,5 @@
 
 			var bookmarks = selection.createBookmarks(),
-				ranges = selection.getRanges();
+				ranges = selection.getRanges( true );
 
 
Index: /CKEditor/branches/features/contenteditable/_source/plugins/link/dialogs/link.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/link/dialogs/link.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/link/dialogs/link.js	(revision 5565)
@@ -1295,5 +1295,5 @@
 				// Create element if current selection is collapsed.
 				var selection = editor.getSelection(),
-					ranges = selection.getRanges();
+					ranges = selection.getRanges( true );
 				if ( ranges.length == 1 && ranges[0].collapsed )
 				{
Index: /CKEditor/branches/features/contenteditable/_source/plugins/list/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/list/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/list/plugin.js	(revision 5565)
@@ -386,5 +386,5 @@
 			var doc = editor.document,
 				selection = editor.getSelection(),
-				ranges = selection && selection.getRanges();
+				ranges = selection && selection.getRanges( true );
 
 			// There should be at least one selected range.
@@ -438,5 +438,5 @@
 			while ( ranges.length > 0 )
 			{
-				range = ranges.shift();
+				range = ranges.pop();
 
 				var boundaryNodes = range.getBoundaryNodes(),
Index: /CKEditor/branches/features/contenteditable/_source/plugins/pagebreak/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/pagebreak/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/pagebreak/plugin.js	(revision 5565)
@@ -83,13 +83,13 @@
 		breakObject = editor.createFakeElement( breakObject, 'cke_pagebreak', 'div' );
 
-		var ranges = editor.getSelection().getRanges();
+		var ranges = editor.getSelection().getRanges( true );
 
 		editor.fire( 'saveSnapshot' );
 
-		for ( var range, i = 0 ; i < ranges.length ; i++ )
+		for ( var range, i = ranges.length - 1 ; i >= 0; i-- )
 		{
 			range = ranges[ i ];
 
-			if ( i > 0 )
+			if ( i < ranges.length -1 )
 				breakObject = breakObject.clone( true );
 
Index: /CKEditor/branches/features/contenteditable/_source/plugins/removeformat/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/removeformat/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/removeformat/plugin.js	(revision 5565)
@@ -36,7 +36,7 @@
 
 				var filter = CKEDITOR.plugins.removeformat.filter;
-				var ranges = editor.getSelection().getRanges();
+				var ranges = editor.getSelection().getRanges( true );
 
-				for ( var i = 0, range ; range = ranges[ i ] ; i++ )
+				for ( var i = ranges.length - 1, range ; range = ranges[ i ] ; i-- )
 				{
 					if ( range.collapsed )
Index: /CKEditor/branches/features/contenteditable/_source/plugins/selection/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/selection/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/selection/plugin.js	(revision 5565)
@@ -476,6 +476,7 @@
 				},
 
-		getRanges :
-			CKEDITOR.env.ie ?
+		getRanges : (function ()
+		{
+			var func = CKEDITOR.env.ie ?
 				( function()
 				{
@@ -565,8 +566,4 @@
 					return function()
 					{
-						var cache = this._.cache;
-						if ( cache.ranges )
-							return cache.ranges;
-
 						// IE doesn't have range support (in the W3C way), so we
 						// need to do some magic to transform selections into
@@ -591,9 +588,9 @@
 							range.setEnd( new CKEDITOR.dom.node( boundaryInfo.container ), boundaryInfo.offset );
 
-							return ( cache.ranges = [ range ] );
+							return [ range ];
 						}
 						else if ( type == CKEDITOR.SELECTION_ELEMENT )
 						{
-							var retval = this._.cache.ranges = [];
+							var retval = [];
 
 							for ( var i = 0 ; i < nativeRange.length ; i++ )
@@ -616,5 +613,5 @@
 						}
 
-						return ( cache.ranges = [] );
+						return [];
 					};
 				})()
@@ -622,7 +619,4 @@
 				function()
 				{
-					var cache = this._.cache;
-					if ( cache.ranges )
-						return cache.ranges;
 
 					// On browsers implementing the W3C range, we simply
@@ -645,7 +639,64 @@
 						ranges.push( range );
 					}
-
-					return ( cache.ranges = ranges );
-				},
+					return ranges;
+				};
+
+			return function( writeMode )
+			{
+				var cache = this._.cache;
+				if ( cache.ranges && !writeMode )
+					return cache.ranges;
+				else if ( !cache.ranges )
+					cache.ranges = func.call( this );
+
+				// Split range into multiple by read-only nodes.
+				if ( writeMode )
+				{
+					var ranges = cache.ranges;
+					for ( var i = 0; i < ranges.length; i++ )
+					{
+						var range = ranges[ i ];
+
+						// Drop range spans inside one ready-only node.
+						var parent = range.getCommonAncestor();
+						if ( parent.isReadOnly())
+							ranges.splice( i, 1 );
+
+						if ( range.collapsed )
+							continue;
+
+						var start = range.getTouchedStartNode(),
+							end = range.getTouchedEndNode(),
+							next = start;
+
+						while( next )
+						{
+							// End of range.
+							if ( end.getPosition( next ) &&
+									!( end.getPosition( next )
+										& ( CKEDITOR.POSITION_FOLLOWING | CKEDITOR.POSITION_CONTAINS ) ) )
+							{
+								break;
+							}
+
+							// Encompass read-only node, split up range around it.
+							if ( next.type == CKEDITOR.NODE_ELEMENT
+								&& next.getAttribute( 'contenteditable' ) == 'false' )
+							{
+								var newRange = range.clone();
+								range.setEndBefore( next );
+								newRange.setStartAfter( next );
+								ranges.splice( i + 1, 0, newRange );
+								break;
+							}
+
+							next = next.getNextSourceNode( false, CKEDITOR.NODE_ELEMENT );
+						}
+					}
+				}
+
+				return cache.ranges;
+			}
+		})(),
 
 		/**
@@ -907,6 +958,12 @@
 			if ( CKEDITOR.env.ie )
 			{
-				// IE doesn't accept multiple ranges selection, so we just
-				// select the first one.
+				if ( ranges.length > 1 )
+				{
+					// IE doesn't accept multiple ranges selection, so we join all into one.
+					var last = ranges[ ranges.length -1 ] ;
+					ranges[ 0 ].setEnd( last.endContainer, last.endOffset );
+					ranges.length = 1;
+				}
+
 				if ( ranges[ 0 ] )
 					ranges[ 0 ].select();
@@ -917,8 +974,29 @@
 			{
 				var sel = this.getNative();
-				sel.removeAllRanges();
+
+				if ( ranges.length )
+					sel.removeAllRanges();
 
 				for ( var i = 0 ; i < ranges.length ; i++ )
 				{
+					if ( i < ranges.length -1 )
+					{
+						var left = ranges[ i  ], right = ranges[ i +1 ];
+						var between = left.clone();
+						between.setStart( left.endContainer, left.endOffset );
+						between.setEnd( right.startContainer, left.startOffset );
+
+						if ( !between.collapsed )
+						{
+							between.shrink( CKEDITOR.NODE_ELEMENT, true );
+							var parent = between.getCommonAncestor();
+							if ( parent.isReadOnly())
+							{
+								left.setEnd( right.endContainer, right.endOffset );
+								ranges.splice( i + 1, 1 );
+							}
+						}
+					}
+
 					var range = ranges[ i ];
 					var nativeRange = this.document.$.createRange();
Index: /CKEditor/branches/features/contenteditable/_source/plugins/specialchar/dialogs/specialchar.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/specialchar/dialogs/specialchar.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/specialchar/dialogs/specialchar.js	(revision 5565)
@@ -16,15 +16,15 @@
 	{
 		var selection = editor.getSelection(),
-			ranges	  = selection.getRanges(),
+			ranges = selection.getRanges( true ),
 			range, textNode;
 
 		editor.fire( 'saveSnapshot' );
 
-		for ( var i = 0, len = ranges.length ; i < len ; i++ )
+		for ( var i = ranges.length - 1; i >= 0 ; i-- )
 		{
 			range = ranges[ i ];
 			range.deleteContents();
 
-			textNode =  CKEDITOR.dom.element.createFromHtml( specialChar );
+			textNode = CKEDITOR.dom.element.createFromHtml( specialChar );
 			range.insertNode( textNode );
 		}
Index: /CKEditor/branches/features/contenteditable/_source/plugins/styles/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/styles/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/styles/plugin.js	(revision 5565)
@@ -1264,9 +1264,10 @@
 		// Get all ranges from the selection.
 		var selection = document.getSelection();
-		var ranges = selection.getRanges();
+		var ranges = selection.getRanges( true );
+
 		var func = remove ? this.removeFromRange : this.applyToRange;
 
 		// Apply the style to the ranges.
-		for ( var i = 0 ; i < ranges.length ; i++ )
+		for ( var i = ranges.length -1 ; i >= 0 ; i-- )
 			func.call( this, ranges[ i ] );
 
Index: /CKEditor/branches/features/contenteditable/_source/plugins/wysiwygarea/plugin.js
===================================================================
--- /CKEditor/branches/features/contenteditable/_source/plugins/wysiwygarea/plugin.js	(revision 5564)
+++ /CKEditor/branches/features/contenteditable/_source/plugins/wysiwygarea/plugin.js	(revision 5565)
@@ -67,5 +67,8 @@
 
 			var selection = this.getSelection(),
-				ranges = selection.getRanges();
+				ranges = selection.getRanges( true );
+
+			if ( !ranges.length )
+				return;
 
 			var selIsLocked = selection.isLocked;
