Index: /FCKeditor/trunk/editor/_source/commandclasses/fckindentcommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/commandclasses/fckindentcommands.js	(revision 834)
+++ /FCKeditor/trunk/editor/_source/commandclasses/fckindentcommands.js	(revision 835)
@@ -28,4 +28,19 @@
 	this.IndentCSSProperty = FCKConfig.ContentLangDirection.IEquals( 'ltr' ) ? 'marginLeft' : 'marginRight' ;
 }
+
+FCKIndentCommand._InitIndentModeParameters = function()
+{
+	if ( FCKConfig.IndentClasses && FCKConfig.IndentClasses.length > 0 )
+	{
+		this._UseIndentClasses = true ;
+		this._IndentClassMap = {} ;
+		for ( var i = 0 ; i < FCKConfig.IndentClasses.length ;i++ )
+			this._IndentClassMap[FCKConfig.IndentClasses[i]] = i + 1 ;
+		this._ClassNameRegex = new RegExp( '(?:^|\\s+)(' + FCKConfig.IndentClasses.join( '|' ) + ')(?=$|\\s)' ) ;
+	}
+	else
+		this._UseIndentClasses = false ;
+}
+
 
 FCKIndentCommand.prototype =
@@ -56,7 +71,45 @@
 	GetState : function()
 	{
-		// TODO: If we're not in a list, and the starting block's indentation is zero, and the current
+		// Disabled if not WYSIWYG.
+		if ( FCK.EditMode != FCK_EDITMODE_WYSIWYG || ! FCK.EditorWindow )
+			return FCK_TRISTATE_DISABLED ;
+
+		// Initialize parameters if not already initialzed.
+		if ( FCKIndentCommand._UseIndentClasses == undefined )
+			FCKIndentCommand._InitIndentModeParameters() ;
+
+		// If we're not in a list, and the starting block's indentation is zero, and the current
 		// command is the outdent command, then we should return FCK_TRISTATE_DISABLED. 
-		return FCK_TRISTATE_OFF;
+		var startContainer = FCKSelection.GetBoundaryParentElement( true ) ;
+		var endContainer = FCKSelection.GetBoundaryParentElement( false ) ;
+		var listNode = FCKDomTools.GetCommonParentNode( startContainer, endContainer, ['ul','ol'] ) ;
+
+		if ( ( ! FCKIndentCommand._UseIndentClasses && this.Name.IEquals( 'indent' ) ) || listNode )
+			return FCK_TRISTATE_OFF;
+
+		var path = new FCKElementPath( startContainer ) ;
+		if ( FCKIndentCommand._UseIndentClasses )
+		{
+			var indentClass = path.Block.className.match( FCKIndentCommand._ClassNameRegex ) ;
+			var indentStep = 0 ;
+			if ( indentClass != null )
+			{
+				indentClass = indentClass[1] ;
+				indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
+			}
+			if ( ( this.Name == 'outdent' && indentStep == 0 ) ||
+					( this.Name == 'indent' && indentStep == FCKConfig.IndentClasses.length ) )
+				return FCK_TRISTATE_DISABLED ;
+			return FCK_TRISTATE_OFF ;
+		}
+		else
+		{
+			var indent = parseInt( path.Block.style[this.IndentCSSProperty], 10 ) ;
+			if ( isNaN( indent ) )
+				indent = 0 ;
+			if ( indent <= 0 )
+				return FCK_TRISTATE_DISABLED ;
+			return FCK_TRISTATE_OFF ;
+		}
 	},
 
@@ -76,11 +129,39 @@
 				continue ;
 
-			// Offset distance is assumed to be in pixels for now.
-			var currentOffset = parseInt( block.style[this.IndentCSSProperty], 10 ) ;
-			if ( isNaN( currentOffset ) )
-				currentOffset = 0 ;
-			currentOffset += this.Offset ;
-			currentOffset = Math.max( currentOffset, 0 ) ;
-			block.style[this.IndentCSSProperty] = currentOffset + 'px' ;
+			if ( FCKIndentCommand._UseIndentClasses )
+			{
+				// Transform current class name to indent step index.
+				var indentClass = block.className.match( FCKIndentCommand._ClassNameRegex ) ;
+				var indentStep = 0 ;
+				if ( indentClass != null )
+				{
+					indentClass = indentClass[1] ;
+					indentStep = FCKIndentCommand._IndentClassMap[indentClass] ;
+				}
+
+				// Operate on indent step index, transform indent step index back to class name.
+				if ( this.Name.IEquals( 'outdent' ) )
+					indentStep-- ;
+				else if ( this.Name.IEquals( 'indent' ) )
+					indentStep++ ;
+				indentStep = Math.min( indentStep, FCKConfig.IndentClasses.length ) ;
+				indentStep = Math.max( indentStep, 0 ) ;
+				var className = block.className.replace( FCKIndentCommand._ClassNameRegex, '' ) ;
+				if ( indentStep < 1 )
+					block.className = className ;
+				else
+					block.className = ( className.length > 0 ? className + ' ' : '' ) + 
+						FCKConfig.IndentClasses[indentStep - 1] ;
+			}
+			else
+			{
+				// Offset distance is assumed to be in pixels for now.
+				var currentOffset = parseInt( block.style[this.IndentCSSProperty], 10 ) ;
+				if ( isNaN( currentOffset ) )
+					currentOffset = 0 ;
+				currentOffset += this.Offset ;
+				currentOffset = Math.max( currentOffset, 0 ) ;
+				block.style[this.IndentCSSProperty] = currentOffset + 'px' ;
+			}
 		}
 	},
@@ -90,5 +171,17 @@
 		// Our starting and ending points of the range might be inside some blocks under a list item...
 		// So before playing with the iterator, we need to expand the block to include the list items.
-		// TODO
+		var startContainer = range.StartContainer ;
+		var endContainer = range.EndContainer ;
+		while ( startContainer && ! startContainer.nodeName.IEquals( ['li', 'ul', 'ol'] ) ) 
+			startContainer = startContainer.parentNode ;
+		while ( endContainer && ! endContainer.nodeName.IEquals( ['li', 'ul', 'ol'] ) )
+			endContainer = endContainer.parentNode ;
+		range.SetStart( startContainer, 1 ) ;
+		range.SetEnd( endContainer, 2 ) ;
+
+		if ( ! startContainer || ! endContainer )
+			return ;
+
+		// Now we can iterate over the individual items.
 		var iterator = new FCKDomRangeIterator( range ) ;
 		var block ;
Index: /FCKeditor/trunk/fckconfig.js
===================================================================
--- /FCKeditor/trunk/fckconfig.js	(revision 834)
+++ /FCKeditor/trunk/fckconfig.js	(revision 835)
@@ -62,4 +62,8 @@
 // The distance of an indentation step, in pixels.
 FCKConfig.IndentLength = 40 ;
+
+// Alternatively, FCKeditor allows the use of CSS classes for block indentation.
+// This overrides the IndentLength setting.
+FCKConfig.IndentClasses = [] ;
 
 FCKConfig.ProcessHTMLEntities	= true ;
