Index: /FCKeditor/trunk/editor/_source/classes/fckdomrange.js
===================================================================
--- /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 833)
+++ /FCKeditor/trunk/editor/_source/classes/fckdomrange.js	(revision 834)
@@ -664,5 +664,7 @@
 
 					// In Gecko, the last child node must be a bogus <br>.
-					if ( FCKBrowserInfo.IsGecko )
+					// Note: bogus <br> added under <ul> or <ol> would cause lists to be incorrectly rendered.
+					if ( FCKBrowserInfo.IsGecko &&
+							! eStartBlock.nodeName.IEquals( ['ul', 'ol'] ) )
 						FCKTools.AppendBogusBr( eStartBlock ) ;
 				}
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 834)
@@ -0,0 +1,164 @@
+﻿/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2007 Frederico Caldeira Knabben
+ *
+ * == BEGIN LICENSE ==
+ *
+ * Licensed under the terms of any of the following licenses at your
+ * choice:
+ *
+ *  - GNU General Public License Version 2 or later (the "GPL")
+ *    http://www.gnu.org/licenses/gpl.html
+ *
+ *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
+ *    http://www.gnu.org/licenses/lgpl.html
+ *
+ *  - Mozilla Public License Version 1.1 or later (the "MPL")
+ *    http://www.mozilla.org/MPL/MPL-1.1.html
+ *
+ * == END LICENSE ==
+ *
+ * FCKIndentCommand Class: controls block indentation.
+ */
+
+var FCKIndentCommand = function( name, offset )
+{
+	this.Name = name ;
+	this.Offset = offset ;
+	this.IndentCSSProperty = FCKConfig.ContentLangDirection.IEquals( 'ltr' ) ? 'marginLeft' : 'marginRight' ;
+}
+
+FCKIndentCommand.prototype =
+{
+	Execute : function()
+	{
+		// Save an undo snapshot before doing anything.
+		FCKUndo.SaveUndoStep() ;
+
+		var range = new FCKDomRange( FCK.EditorWindow ) ;
+		range.MoveToSelection() ;
+		var bookmark = range.CreateBookmark() ;
+
+		// Two cases to handle here: either we're in a list, or not.
+		// If we're in a list, then the indent/outdent operations would be done on the list nodes.
+		// Otherwise, apply the operation on the nearest block nodes.
+		var nearestListBlock = FCKDomTools.GetCommonParentNode( range.StartNode, range.EndNode, ['ul', 'ol'] ) ;
+		if ( nearestListBlock )
+			this._IndentList( range, nearestListBlock ) ;
+		else
+			this._IndentBlock( range ) ;
+
+		range.MoveToBookmark( bookmark ) ;
+		range.Select() ;
+		FCK.Events.FireEvent( 'OnSelectionChange' ) ;
+	},
+
+	GetState : function()
+	{
+		// TODO: 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;
+	},
+
+	_IndentBlock : function( range )
+	{
+		var iterator = new FCKDomRangeIterator( range ) ;
+		range.Expand( 'block_contents' ) ;
+		var commonParents = FCKDomTools.GetCommonParents( range.StartContainer, range.EndContainer ) ;
+		var nearestParent = commonParents[commonParents.length - 1] ;
+		var block ;
+
+		while ( ( block = iterator.GetNextParagraph() ) )
+		{
+			// We don't want to indent subtrees recursively, so only perform the indent operation
+			// if the block itself is the nearestParent, or the block's parent is the nearestParent.
+			if ( ! ( block == nearestParent || block.parentNode == nearestParent ) )
+				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' ;
+		}
+	},
+
+	_IndentList : function( range, listNode )
+	{
+		// 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 iterator = new FCKDomRangeIterator( range ) ;
+		var block ;
+		var itemsToMove = [] ;
+		while ( ( block = iterator.GetNextParagraph() ) )
+		{
+			if ( block.parentNode == listNode )
+				itemsToMove.push( block ) ;
+		}
+		if ( itemsToMove.length < 1 )
+			return ;
+		var lastItem = itemsToMove[ itemsToMove.length - 1 ] ;
+
+		if ( this.Name.IEquals( 'indent' ) )
+		{
+			// Indent is easy... just clone the list node, add under the original, and 
+			// move the contents inside the clone.
+			var indentList = listNode.cloneNode( false ) ;
+			FCKDomTools.InsertAfterNode( lastItem, indentList ) ;
+			while ( itemsToMove.length > 0 )
+				indentList.appendChild( itemsToMove.shift() ) ;
+		}
+		else if ( this.Name.IEquals( 'outdent' ) )
+		{
+			var startItem = itemsToMove[0] ;
+
+			// If we're in the middle of the list, we will have to split the list into two.
+			if ( startItem.previousSibling && lastItem.nextSibling )
+			{
+				range.SetStart( startItem, 3 ) ;
+				range.SetEnd( startItem, 3 ) ;
+				listNode = range.SplitBlock().NextBlock ;
+			}
+
+			// Remove the list items.
+			for ( var i = 0 ; i < itemsToMove.length ; i++ )
+				itemsToMove[i].parentNode.removeChild( itemsToMove[i] )  ;
+
+			// If the parent of listNode is not another list, then we need to convert the 
+			// listItems into paragraphs, depending on EnterMode.
+			if ( ! listNode.parentNode.nodeName.IEquals( ['ul', 'ol'] ) )
+			{
+				for ( var i = 0 ; i < itemsToMove.length ; i++ )
+				{
+					var container ;
+					if ( FCKConfig.EnterMode.IEquals( ['p', 'div'] ) )
+						container = listNode.ownerDocument.createElement( FCKConfig.EnterMode ) ;
+					else
+					{
+						container = listNode.ownerDocument.createDocumentFragment() ;
+						container.appendChild( listNode.ownerDocument.createElement( 'br' ) ) ;
+					}
+
+					var listItem = itemsToMove[i] ;
+					while ( listItem.lastChild )
+					{
+						var node = listItem.removeChild( listItem.lastChild ) ;
+						container.insertBefore( node, container.firstChild ) ;
+					}
+					itemsToMove[i] = container ;
+				}
+			}
+
+			// Insert the content nodes to listNode's parent.
+			while ( itemsToMove.length > 0 )
+				listNode.parentNode.insertBefore( itemsToMove.shift(), listNode ) ;
+
+			// Cleanup: if the listNode becomes empty, remove it.
+			if ( ! listNode.lastChild )
+				listNode.parentNode.removeChild( listNode ) ;
+		}
+	}
+} ;
Index: /FCKeditor/trunk/editor/_source/commandclasses/fckjustifycommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/commandclasses/fckjustifycommands.js	(revision 833)
+++ /FCKeditor/trunk/editor/_source/commandclasses/fckjustifycommands.js	(revision 834)
@@ -83,4 +83,7 @@
 	Execute : function()
 	{
+		// Save an undo snapshot before doing anything.
+		FCKUndo.SaveUndoStep() ;
+		
 		var range = new FCKDomRange( FCK.EditorWindow ) ;
 		range.MoveToSelection() ;
Index: /FCKeditor/trunk/editor/_source/internals/fck.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fck.js	(revision 833)
+++ /FCKeditor/trunk/editor/_source/internals/fck.js	(revision 834)
@@ -854,4 +854,7 @@
 		return ;
 
+	if ( FCKConfig.Debug )
+		FCKDebug._GetWindow() ;
+
 	FCK.SetStatus( FCK_STATUS_ACTIVE ) ;
 }
