Index: _source/plugins/styles/plugin.js
===================================================================
--- _source/plugins/styles/plugin.js	(revision 5206)
+++ _source/plugins/styles/plugin.js	Sun Mar 07 20:01:20 CST 2010
@@ -138,6 +138,40 @@
 						: null ).call( this, range );
 		},
 
+		// Removes any conflicting styles from within the specified range..
+		removeConflictsFromRange : function ( range )
+		{
+			var style = this,
+					overrides = getOverrides( style ),
+					candidates1 = [],
+					candidates2 = [];
+
+			var walker = new CKEDITOR.dom.walker( range );
+			walker.evaluator = function( node )
+			{
+				if( node.type == CKEDITOR.NODE_ELEMENT )
+				{
+					if( node.is( style.element ) )
+						candidates1.push( node );
+					if( node.getName() in overrides )
+						candidates2.push( node );
+				}
+			};
+			walker.lastForward();
+
+			var count1 = candidates1.length,
+					count2 = candidates2.length;
+			
+			// First remove from element any style conflictions.
+			for ( var i = 0; i < count1; i++ )
+				removeFromElement( style,  candidates1[ i ] );
+
+			// Now remove any other element with different name that is
+			// defined to be overriden.
+			for ( i = 0; i < count2; i++ )
+				removeOverrides( candidates2[ i ], overrides[ candidates2[ i ].getName() ] ) ;
+		},
+
 		applyToObject : function( element )
 		{
 			setupElement( element, this );
@@ -310,6 +344,12 @@
 		range.enlarge( CKEDITOR.ENLARGE_ELEMENT );
 		range.trim();
 
+		// Remove all style conflictions within the range,
+		// e.g. style="color:red" is conflicting with style="color:blue".
+		var enlargedBookmark = range.createBookmark();
+		this.removeConflictsFromRange( range );
+		range.moveToBookmark( enlargedBookmark );
+
 		// Get the first node to be processed and the last, which concludes the
 		// processing.
 		var boundaryNodes = range.getBoundaryNodes();
@@ -480,10 +520,6 @@
 					// Move the contents of the range to the style element.
 					styleRange.extractContents().appendTo( styleNode );
 
-					// Here we do some cleanup, removing all duplicated
-					// elements from the style element.
-					removeFromInsideElement( this, styleNode );
-
 					// Insert it into the range position (it is collapsed after
 					// extractContents.
 					styleRange.insertNode( styleNode );
@@ -900,36 +936,6 @@
 		removeNoAttribsElement( element );
 	}
 
-	// Removes a style from inside an element.
-	function removeFromInsideElement( style, element )
-	{
-		var def = style._.definition,
-			attribs = def.attributes,
-			styles = def.styles,
-			overrides = getOverrides( style );
-
-		var innerElements = element.getElementsByTag( style.element );
-
-		for ( var i = innerElements.count(); --i >= 0 ; )
-			removeFromElement( style,  innerElements.getItem( i ) );
-
-		// Now remove any other element with different name that is
-		// defined to be overriden.
-		for ( var overrideElement in overrides )
-		{
-			if ( overrideElement != style.element )
-			{
-				innerElements = element.getElementsByTag( overrideElement ) ;
-				for ( i = innerElements.count() - 1 ; i >= 0 ; i-- )
-				{
-					var innerElement = innerElements.getItem( i );
-					removeOverrides( innerElement, overrides[ overrideElement ] ) ;
-				}
-			}
-		}
-
-	}
-
 	/**
 	 *  Remove overriding styles/attributes from the specific element.
 	 *  Note: Remove the element if no attributes remain.
