Index: CKEditor/trunk/_source/core/dom/element.js
===================================================================
--- CKEditor/trunk/_source/core/dom/element.js	(revision 3516)
+++ CKEditor/trunk/_source/core/dom/element.js	(revision 3517)
@@ -431,5 +431,8 @@
 						case 'style':
 							// IE does not return inline styles via getAttribute(). See #2947.
-							return this.$.style.cssText;
+							var styleText = this.$.style.cssText;
+							return styleText.toLowerCase().replace(
+								/\s*(?:;\s*|$)/, ';').replace(
+									/([^;])$/, '$1;');
 					}
 
Index: CKEditor/trunk/_source/plugins/find/dialogs/find.js
===================================================================
--- CKEditor/trunk/_source/plugins/find/dialogs/find.js	(revision 3516)
+++ CKEditor/trunk/_source/plugins/find/dialogs/find.js	(revision 3517)
@@ -27,5 +27,5 @@
 	var cursorStep = function()
 	{
-		var obj = {
+		return {
 			textNode : this.textNode,
 			offset : this.offset,
@@ -34,5 +34,4 @@
 			hitMatchBoundary : this._.matchBoundary
 		};
-		return obj;
 	};
 
@@ -73,8 +72,9 @@
 
 		/**
-		 * Iterator which walk through document char by char.
-		 * @param {Object} start
-		 * @param {Number} offset
-		 * @param {Boolean} isStrict
+		 * Iterator which walk through the specified range char by char. By
+		 * default the walking will not stop at the character boundaries, until
+		 * the end of the range is encountered.
+		 * @param { CKEDITOR.dom.range } range
+		 * @param {Boolean} matchWord Whether the walking will stop at character boundary.
 		 */
 		var characterWalker = function( range , matchWord )
@@ -194,56 +194,19 @@
 				return range;
 			},
-
+			/**
+			 * Reflect the latest changes from dom range.
+			 */
 			updateFromDomRange : function( domRange )
 			{
-				var startNode = domRange.startContainer,
-					startIndex = domRange.startOffset,
-					endNode = domRange.endContainer,
-					endIndex = domRange.endOffset,
-					boundaryNodes = domRange.getBoundaryNodes();
-
-				if ( startNode.type != CKEDITOR.NODE_TEXT )
-				{
-					startNode = boundaryNodes.startNode;
-					while ( startNode.type != CKEDITOR.NODE_TEXT )
-						startNode = startNode.getFirst();
-					startIndex = 0;
-				}
-
-				if ( endNode.type != CKEDITOR.NODE_TEXT )
-				{
-					endNode = boundaryNodes.endNode;
-					while ( endNode.type != CKEDITOR.NODE_TEXT )
-						endNode = endNode.getLast();
-					endIndex = endNode.getLength();
-				}
-
-				// If the endNode is an empty text node, our walker would just walk through
-				// it without stopping. So need to backtrack to the nearest non-emtpy text
-				// node.
-				if ( endNode.getLength() < 1 )
-				{
-					while ( ( endNode = endNode.getPreviousSourceNode() )
-						   && !( endNode.type == CKEDITOR.NODE_TEXT
-									&& endNode.getLength() > 0 ) )
-					{ /*jsl:pass*/ }
-
-					endIndex = endNode.getLength();
-				}
-
-				// Rebuild the character range.
 				var cursor,
-						walker = new characterWalker(
-								getRangeAfterCursor(
-													( { textNode: startNode, offset : startIndex } ),
-													true ) );
+						walker = new characterWalker( domRange );
 				this._.cursors = [];
 				do
 				{
 					cursor = walker.next();
-					this._.cursors.push( cursor );
-				}
-				while ( !( cursor.textNode.equals( endNode )
-							 && cursor.offset == endIndex - 1 ) );
+					if ( cursor.character )
+						this._.cursors.push( cursor );
+				}
+				while ( cursor.character );
 				this._.rangeLength = this._.cursors.length;
 			},
@@ -440,5 +403,4 @@
 				}
 
-				return null;
 			},
 
@@ -536,32 +498,31 @@
 				matchCyclic, matchReplaceAll )
 			{
-				var replaceResult = false;
-				if ( this.range && this.range.isMatched() )
-				{
-					var domRange = this.range.toDomRange();
+				// Successiveness of current replace/find.
+				var result = false;
+
+				// 1. Perform the replace when there's already a match here.
+				// 2. Otherwise perform the find but don't replace it immediately.
+				if ( this.matchRange && this.matchRange.isMatched() )
+				{
+					var domRange = this.matchRange.toDomRange();
 					var text = editor.document.createText( newString );
 					domRange.deleteContents();
 					domRange.insertNode( text );
-					this.range.updateFromDomRange( domRange );
-
+					this.matchRange.updateFromDomRange( domRange );
+					this.matchRange._.isMatched = false;
 					this.replaceCounter++;
-					replaceResult = true;
-				}
-
-				var findResult = this.find( pattern, matchCase, matchWord, matchCyclic );
-				if ( findResult && matchReplaceAll )
+					result = true;
+				}
+				else
+					result = this.find( pattern, matchCase, matchWord, matchCyclic );
+				
+				// Recusively replace all matches.
+				if ( matchReplaceAll && result )
 					this.replace.apply( this, Array.prototype.slice.call( arguments ) );
+
 				return matchReplaceAll ?
-					this.replaceCounter : replaceResult || findResult;
+					this.replaceCounter : result;
 			}
 		};
