Index: _source/core/dom/node.js
===================================================================
--- _source/core/dom/node.js	(revision 6602)
+++ _source/core/dom/node.js	(working copy)
@@ -534,6 +534,27 @@
 			return false;
 		},
 
+		/**
+		 * Get an ascendant whose tag name is included in
+		 * the provided hash object
+		 */
+		getAscendantInHash : function( hash, includeSelf )
+		{
+			var $ = this.$;
+
+			if ( !includeSelf )
+				$ = $.parentNode;
+
+			while ( $ )
+			{
+				if ( $.nodeName && hash[ $.nodeName.toLowerCase() ] )
+					return new CKEDITOR.dom.node( $ );
+
+				$ = $.parentNode;
+			}
+			return null;
+		},
+
 		move : function( target, toStart )
 		{
 			target.append( this.remove(), toStart );
Index: _source/plugins/styles/plugin.js
===================================================================
--- _source/plugins/styles/plugin.js	(revision 6603)
+++ _source/plugins/styles/plugin.js	(working copy)
@@ -100,7 +100,9 @@
 
 		var element = this.element = ( styleDefinition.element || '*' ).toLowerCase();
 
-		this.type =
+		// A style definition can specify how it wants to be applied, although it
+		// might not work as expected (can't really create a td out of nowhere)
+		this.type = styleDefinition.type ||
 			blockElements[ element ] ?
 				CKEDITOR.STYLE_BLOCK
 			: objectElements[ element ] ?
@@ -108,6 +110,12 @@
 			:
 				CKEDITOR.STYLE_INLINE;
 
+		// Optionally a definition can define a set of elements that it can be applied to
+		this.elements = styleDefinition.elements;
+		// In that case, it will be applied like an object style: only to existing elements
+		if ( this.elements )
+			this.type = CKEDITOR.STYLE_OBJECT
+
 		this._ =
 		{
 			definition : styleDefinition
@@ -179,9 +187,13 @@
 							  && ( element == elementPath.block || element == elementPath.blockLimit ) )
 							continue;
 
-						if( this.type == CKEDITOR.STYLE_OBJECT
-							 && !( element.getName() in objectElements ) )
+						if( this.type == CKEDITOR.STYLE_OBJECT )
+						{
+							var name = element.getName();
+							if ( name != this.element &&
+								!(this.elements && ( name in this.elements)) )
 								continue;
+						}
 
 						if ( this.checkElementRemovable( element, true ) )
 							return true;
@@ -203,7 +215,8 @@
 					break;
 
 				case CKEDITOR.STYLE_OBJECT :
-					return elementPath.lastElement.getAscendant( this.element, true );
+					var root = elementPath.lastElement;
+					return this.elements ? root.getAscendantInHash( this.elements, true ) : root.getAscendant( this.element, true );
 			}
 
 			return true;
@@ -217,10 +230,11 @@
 				return false;
 
 			var def = this._.definition,
-				attribs;
+				attribs,
+				name = element.getName();
 
 			// If the element name is the same as the style name.
-			if ( element.getName() == this.element )
+			if ( name == this.element || ( this.elements && name in this.elements ) )
 			{
 				// If no attributes are defined in the element.
 				if ( !fullMatch && !element.hasAttributes() )
@@ -814,14 +828,14 @@
 	function applyObjectStyle( range )
 	{
 		var root = range.getCommonAncestor( true, true ),
-			element = root.getAscendant( this.element, true );
+			element = this.elements ? root.getAscendantInHash( this.elements, true ) : root.getAscendant( this.element, true );
 		element && setupElement( element, this );
 	}
 
 	function removeObjectStyle( range )
 	{
 		var root = range.getCommonAncestor( true, true ),
-			element = root.getAscendant( this.element, true );
+			element = this.elements ? root.getAscendantInHash( this.elements, true ) : root.getAscendant( this.element, true );
 
 		if ( !element )
 			return;