Index: /FCKeditor/trunk/editor/_source/internals/fckcommands.js
===================================================================
--- /FCKeditor/trunk/editor/_source/internals/fckcommands.js	(revision 833)
+++ /FCKeditor/trunk/editor/_source/internals/fckcommands.js	(revision 834)
@@ -93,4 +93,6 @@
 		case 'JustifyRight'	: oCommand = new FCKJustifyCommand( 'right' ) ; break ;
 		case 'JustifyFull'	: oCommand = new FCKJustifyCommand( 'justify' ) ; break ;
+		case 'Indent'	: oCommand = new FCKIndentCommand( 'indent', FCKConfig.IndentLength ) ; break ;
+		case 'Outdent'	: oCommand = new FCKIndentCommand( 'outdent', FCKConfig.IndentLength * -1 ) ; break ;
 
 		case 'TableInsertRowAfter'		: oCommand = new FCKTableCommand('TableInsertRowAfter') ; break ;
Index: /FCKeditor/trunk/editor/fckeditor.html
===================================================================
--- /FCKeditor/trunk/editor/fckeditor.html	(revision 833)
+++ /FCKeditor/trunk/editor/fckeditor.html	(revision 834)
@@ -119,4 +119,5 @@
 LoadScript( '_source/commandclasses/fcklistcommands.js' ) ;
 LoadScript( '_source/commandclasses/fckjustifycommands.js' ) ;
+LoadScript( '_source/commandclasses/fckindentcommands.js' ) ;
 LoadScript( '_source/commandclasses/fckcorestylecommand.js' ) ;
 LoadScript( '_source/commandclasses/fckremoveformatcommand.js' ) ;
Index: /FCKeditor/trunk/fckconfig.js
===================================================================
--- /FCKeditor/trunk/fckconfig.js	(revision 833)
+++ /FCKeditor/trunk/fckconfig.js	(revision 834)
@@ -61,5 +61,5 @@
 
 // The distance of an indentation step, in pixels.
-FCKConfig.IndentLength = 25 ;
+FCKConfig.IndentLength = 40 ;
 
 FCKConfig.ProcessHTMLEntities	= true ;
Index: /FCKeditor/trunk/fckpackager.xml
===================================================================
--- /FCKeditor/trunk/fckpackager.xml	(revision 833)
+++ /FCKeditor/trunk/fckpackager.xml	(revision 834)
@@ -129,4 +129,5 @@
 		<File path="editor/_source/commandclasses/fcklistcommands.js" />
 		<File path="editor/_source/commandclasses/fckjustifycommands.js" />
+		<File path="editor/_source/commandclasses/fckindentcommands.js" />
 		<File path="editor/_source/commandclasses/fckcorestylecommand.js" />
 		<File path="editor/_source/commandclasses/fckremoveformatcommand.js" />
@@ -222,4 +223,5 @@
 		<File path="editor/_source/commandclasses/fcklistcommands.js" />
 		<File path="editor/_source/commandclasses/fckjustifycommands.js" />
+		<File path="editor/_source/commandclasses/fckindentcommands.js" />
 		<File path="editor/_source/commandclasses/fckcorestylecommand.js" />
 		<File path="editor/_source/commandclasses/fckremoveformatcommand.js" />
