Index: CKEditor/branches/features/pasting/_source/core/htmlparser/element.js
===================================================================
--- CKEditor/branches/features/pasting/_source/core/htmlparser/element.js	(revision 4282)
+++ CKEditor/branches/features/pasting/_source/core/htmlparser/element.js	(revision 4285)
@@ -103,5 +103,5 @@
 			var element = this,
 				writeName = element.name,
-				a, value;
+				a, newAttrName, value;
 
 			var isChildrenFiltered;
@@ -156,39 +156,33 @@
 			writer.openTag( writeName, attributes );
 
-			if ( writer.sortAttributes )
-			{
-				// Copy all attributes to an array.
-				var attribsArray = [];
+			// Copy all attributes to an array.
+			var attribsArray = [];
+			// Iterate over the attributes twice since filters may alter
+			// other attributes.
+			for( var i = 0 ; i < 2; i++ )
+			{
 				for ( a in attributes )
 				{
+					newAttrName = a;
 					value = attributes[ a ];
-
-					if ( filter && ( !( a = filter.onAttributeName( a ) ) || ( value = filter.onAttribute( element, a, value ) ) === false ) )
-						continue;
-
-					attribsArray.push( [ a, value ] );
+					if( i == 1 )
+						attribsArray.push( [ a, value ] );
+					else if ( filter &&
+					          ( !( newAttrName = filter.onAttributeName( a ) )
+							          || ( value = filter.onAttribute( element, newAttrName, value ) ) === false ) )
+						delete attributes[ a ];
+					else
+						attributes[ newAttrName ] = value;
 				}
-
-				// Sort the attributes by name.
+			}
+			// Sort the attributes by name.
+			if ( writer.sortAttributes )
 				attribsArray.sort( sortAttribs );
 
-				// Send the attributes.
-				for ( var i = 0, len = attribsArray.length ; i < len ; i++ )
-				{
-					var attrib = attribsArray[ i ];
-					writer.attribute( attrib[0], attrib[1] );
-				}
-			}
-			else
-			{
-				for ( a in attributes )
-				{
-					value = attributes[ a ];
-
-					if ( filter && ( !( a = filter.onAttributeName( a ) ) || ( value = filter.onAttribute( element, a, value ) ) === false ) )
-						continue;
-
-					writer.attribute( a, value );
-				}
+			// Send the attributes.
+			for ( i = 0, len = attribsArray.length ; i < len ; i++ )
+			{
+				var attrib = attribsArray[ i ];
+				writer.attribute( attrib[0], attrib[1] );
 			}
 
Index: CKEditor/branches/features/pasting/_source/plugins/pastefromword/plugin.js
===================================================================
--- CKEditor/branches/features/pasting/_source/plugins/pastefromword/plugin.js	(revision 4282)
+++ CKEditor/branches/features/pasting/_source/plugins/pastefromword/plugin.js	(revision 4285)
@@ -48,11 +48,91 @@
 	} );
 
+	var fragmentPrototype = CKEDITOR.htmlParser.fragment.prototype,
+		elementPrototype = CKEDITOR.htmlParser.element.prototype;
+
+	fragmentPrototype.onlyChild = elementPrototype.onlyChild = function()
+	{
+		var children = this.children,
+			count = children.length,
+			firstChild = ( count == 1 ) && children[ 0 ];
+		return firstChild || null;
+	};
+
+	elementPrototype.anyChildWithName = function( tagName, includingSelf )
+	{
+		var children = this.children,
+			count = children && children.length,
+			childs = [];
+
+		if( includingSelf && this.name == tagName )
+			childs.push( this );
+
+		for ( var i = 0; i < count; i++ )
+		{
+			if( children[ i ].name  )
+				childs = childs.concat( children[ i ].anyChildWithName( tagName, true ) );
+		}
+		return childs;
+	};
+
+	fragmentPrototype.firstTextChild = elementPrototype.firstTextChild = function()
+	{
+		var child;
+		for( var i = 0 ; i < this.children.length ; i++ )
+		{
+			child = this.children[ i ];
+			if( child.value )
+				return child;
+		}
+	};
+
+	// Adding a (set) of styles to the element's attributes.
+	elementPrototype.addStyle = function( name, value )
+	{
+		var styleText, addingStyleText = '';
+		// style literal.
+		if( typeof name == 'object' )
+		{
+			for( var style in name )
+			{
+				if( name.hasOwnProperty( style) )
+					addingStyleText += style + ':' + name[ style ] + ';';
+			}
+		}
+		// name/value pair.
+		else if( value )
+			addingStyleText += name + ':' + value + ';';
+		// raw style text form.
+		else if( name )
+			addingStyleText += name;
+
+		if( !this.attributes )
+			this.attributes = {};
+		styleText = this.attributes.style;
+		if( !styleText )
+			this.attributes.style = "";
+		else if( !/;$/.test( styleText ) )
+			this.attributes.style = styleText + ';';
+
+		this.attributes.style += addingStyleText;
+	}
+
+	/**
+	 * Return the DTD-valid parent tag names of the specified one.
+	 * @param tagName
+	 */
+	CKEDITOR.dtd.parentOf = function( tagName )
+	{
+		var result = {};
+		for( var tag in this )
+		{
+			if( tag.indexOf( '$' ) == -1 && this[ tag ][ tagName ] )
+				result[ tag ] = 1;
+		}
+		return result;
+	};
+	
 	CKEDITOR.plugins.pastefromword =
 	{
-		_ :
-		{
-			cachedRules : null
-		},
-
 		utils :
 		{
@@ -150,6 +230,7 @@
 					return true;
 				}
-			}
-
+			},
+
+			listDtdParents : CKEDITOR.dtd.parentOf( 'ol' )
 		},
 