-
-		/**
-		 * Get the default cursor which is the start of this document.
-		 */
-		function getDefaultStartCursor()
-		{
-			return { textNode : editor.document.getBody(), offset: 0 };
-		}
 
 		/**
Index: CKEditor/trunk/_source/plugins/styles/plugin.js
===================================================================
--- CKEditor/trunk/_source/plugins/styles/plugin.js	(revision 3516)
+++ CKEditor/trunk/_source/plugins/styles/plugin.js	(revision 3517)
@@ -198,6 +198,5 @@
 						if ( attName == '_length' )
 							continue;
-
-						if ( compareAttributeValues(attName, attribs[attName], element.getAttribute( attName ) ) )
+						if ( attribs[attName] == element.getAttribute( attName ) )
 						{
 							if ( !fullMatch )
@@ -270,11 +269,6 @@
 		// we normalize it to the browser format.
 		if ( stylesText.length )
-		{
 			stylesText = normalizeCssText( stylesText );
-
-			if ( stylesText.length )
-				stylesText = stylesText.replace( semicolonFixRegex, ';' );
-		}
-
+		
 		// Return it, saving it to the next request.
 		return ( styleDefinition._ST = stylesText );
@@ -890,5 +884,4 @@
 	}
 
-	var spacesRegex = /\s+/g;
 
 	// Returns an object that can be used for style matching comparison.
@@ -913,5 +906,5 @@
 			{
 				length++;
-				attribs[ styleAtt.toLowerCase() ] = styleAttribs[ styleAtt ].toLowerCase();
+				attribs[ styleAtt ] = styleAttribs[ styleAtt ];
 			}
 		}
@@ -919,10 +912,9 @@
 		// Includes the style definitions.
 		var styleText = CKEDITOR.style.getStyleText( styleDefinition );
-		if ( styleText.length > 0 )
+		if ( styleText )
 		{
 			if ( !attribs[ 'style' ] )
 				length++;
-
-			attribs['style'] = styleText.replace( spacesRegex, '' ).toLowerCase();
+			attribs[ 'style' ] = styleText;
 		}
 
@@ -1002,29 +994,7 @@
 		// Injects the style in a temporary span object, so the browser parses it,
 		// retrieving its final format.
-		var tempSpan = document.createElement( 'span' );
-		tempSpan.style.cssText = unparsedCssText;
-		return tempSpan.style.cssText;
-	}
-
-	// valueA is our internal "for comparison" value.
-	// valueB is the value retrieved from the element.
-	function compareAttributeValues( attName, valueA, valueB )
-	{
-		if ( valueA == valueB || ( !valueA && !valueB ) )
-			return true;
-		else if ( !valueA || !valueB )
-			return false;
-
-		valueB = valueB.toLowerCase();
-
-		if ( attName == 'style' )
-		{
-			valueB = valueB.replace( spacesRegex, '' );
-			if ( valueB.charAt( valueB.length - 1 ) != ';' )
-				valueB += ';';
-		}
-
-		// Return true if they match or if valueA is null and valueB is an empty string
-		return ( valueA == valueB );
+		var temp = new CKEDITOR.dom.element( 'span' );
+		temp.setAttribute( 'style', unparsedCssText );
+		return temp.getAttribute( 'style' );
 	}
 
Index: CKEditor/trunk/_source/tests/core/dom/element.html
===================================================================
--- CKEditor/trunk/_source/tests/core/dom/element.html	(revision 3516)
+++ CKEditor/trunk/_source/tests/core/dom/element.html	(revision 3517)
@@ -173,5 +173,5 @@
 			element.setAttribute( 'style', 'position: absolute;' );
 
-			assert.areEqual( 'position:absolute', document.getElementById( 'test1' ).style.cssText.replace( /[\s;]/g, '' ).toLowerCase() );
+			assert.areEqual( 'position: absolute;', element.getAttribute( 'style' ) );
 		},
 
@@ -202,5 +202,5 @@
 
 			assert.areSame( 'Test', document.getElementById( 'test1' ).className, 'class is wrong' );
-			assert.areEqual( 'position:absolute', document.getElementById( 'test1' ).style.cssText.replace( /[\s;]/g, '' ).toLowerCase(), 'style is wrong' );
+			assert.areEqual( 'position: absolute;', element.getAttribute( 'style'), 'style is wrong' );
 			assert.areEqual( 'TestName', document.getElementById( 'test1' ).name, 'name is wrong' );
 			assert.areEqual( 5, document.getElementById( 'test1' ).rows, 'rows is wrong' );
@@ -415,5 +415,5 @@
 			element.removeAttribute( 'class' );
 
-			assert.areEqual( 'float:right', element.getAttribute( 'style' ).toLowerCase().replace( /[ ;]/g, '' ) );
+			assert.areEqual( 'float: right;', element.getAttribute( 'style' ) );
 
 			element.removeAttribute( 'style' );