@@ -165,6 +246,8 @@
 
 				/**
-				 * A filter dedicated on the 'style' attribute for dropping/replacing style rules.
-				 * @param styles {Array} A triple in form of [ styleNameRegexp, styleValueRegexp, newStyleValue ] where the last two are optional.
+				 * A filter dedicated on the 'style' attribute filtering, e.g. dropping/replacing style properties.
+				 * @param styles {Array} in form of [ styleNameRegexp, styleValueRegexp,
+				 *  newStyleValue/newStyleGenerator, newStyleName ] where only the first
+				 *  parameter is mandatory.
 				 */
 				stylesFilter : function( styles )
@@ -283,10 +366,6 @@
 		getRules : function( editor )
 		{
-			var cached;
-			if( cached = this._.cachedRules )
-				return cached;
-
 			var dtd = CKEDITOR.dtd,
-				listDtdParents = dtd.parentOf( 'ol' ),
+				config = editor.config,
 				filters = this.filters,
 				falsyFilter = filters.falsyFilter,
@@ -299,5 +378,5 @@
 				containsNothingButSpaces = this.utils.isContainingOnlySpaces,
 				resolveListItem = this.utils.resolveList,
-				config = editor.config,
+				listDtdParents = this.utils.listDtdParents,
 				ignoreFontFace = config.pasteFromWordIgnoreFontFace;
 
@@ -650,6 +729,5 @@
 					[ /(?:v|o):\w+/, '' ],
 					// Remove lang/language attributes.
-					[ /^lang/, '' ],
-					ignoreFontFace ? [ /^(?:face|font|size)/, '' ] : null
+					[ /^lang/, '' ]
 				],
 
@@ -658,12 +736,13 @@
 					'style' : stylesFilter(
 					[
-						[ /mso-/ ],
-						[ /-moz-/ ],
-						[ 'background-color', 'transparent' ],
-						// Firefox: replacing Mozilla-specific color value.
-						CKEDITOR.env.gecko ? [ '-color', null, function( value, element )
-						{
-							return value.replace( /-moz-use-text-color/g, 'transparent' );	
-						} ]: null,
+						[ /^mso-/ ],
+						// Fixing color values.
+						[ /-color$/, null, function( value )
+						{
+							if( value == 'transparent' )
+								return false;
+							if( CKEDITOR.env.gecko )
+								return value.replace( /-moz-use-text-color/g, 'transparent' );
+						} ],
 						// Remove default border style.
 						[ /^border$/, /^(:?medium\s*)?none\s*$/ ],
@@ -683,5 +762,5 @@
 							return value;
 						} ],
-						[ 'margin', /0(?:cm|in) 0(?:cm|in) 0pt/ ],
+						[ /^margin$/, /0(?:cm|in) 0(?:cm|in) 0pt/ ],
 						[ 'text-indent', '0cm' ],
 						[ 'page-break-before' ],
@@ -715,5 +794,5 @@
 					'valign' : function( value, element )
 					{
-						if( value != 'top' )
+						if ( value != 'top' )
 							element.addStyle( 'vertical-align', value );
 						return false;
@@ -749,90 +828,4 @@
 		}
 	};
-
-	var fragmentPrototype = CKEDITOR.htmlParser.fragment.prototype,
-		elementPrototype = CKEDITOR.htmlParser.element.prototype;
-
-	fragmentPrototype.onlyChild = elementPrototype.onlyChild = function()
-	{
-		var children = this.children,
-			count = children.length,
-			firstChild = ( count == 1 ) && children[ 0 ];
-		return firstChild || null;
-	};
-
-	elementPrototype.anyChildWithName = function( tagName, includingSelf )
-	{
-		var children = this.children,
-			count = children && children.length,
-			childs = [];
-
-		if( includingSelf && this.name == tagName )
-			childs.push( this );
-
-		for ( var i = 0; i < count; i++ )
-		{
-			if( children[ i ].name  )
-				childs = childs.concat( children[ i ].anyChildWithName( tagName, true ) );
-		}
-		return childs;
-	};
-
-	fragmentPrototype.firstTextChild = elementPrototype.firstTextChild = function()
-	{
-		var child;
-		for( var i = 0 ; i < this.children.length ; i++ )
-		{
-			child = this.children[ i ];
-			if( child.value )
-				return child;
-		}
-	};
-
-	// Adding a (set) of styles to the element's attributes.
-	elementPrototype.addStyle = function( name, value )
-	{
-		var styleText, addingStyleText = '';
-		// style literal.
-		if( typeof name == 'object' )
-		{
-			for( var style in name )
-			{
-				if( name.hasOwnProperty( style) )
-					addingStyleText += style + ':' + name[ style ] + ';';
-			}
-		}
-		// name/value pair.
-		else if( value )
-			addingStyleText += name + ':' + value + ';';
-		// raw style text form.
-		else if( name )
-			addingStyleText += name;
-
-		if( !this.attributes )
-			this.attributes = {};
-		styleText = this.attributes.style;
-		if( !styleText )
-			this.attributes.style = "";
-		else if( !/;$/.test( styleText ) )
-			this.attributes.style = styleText + ';';
-
-		this.attributes.style += addingStyleText;
-	}
-
-	/**
-	 * Return the DTD-valid parent tag names of the specified one.
-	 * @param tagName
-	 */
-	CKEDITOR.dtd.parentOf = function( tagName )
-	{
-		var result = {};
-		for( var tag in this )
-		{
-			if( tag.indexOf( '$' ) == -1 && this[ tag ][ tagName ] )
-				result[ tag ] = 1;
-		}
-		return result;
-	};
-
 } )();
 
