////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package flashx.textLayout.edit
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.InteractiveObject;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.IMEEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.Capabilities;
	import flash.text.engine.TextLine;
	import flash.ui.Keyboard;
	import flash.utils.getQualifiedClassName;
	
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.Configuration;
	import flashx.textLayout.elements.DivElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowGroupElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.ListElement;
	import flashx.textLayout.elements.ListItemElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SubParagraphGroupElement;
	import flashx.textLayout.elements.TCYElement;
	import flashx.textLayout.elements.TableCellElement;
	import flashx.textLayout.elements.TableElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.elements.TextRange;
	import flashx.textLayout.events.FlowOperationEvent;
	import flashx.textLayout.events.ModelChange;
	import flashx.textLayout.formats.IListMarkerFormat;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.operations.ApplyElementIDOperation;
	import flashx.textLayout.operations.ApplyElementTypeNameOperation;
	import flashx.textLayout.operations.ApplyFormatOperation;
	import flashx.textLayout.operations.ApplyFormatToElementOperation;
	import flashx.textLayout.operations.ApplyLinkOperation;
	import flashx.textLayout.operations.ApplyTCYOperation;
	import flashx.textLayout.operations.ClearFormatOnElementOperation;
	import flashx.textLayout.operations.ClearFormatOperation;
	import flashx.textLayout.operations.CompositeOperation;
	import flashx.textLayout.operations.CreateDivOperation;
	import flashx.textLayout.operations.CreateListOperation;
	import flashx.textLayout.operations.CreateSubParagraphGroupOperation;
	import flashx.textLayout.operations.CutOperation;
	import flashx.textLayout.operations.DeleteTextOperation;
	import flashx.textLayout.operations.FlowOperation;
	import flashx.textLayout.operations.InsertInlineGraphicOperation;
	import flashx.textLayout.operations.InsertTableElementOperation;
	import flashx.textLayout.operations.InsertTextOperation;
	import flashx.textLayout.operations.ModifyInlineGraphicOperation;
	import flashx.textLayout.operations.MoveChildrenOperation;
	import flashx.textLayout.operations.PasteOperation;
	import flashx.textLayout.operations.RedoOperation;
	import flashx.textLayout.operations.SplitElementOperation;
	import flashx.textLayout.operations.SplitParagraphOperation;
	import flashx.textLayout.operations.UndoOperation;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.CharacterUtil;
	import flashx.textLayout.utils.GeometryUtil;
	import flashx.textLayout.utils.NavigationUtil;
	import flashx.undo.IOperation;
	import flashx.undo.IUndoManager;
		
	use namespace tlf_internal;
	
	/** 
	 * The EditManager class manages editing changes to a TextFlow. 
	 * 
	 * <p>To enable text flow editing, assign an EditManager object to the <code>interactionManager</code> 
	 * property of the TextFlow object. The edit manager handles changes to the text (such as insertions, 
	 * deletions, and format changes). Changes are reversible if the edit manager has an undo manager. The edit
	 * manager triggers the recomposition and display of the text flow, as necessary.</p>
	 *
	 * <p>The EditManager class supports the following keyboard shortcuts:</p>
	 * 
	 * <table class="innertable" width="100%">
	 *  <tr><th>Keys</th><th>Result</th></tr>
	 *  <tr><td>ctrl-z</td><td>undo</td></tr>					
	 * 	<tr><td>ctrl-y</td><td>redo</td></tr>					
	 * 	<tr><td>ctrl-backspace</td><td>deletePreviousWord</td></tr>					
	 * 	<tr><td>ctrl-delete</td><td>deleteNextWord</td></tr>					
	 * 	<tr><td>alt+delete</td><td>deleteNextWord</td></tr>					
	 * 	<tr><td>ctrl+alt-delete</td><td>deleteNextWord</td></tr>					
	 * 	<tr><td>ctrl-shift-hyphen</td><td>insert discretionary hyphen</td></tr>					
	 * 	<tr><td>ctrl+backspace</td><td>deletePreviousWord</td></tr>					
	 * 	<tr><td>alt+backspace</td><td>deletePreviousWord</td></tr>					
	 * 	<tr><td>ctrl+alt-backspace</td><td>deletePreviousWord</td></tr>					
	 * 	<tr><td>INSERT</td><td>toggles overWriteMode</td></tr>					
	 * 	<tr><td>backspace</td><td>deletePreviousCharacter</td></tr>					
	 * 	<tr><td>ENTER</td><td>if textFlow.configuration.manageEnterKey in a list it creates a new list item, otherwise creates a new paragraph</td></tr>					
	 * 	<tr><td>shift-ENTER</td><td>if textFlow.configuration.manageEnterKey creates a new paragraph</td></tr>					
	 * 	<tr><td>TAB</td><td>if textFlow.configuration.manageTabKey in a list it creates nested list, otherwise inserts a TAB or overwrites next character with a TAB</td></tr>    
	 * 	<tr><td>shift-TAB</td><td>if textFlow.configuration.manageTabKey in the first item of a list it moves the item out of the list (promotes it)</td></tr>    
	 * </table>
	 *
	 * <p><strong>Note:</strong> The following keys do not work on Windows: alt-backspace, alt-delete, ctrl+alt-backspace,
	 * and ctrl+alt-delete. These keys do not generate an event for the runtime.</p>						
 	 * 
 	 * @see flashx.textLayout.elements.TextFlow
 	 * @see flashx.undo.UndoManager
	 *
	 * @includeExample examples\EditManager_example.as -noswf
	 * 
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
 	 * @langversion 3.0
	 */			
	public class EditManager extends SelectionManager implements IEditManager
	{
		static tlf_internal var handleShiftAsSoftReturn:Boolean = true;
		 /**
		 *  To minimize expensive recompositions during fast typing, inserts
		 *  don't necessarily take place immediately. An insert operation that
		 *  hasn't yet executed is held here.
		 */
		private var pendingInsert:InsertTextOperation;
		
		/* 
		 * The object that has the ENTER_FRAME event listener attached to perform pending inserts.
		 */
		private var enterFrameListener:DisplayObjectContainer;

		/* True if updates get handled on enter_frame, and not immediately. */
		private var _delayUpdates:Boolean = false;
		
		/* True if some operations (e.g., handling of text events) can be delayed to next enterFrame by default. False for immediate handling */
		private var _allowDelayedOperations:Boolean = true;
		
		/*
		 * The object that has the ENTER_FRAME event listener attached to perform pending updates.
		 */
		private var redrawListener:DisplayObjectContainer;

		/*
		 *  Some operations can be undone & redone. The undoManager keeps track
		 *  of the operations that have been done or undone so that they can be undone or
		 *  redone.  I'm not sure if only text operations can be undone. If so, the undoManager
		 *  should probably be moved to EditManager.
		 */
		private var _undoManager:flashx.undo.IUndoManager;
		
		private var _imeSession:IMEClient;
		private var _imeOperationInProgress:Boolean;
		
		/** 
		 * Indicates whether overwrite mode is on or off.
		 * 
		 * <p>If <code>true</code>, then a keystroke overwrites the character following the cursor.
		 * If <code>false</code>, then a keystroke is inserted at the cursor location.</p> 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/		
		public static var overwriteMode:Boolean = false;
		
		/** 
		 * Creates an EditManager object.
		 * 
		 * <p>Assign an EditManager object to the <code>interactionManager</code> property
		 * of a text flow to enable editing of that text flow. </p>
		 *
		 * <p>To enable support for undoing and redoing changes, pass an 
		 * IUndoManager instance to the EditManager constructor. You can use
		 * the <code>flashx.undo.UndoManager</code> class
		 * or create a custom IUndoManager instance. Use a custom IUndoManager instance
		 * to integrate Text Layout Framework changes with an existing
		 * undo manager that is not an instance of the UndoManager class.
		 * To create a custom IUndoManager instance, ensure that the class
		 * you use to define the undo manager 
		 * implements the IUndoManager interface.</p>
		 * 
		 * 
		 * @param undo	The UndoManager for the application
		 * 
		 * @see flashx.textLayout.elements.TextFlow#interactionManager
		 * @see flashx.undo.IUndoManager
		 * 
		 * @includeExample examples\EditManager_constructor.as -noswf
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function EditManager(undoManager:flashx.undo.IUndoManager = null)
		{
			super();
			_undoManager = undoManager;
		}

		/**  
		 * The IUndoManager assigned to this edit manager.
		 * 
		 * <p>To allow edits to be undone (and redone), pass an IUndoManager instance to the EditManager
		 * constructor. The undo manager maintains a stack of operations that have been executed, and it can 
		 * undo or redo individual operations. </p>
		 * 
		 * <p><b>Note:</b> If the TextFlow is modified directly (not via
		 * calls to the EditManager, but directly via calls to the managed FlowElement objects), then the EditManager
		 * clears the undo stack to prevent the stack from getting out of sync with the current state.</p>
		 * 
	 	 * @playerversion Flash 10
	 	 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */	
		public function get undoManager():flashx.undo.IUndoManager
		{
			return _undoManager;
		}
		
		// Backdoor provided so that IMEClient can temporarily use an undo manager to maintain the IME session state.
		/** @private */
		tlf_internal function setUndoManager(undoManager:flashx.undo.IUndoManager):void
		{
			_undoManager = undoManager;
		}
		
		/** @private */
		override public function editHandler(event:Event):void
		{
			if (event.isDefaultPrevented())
				return;

			super.editHandler(event);
			switch (event.type)
			{
				case Event.CUT: 
				case Event.CLEAR:
					if (activePosition != anchorPosition)
					{
						if (event.type == Event.CUT)
							TextClipboard.setContents(cutTextScrap());
						else
							deleteText(null);
						event.preventDefault();
					}
					break;
				case Event.PASTE:
					pasteTextScrap(TextClipboard.getContents());
					event.preventDefault();
					break;
			}
		}

		// ///////////////////////////////////
		// keyboard methods 
		// ///////////////////////////////////
		
		/** @private */
		public override function keyDownHandler(event:KeyboardEvent):void
		{
			var listItem:ListItemElement;
			var operationState:SelectionState;
			
			if (!hasSelection() || event.isDefaultPrevented())
				return;
			
			if (redrawListener)		// pending redraw; handle this before anything else so TextLines on screen will be up to date
				updateAllControllers();
			
			super.keyDownHandler(event);
			
			if (event.ctrlKey)
			{
				// The player subsequently sends a text input event (which should be ignored) as listed below:
				// CTRL/CMD+z: Only on Mac when using a pre-Argo player version
				// CTRL/CMD+y: On all platforms (the exact char code for the text input event is platform dependent) 
				if (!event.altKey)
				{
					if (_imeSession != null && ((event.charCode == 122) || (event.charCode == 121)))
						_imeSession.compositionAbandoned();		// must be done before undo or redo start b/c IME session uses undo also for its own rollback
					// do Operation will also cancel the session.
					
					switch(event.charCode)
					{
						case 122:	// small z
							/* pre-Argo and on the mac then ignoreNextTextEvent */ 
							if (!Configuration.versionIsAtLeast(10,1) && (Capabilities.os.search("Mac OS") > -1)) 
								ignoreNextTextEvent = true;
							if(event.shiftKey){
								redo();
								event.preventDefault();

							} else {
								undo();
								event.preventDefault();
							}
							break;
						case 121:	// small y
							ignoreNextTextEvent = true;
							redo();
							event.preventDefault();
							break;
						case Keyboard.BACKSPACE:
							if (_imeSession)
								_imeSession.compositionAbandoned();
							deletePreviousWord();
							event.preventDefault();
							break;
					}
					if (event.keyCode == Keyboard.DELETE)
					{
						if (_imeSession)
							_imeSession.compositionAbandoned();
						deleteNextWord();
						event.preventDefault();
					}
					
					if (event.shiftKey)
					{
						// detect ctrl-shift-"-" (cnd-shift-"-" on mac) and insert a DH
						if (event.charCode == 95)
						{
							if (_imeSession)
								_imeSession.compositionAbandoned();
							
							//a discretionary hyphen is being inserted. 
							var discretionaryHyphenString:String = String.fromCharCode(0x000000AD);
							overwriteMode ? overwriteText(discretionaryHyphenString) : insertText(discretionaryHyphenString);
							event.preventDefault();
						}
					}
				}
			} 
			else if (event.altKey)
			{
				if (event.charCode == Keyboard.BACKSPACE)
				{
					deletePreviousWord();
					event.preventDefault();
				}
				else if (event.keyCode == Keyboard.DELETE)
				{
					deleteNextWord();
					event.preventDefault();
				}
			}
			// not ctrl key or alt key
			else if (event.keyCode == Keyboard.DELETE) //del
			{
				deleteNextCharacter();
				event.preventDefault();
			}
			else if (event.keyCode == Keyboard.INSERT) //insert
			{
				overwriteMode = !overwriteMode;				
				event.preventDefault();
			}
			else switch(event.charCode) {
				case Keyboard.BACKSPACE:
					deletePreviousCharacter();
					event.preventDefault();
					break;
				case Keyboard.ENTER:
					if (textFlow.configuration.manageEnterKey) 
					{
						var firstLeaf:FlowLeafElement = textFlow.findLeaf(absoluteStart);
						listItem = firstLeaf.getParentByType(ListItemElement) as ListItemElement;
						// if the listitem has a ListElement child then treat this as a regular Paragraph
						if (listItem && firstLeaf.getParentByType(ListElement) != listItem.getParentByType(ListElement))
							listItem = null;
						
						// inside a list shift-enter splits a paragraph and enter splits the listitem
						if (listItem && !event.shiftKey)
						{
							// if on last item of list and it's empty, remove it and put cursor on a new para immediatly following the list (new para should be wrapped in a new list item if parent of list is another list).
							if(listItem.textLength == 1 && listItem.parent.getChildIndex(listItem) == listItem.parent.numChildren - 1)
							{
								operationState = defaultOperationState();
								if (!operationState)
									return;
								
								doOperation(new MoveChildrenOperation(operationState, listItem.parent, listItem.parent.getChildIndex(listItem), 1, listItem.parent.parent, listItem.parent.parent.getChildIndex(listItem.parent) + 1));
							}
							else
							{
								splitElement(listItem);
								// push cursor past the marker
								selectRange(absoluteStart+1,absoluteStart+1);
								refreshSelection();
							}
						}
						else if(event.shiftKey &&
							((!listItem && textFlow.configuration.shiftEnterLevel > 0) ||
							textFlow.configuration.shiftEnterLevel > 1)
						)
						{
							overwriteMode ? overwriteText("\u2028") : insertText("\u2028");
						}
						else
							splitParagraph();
						event.preventDefault();
						event.stopImmediatePropagation();
					}
					break;
				case Keyboard.TAB:
					if (textFlow.configuration.manageTabKey) 
					{
						listItem  = textFlow.findLeaf(absoluteStart).getParentByType(ListItemElement) as ListItemElement;
						if (listItem && listItem.getAbsoluteStart() == absoluteStart)
						{
							operationState = defaultOperationState();
							if (!operationState)
								return;
							
							if(event.shiftKey)
							{
								// unindent by moving list element(s) out of parent into grandparent
								
								// first make sure there is a grandparent
								if(listItem.parent.parent is ListElement && listItem.parent.getChildIndex(listItem) == 0)
								{
									var source:FlowGroupElement;
									var target:FlowGroupElement;
									var numElements:int;
									var sourceIndex:int;
									var targetIndex:int;
									
									{
										source = listItem.parent;
										target = listItem.parent.parent;
										numElements = listItem.parent.numChildren;
										sourceIndex = 0;
										targetIndex = listItem.parent.parent.getChildIndex(listItem.parent);
									}
									doOperation(new MoveChildrenOperation(operationState, source, sourceIndex, numElements, target, targetIndex));
								}
							}
							else
							{
								// create new list from list element(s)
								var element:FlowGroupElement = listItem;
								if(listItem.parent.getChildIndex(listItem) == 0) 
									element = listItem.parent;
								
								doOperation(new CreateListOperation(new SelectionState(textFlow, element.getAbsoluteStart(), element.getAbsoluteStart() + element.textLength), listItem.parent));
							}
						}
						else if (textFlow.nestedInTable()) {
							var cell:TableCellElement;
							
							if (event.shiftKey) {
								cell = (textFlow.parentElement as TableCellElement).getPreviousCell();
							}
							else {
								cell = (textFlow.parentElement as TableCellElement).getNextCell();
							}
							
							// select next cell in table
							if (cell && cell.textFlow && cell.textFlow.interactionManager is EditManager) {
								//cell.textFlow.interactionManager.selectLastPosition();
								deselect();
								cell.textFlow.interactionManager.selectAll();
								cell.textFlow.interactionManager.setFocus();
							}
						}
						else
						{
							overwriteMode ? overwriteText(String.fromCharCode(event.charCode)) : insertText(String.fromCharCode(event.charCode));
						}
						event.preventDefault();
					}
					break;
			}
		}
		
		/** @private */
		public override function keyUpHandler(event:KeyboardEvent):void
		{
			if (!hasSelection() || event.isDefaultPrevented())
				return;
				
			super.keyUpHandler(event);
			
			if ((textFlow.configuration.manageEnterKey && event.charCode == Keyboard.ENTER) || (textFlow.configuration.manageTabKey && event.charCode == Keyboard.TAB)) {
				event.stopImmediatePropagation();
			}
		}
		
		/** @private */	
		public override function keyFocusChangeHandler(event:FocusEvent):void
		{
			if (textFlow.configuration.manageTabKey) 
				event.preventDefault();
		}
	
		/** @private */
		public override function mouseDownHandler(event:MouseEvent):void
		{
			if (redrawListener)
				updateAllControllers();
			super.mouseDownHandler(event);
		}
		
		/** @private */
		public override function textInputHandler(event:TextEvent):void
		{
			if (!ignoreNextTextEvent)
			{
				var charCode:int = event.text.charCodeAt(0);
				// only if its a space or larger - ignore control characters here
				if (charCode >=  32)
					overwriteMode ? overwriteText(event.text) : insertText(event.text);
			}
			ignoreNextTextEvent = false;
			// if the manager is nested inside another one, do not handle it again in the outer one
			if(superManager)
				event.preventDefault();
				
		}
		
		/** @private */
		override public function focusOutHandler(event:FocusEvent):void
		{
			super.focusOutHandler(event);
			if (_imeSession && selectionFormatState != SelectionFormatState.FOCUSED)
				_imeSession.compositionAbandoned();
		}
		
		/** @private */
		override public function deactivateHandler(event:Event):void
		{
			super.deactivateHandler(event);
			if (_imeSession)
				_imeSession.compositionAbandoned();
		}
		
		/** @private */
		override public function imeStartCompositionHandler(event:IMEEvent):void
		{
			CONFIG::debug{ assert(!_imeSession, "IME session already in progress: IME not reentrant!"); }
		//	CONFIG::debug { Debugging.traceOut("imeStartComposition event"); }

			// any pending operations must be executed first, to
			// preserve operation order.
			flushPendingOperations();
			
			// Coded to avoid dependency on Argo (10.1). 
			if (!(event["imeClient"]))
			{
				_imeSession = new IMEClient(this);
				_imeOperationInProgress = false;
				event["imeClient"] = _imeSession;
			}
		}
		
		/** @private */
		override public function setFocus():void
		{
			var flowComposer:IFlowComposer = textFlow ? textFlow.flowComposer : null;
			if (_imeSession && flowComposer && flowComposer.numControllers > 1)
			{
				// container with the ime start position gets the key focus
				_imeSession.setFocus();

				setSelectionFormatState(SelectionFormatState.FOCUSED);
			}
			else
				super.setFocus();
			
			/* CONFIG::debug
			{
				if (textFlow.flowComposer.getControllerAt(0).container.stage)
				{
					var focusDI:DisplayObject = textFlow.flowComposer.getControllerAt(0).container.stage.focus;
					trace("set focus to ", focusDI.hasOwnProperty("name") ? focusDI["name"] : focusDI.toString());
				}
			} */
		}
		/** @private */		
		tlf_internal function endIMESession():void
		{
			_imeSession = null;
			var flowComposer:IFlowComposer = textFlow ? textFlow.flowComposer : null;
			if (flowComposer && flowComposer.numControllers > 1)
				setFocus();
		}
		/** @private */
		tlf_internal function beginIMEOperation():void
		{
			_imeOperationInProgress = true;
			beginCompositeOperation();
		}
		/** @private */
		tlf_internal function endIMEOperation():void
		{
			endCompositeOperation();
			_imeOperationInProgress = false;
		}

		/** @private We track the nesting level of the doOperation, because in finalize we need to know if
		we are at the outermost level and need to push the operation on the undo stack and redraw
		the screen, or if we're in a nested level and need to append the operation to the next
		level up. */
		tlf_internal var captureLevel:int = 0;

		/** 
		  * @copy IEditManager#doOperation()
		  * 
		  * @includeExample examples\EditManager_doOperation.as -noswf
		  * 
		  * @playerversion Flash 10
		  * @playerversion AIR 1.5
 	 	  * @langversion 3.0
		  */
		public override function doOperation(operation:FlowOperation):void
		{
			CONFIG::debug { assert(operation.textFlow == this.textFlow,"Operation from a different TextFlow"); }
			
			// If we get any operation during an IME session that is not owned by the session, we cancel the IME
			if (_imeSession && !_imeOperationInProgress)
				_imeSession.compositionAbandoned();
			
			// any pending operations must be executed first, to
			// preserve operation order.
			flushPendingOperations();
			
			try
			{
				captureLevel++;
				operation = doInternal(operation);
			}
			catch(e:Error)
			{
				captureLevel--;
				throw(e);
			}
			captureLevel--;
			
			if (operation)			// don't finalize if operation was cancelled
				finalizeDo(operation);
		}

		private function finalizeDo(op:FlowOperation):void
		{
			// Handle operation if we're in a beginCompositeOperation/endCompositeOperation context
			// In this case any nested commands we do will get added to the composite operation when 
			// they're done instead of added to the undo stack.
			var parentOperation:CompositeOperation;
			if (parentStack && parentStack.length > 0)
			{
				var parent:Object = parentStack[parentStack.length - 1];
				if (parent.captureLevel == captureLevel)
					parentOperation = parent.operation as CompositeOperation;
			}

	//		CONFIG::debug { assert(captureLevel == 0 || parentOperation != null, "missing parent for nested operation"); }
			
			if (parentOperation)
				parentOperation.addOperation(op);
			
			else if (captureLevel == 0)
			{
				captureOperations.length = 0; 
				if (_undoManager)
				{
					if (_undoManager.canUndo() && allowOperationMerge)
					{
						var lastOp:FlowOperation = _undoManager.peekUndo() as FlowOperation;
						if (lastOp)
						{
							// Try to merge the last operation on the stack with the current
							// operation. This may modify lastOp, or return a new operation
							var combinedOp:FlowOperation = lastOp.merge(op);
							if (combinedOp)
							{
								CONFIG::debug { assert(combinedOp.endGeneration == textFlow.generation,"Who did what?"); }
								CONFIG::debug { assert(combinedOp.canUndo() && combinedOp.endGeneration == op.endGeneration,"Bad operation merge in EditManager") };
								_undoManager.popUndo();
								op = combinedOp;
							}
						}
					}
					if (op.canUndo())
						_undoManager.pushUndo(op);
					allowOperationMerge = true;

					// following operations are no longer redoable
					_undoManager.clearRedo();
				}

				handleUpdate();			

				if (!_imeSession)
				{	
					var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,op,0,null);
					textFlow.dispatchEvent(opEvent);
				}
			}	
		}
		
		private var captureOperations:Array = [];

		/** Internal guts of a dooperation - Execute a FlowOperation.  This function proceeds in steps.
		  * <p>Step 2. Send a canceallable OperationEvent.  If cancelled this method returns immediately.</p>
		  * If it is not cancelled, the listener may "do" other operations by calling back into the EditManager. This will result
		  * in a nested call to do which will post additional commands to the captureOperations array.
		  * <p>Step 3. Execute the operation.  The operation returns true or false.  false indicates no changes were made.</p>
		  * <p>Step 7. Send a OperationEvent. </p>
		  * The listener may "do" other operations by calling back into the EditManager. This will result
		  * in a nested call to do which will post additional commands to the captureOperations array.
		  * <p>Exception handling.  If the operation throws the exception is caught and the error is attached to the event dispatched
		  * at step 7.  If the event is not cancelled the error is rethrown.</p>
		  */
		private function doInternal(op:FlowOperation):FlowOperation
		{
			CONFIG::debug { assert(op.textFlow == this.textFlow,"Operation from a different TextFlow"); }
			
			var captureStart:int = captureOperations.length;
			var success:Boolean = false;
			var opEvent:FlowOperationEvent;
			
			// tell any listeners about the operation
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,op,captureLevel-1,null);
				textFlow.dispatchEvent(opEvent);
				if (opEvent.isDefaultPrevented())
					return null;
				// user may replace the operation - TODO: WHAT IF SWITCH TO UNDO/REDO????
				op = opEvent.operation;
				if ((op is UndoOperation) || (op is RedoOperation))
					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(op) ]));
			}
				
			var opError:Error = null;
			try
			{
				// begin this op after pending ops are flushed
				CONFIG::debug 
				{ 
					if (captureLevel <= 1)
						debugCheckTextFlow(); 
				}
				
				// null return implies no operation was done - just discard it
				var beforeGeneration:uint = textFlow.generation;
				op.setGenerations(beforeGeneration,0);
	
				captureOperations.push(op);
				success = op.doOperation();
				if (success)		// operation succeeded
				{
					textFlow.normalize();   //force normalization at this point. Don't compose unless the captureLevel is 0
					
					// This has to be done after the normalize, because normalize increments the generation number
					op.setGenerations(beforeGeneration,textFlow.generation);					
				} 
				else 
				{
					var index:int = captureOperations.indexOf(op);
					if (index >= 0) 
						captureOperations.splice(index, 1);
				}
			}
			catch(e:Error)
			{
				opError = e;
			}
			
			// operation completed - send event whether it succeeded or not.
			// client can check generation number for changes
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,op,captureLevel-1,opError);
				textFlow.dispatchEvent(opEvent);
				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
			}

			if (opError)
				throw (opError);
				
			// If we fired off any subsidiary operations, create a composite operation to hold them all
		 	if (captureOperations.length - captureStart > 1)
		 	{
				op = new CompositeOperation(captureOperations.slice(captureStart));
				op.setGenerations(FlowOperation(CompositeOperation(op).operations[0]).beginGeneration,textFlow.generation);
				allowOperationMerge = false;
				captureOperations.length = captureStart;		
		 	}
			 	
			return success ? op : null;
		}

		/** @private **/
		override public function set textFlow(value:TextFlow):void
		{
			flushPendingOperations();
			if (redrawListener)	// detach handler if there is one
				updateAllControllers();
			super.textFlow = value;
		}  
		
		/**
		 * @copy IEditManager.delayUpdates
		 */
		public function get delayUpdates():Boolean
		{
			return _delayUpdates;
		}
		public function set delayUpdates(value:Boolean):void
		{
			_delayUpdates = value;
		}
		
		private function redrawHandler(e:Event):void
		{
			// This is here because it has to take an argument
			updateAllControllers();
		}

		/** @copy IEditManager.updateAllControllers
		 */
		public function updateAllControllers():void
		{
			flushPendingOperations();

			if (redrawListener)	// detach handler if there is one
			{
				redrawListener.removeEventListener(Event.ENTER_FRAME, redrawHandler);
				redrawListener = null;
			}

			var cellHeight:Number = 0;
			if (textFlow.flowComposer)
			{
				if(superManager && superManager is IEditManager)
				{
					var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
					if (controller)
					{
						cellHeight = controller.container.height;
					}
				}


				 textFlow.flowComposer.updateAllControllers(); 

				// Scroll to selection
				if (hasSelection())
				{
					var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(activePosition);
					if (controllerIndex >= 0)
						textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);	
				}
				if(superManager && superManager is IEditManager)
				{
					if(controller.container.height != cellHeight)
					{
						var setFormat:String = selectionFormatState;
						var table:TableElement = (textFlow.parentElement as TableCellElement).getTable();
						table.modelChanged(ModelChange.ELEMENT_MODIFIED, table, 0, table.textLength);
						(superManager as IEditManager).updateAllControllers();
						if(setFormat == SelectionFormatState.FOCUSED)
							setFocus();
					}
				}
			}

			selectionChanged(true, false);
				
			CONFIG::debug { debugCheckTextFlow(); }
		}

		// By default, the EditManager will update in response to a model change immediately.
		// Client may also request a delayed update; in this case, we schedule an update on the
		// next enter frame event.
		private function handleUpdate():void
		{
			if (_delayUpdates)
			{
				if (!redrawListener)	// only need to attach if we're not already
				{
					var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
					if (controller)
					{
						redrawListener = controller.container;
						if (redrawListener)
							redrawListener.addEventListener(Event.ENTER_FRAME, redrawHandler, false, 1.0, true);			
					}
				}
			}
			else		// redraw now
			{
				updateAllControllers();
			}
		}
			
		/** @copy IEditManager#allowDelayedOperations() */
		public function get allowDelayedOperations():Boolean
		{
			return _allowDelayedOperations;
		}
		public function set allowDelayedOperations(value:Boolean):void
		{
			if (!value)
				flushPendingOperations();
			_allowDelayedOperations = value;
		}
		
		/** @private */
		public override function flushPendingOperations():void
		{
			super.flushPendingOperations();
			if (pendingInsert)
			{
				var pi0:InsertTextOperation = pendingInsert;
				pendingInsert = null;
				if (enterFrameListener)
				{
					enterFrameListener.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
					enterFrameListener = null;
				}
				doOperation(pi0);
			}
		}

		/** 
		 * @copy IEditManager#undo()
		 * @includeExample examples\EditManager_undo.as -noswf
		 * 
		 * @see flashx.undo.IUndoManager#undo()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function undo():void
		{
			// Cancel out of an IME session if there is one. 
			// Some IMEs are on all the time, and so the undo has to win over the IME, 
			// otherwise you would never be able to undo in Korean.
			if (_imeSession)
				_imeSession.compositionAbandoned();
			
			if (undoManager)
				undoManager.undo();
		}
		 			
		/** @private */
		public function performUndo(theop:IOperation):void
		{
			var operation:FlowOperation = theop as FlowOperation;
			if ((!operation) || (operation.textFlow != textFlow)) 
				return;			
			// tell any listeners about the operation
			if (!_imeSession)
			{
				var undoPsuedoOp:UndoOperation = new UndoOperation(operation);
				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,undoPsuedoOp,0,null);
				textFlow.dispatchEvent(opEvent);
				if (opEvent.isDefaultPrevented())
				{
					//operation cancelled by user. Push the operation back onto the undo stack
					undoManager.pushUndo(operation);
					return;
				}
				undoPsuedoOp = opEvent.operation as UndoOperation;
				if (!undoPsuedoOp)
					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(opEvent.operation) ]));
				operation = undoPsuedoOp.operation;
			}
					
			if (operation.endGeneration != textFlow.generation)
			{
				//CONFIG::debug { trace("EditManager.undo: skipping undo due to mismatched generation numbers. textFlow",textFlow.generation,flash.utils.getQualifiedClassName(operation),operation.endGeneration); }
				return;
			}
				
			var opError:Error = null;
			try
			{
				CONFIG::debug { debugCheckTextFlow(); }
	
				var rslt:SelectionState;
				rslt = operation.undo();
	
				CONFIG::debug { assert(rslt != null,"undoable operations must return a SelectionState"); }
				setSelectionState(rslt);
				if (_undoManager)
					_undoManager.pushRedo(operation);

			}
			catch(e:Error)
			{
				opError = e;
			}
				
			// tell user its complete and give them a chance to cancel the rethrow
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,undoPsuedoOp,0,opError);
				textFlow.dispatchEvent(opEvent);
				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
			}

			if (opError)
				throw (opError);
			
			handleUpdate();
			
			// push the generation of the textFlow backwards - must be done after update which does a normalize
			textFlow.setGeneration(operation.beginGeneration);
			
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,undoPsuedoOp,0,null);
				textFlow.dispatchEvent(opEvent);
			}
		}
		
		/** 
		 * @copy IEditManager#redo()
		 * @includeExample examples\EditManager_redo.as -noswf
		 * 
		 * @see flashx.undo.IUndoManager#redo()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function redo():void
		{
			// Cancel out of an IME session if there is one. 
			// Some IMEs are on all the time, and so the undo has to win over the IME, 
			// otherwise you would never be able to undo in Korean.
			if (_imeSession)
				_imeSession.compositionAbandoned();
			
			if (undoManager)
				undoManager.redo();
		}
		
		/** @private */
		public function performRedo(theop:IOperation):void
		{
			var opEvent:FlowOperationEvent;
			var op:FlowOperation = theop as FlowOperation;
			if ((!op) || (op.textFlow != textFlow)) 
				return;
			// tell any listeners about the operation
			if (!_imeSession)
			{
				var redoPsuedoOp:RedoOperation = new RedoOperation(op);
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,redoPsuedoOp,0,null);
				textFlow.dispatchEvent(opEvent);
				if (opEvent.isDefaultPrevented() && _undoManager)
				{
					//user cancelled the event. Push the operation back onto the redo stack
					_undoManager.pushRedo(op);
					return;
				}
				redoPsuedoOp = opEvent.operation as RedoOperation;
				if (!redoPsuedoOp)
					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(opEvent.operation) ]));
				op = redoPsuedoOp.operation;
			}
					
			if (op.beginGeneration != textFlow.generation)
			{
				//CONFIG::debug { trace("EditManager.redo: skipping redo due to mismatched generation numbers."); }
				return;
			}
				
			var opError:Error = null;
			try
			{
				CONFIG::debug { debugCheckTextFlow(); }					
				var rslt:SelectionState;
				rslt = op.redo();
					
				CONFIG::debug { assert(rslt != null,"redoable operations must return a SelectionState"); }
				setSelectionState(rslt);
				if (_undoManager)
					_undoManager.pushUndo(op);

			
			}
			catch(e:Error)
			{
				opError = e;
			}
				
			// tell user its complete and give them a chance to cancel the rethrow
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,redoPsuedoOp,0,opError);
				textFlow.dispatchEvent(opEvent);
				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
			}
			if (opError)
				throw (opError);
			
			handleUpdate();
			
			// push the generation of the textFlow backwards - must be done after update which does a normalize
			// set the generation of the textFlow to end of redoOp.
			textFlow.setGeneration(op.endGeneration);
			
			if (hasSelection())
			{
				var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(activePosition);
				if (controllerIndex >= 0)
					textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);						
			}	
			if (!_imeSession)
			{
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,redoPsuedoOp,0,null);
				textFlow.dispatchEvent(opEvent);			
			}
		}
		
		/**
		 * @private
		 * Returns the editing mode (READ_ONLY, READ_SELECT, or READ_WRITE) of the EditManager.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * @see flashx.textLayout.edit.EditingMode.
		 */
		 public override function get editingMode():String
		 {
		 	return EditingMode.READ_WRITE;
		 }				 		
		
		// Resolve the operationState.
		//		If the operation state is null...
		//			Return the active selection
		//			If there's no active selection, return null. The caller will have to check
		//		Otherwise (operation not null)
		//			just return it
		/** @private */
		tlf_internal function defaultOperationState(operationState:SelectionState = null):SelectionState
		{
			if (operationState)
			{
				// flush any pending operations and use marks to preserve the operationState positions
				var markActive:Mark = createMark();
				var markAnchor:Mark = createMark();
				try
				{
					markActive.position = operationState.activePosition;
					markAnchor.position = operationState.anchorPosition;
					flushPendingOperations();
				}
				finally
				{
					removeMark(markActive);
					removeMark(markAnchor);
					operationState.activePosition = markActive.position;
					operationState.anchorPosition = markAnchor.position;
				}
			}
			else
			{
				flushPendingOperations();
				if (hasSelection())
				{
					// tell the operation that the state is from the SelectionManager so it will update pending point formats
					operationState = getSelectionState();
					operationState.selectionManagerOperationState = true;
				}
			}
			return operationState;
		}

		/** 
		 * @copy IEditManager#splitParagraph()
		 * @includeExample examples\EditManager_splitParagraph.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function splitParagraph(operationState:SelectionState = null):ParagraphElement
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;

			var op:SplitElementOperation = new SplitParagraphOperation(operationState);
			doOperation(op);
			return op.newElement as ParagraphElement;
		}
		
		
		/** @copy IEditManager#splitElement() */
		public function splitElement(target:FlowGroupElement, operationState:SelectionState = null):FlowGroupElement
		{ 
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
			var op:SplitElementOperation = new SplitElementOperation(operationState, target);
			doOperation(op);
			return op.newElement;
		}
		
		/** @copy IEditManager#createDiv() */
		public function createDiv(parent:FlowGroupElement = null, format:ITextLayoutFormat = null, operationState:SelectionState = null):DivElement
		{ 
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
			
			var operation:CreateDivOperation = new CreateDivOperation(operationState, parent, format);
			doOperation(operation);
			return operation.newDivElement;
		}		
		
		/** @copy IEditManager#createList() */
		public function createList(parent:FlowGroupElement = null, format:ITextLayoutFormat = null, operationState:SelectionState = null):ListElement
		{ 
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
			
			var operation:CreateListOperation = new CreateListOperation(operationState, parent, format);
			doOperation(operation);
			return operation.newListElement;
		}
		
		/** @copy IEditManager#moveChildren() */
		public function moveChildren(source:FlowGroupElement, sourceIndex:int, numChildren:int, destination:FlowGroupElement, destinationIndex:int, selectionState:SelectionState = null):void
		{ 
			selectionState = defaultOperationState(selectionState);
			if (!selectionState)
				return;

			var operation:MoveChildrenOperation = new MoveChildrenOperation(selectionState, source, sourceIndex, numChildren, destination, destinationIndex);
			doOperation(operation);
		}
		
		/** @copy IEditManager#createSubParagraphGroup() */
		public function createSubParagraphGroup(parent:FlowGroupElement = null, format:ITextLayoutFormat = null, operationState:SelectionState = null):SubParagraphGroupElement
		{ 
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
			
			var operation:CreateSubParagraphGroupOperation = new CreateSubParagraphGroupOperation(operationState, parent, format);
			doOperation(operation);
			return operation.newSubParagraphGroupElement;
		}

		/** 
		 * @copy IEditManager#deleteText()
		 * @includeExample examples\EditManager_deleteText.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function deleteText(operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).deleteText(operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			doOperation(new DeleteTextOperation(operationState, operationState, false /* don't allow merge when deleting by range */));				
		}		
		
		/**
		 * @copy IEditManager#deleteNextCharacter()
		 * @includeExample examples\EditManager_deleteNextCharacter.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function deleteNextCharacter(operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).deleteNextCharacter(operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			/*
			This should not be necessary...
			// mjzhang : fix for table
			var leaf:FlowLeafElement = textFlow.findLeaf(operationState.absoluteStart);
			var para:ParagraphElement = leaf.getParagraph();
			if ( para.isInTable() )
				return;
			*/
			// Delete the next character if it's a caret selection, and allow adejacent delete next's to merge
			// If it's a range selection, delete the range and disallow merge
			var deleteOp:DeleteTextOperation;
			if (operationState.absoluteStart == operationState.absoluteEnd)
			{
				var nextPosition:int = NavigationUtil.nextAtomPosition(textFlow, absoluteStart);
				deleteOp = new DeleteTextOperation(operationState, new SelectionState(textFlow, absoluteStart, nextPosition, pointFormat), true /* allowMerge for deleteForward */);	
			}
			else 
				deleteOp = new DeleteTextOperation(operationState, operationState, false /* don't allow merge when deleting by range */);			
			doOperation(deleteOp);			

		}

		/** 
		 * @copy IEditManager#deleteNextWord()
		 * @includeExample examples\EditManager_deleteNextWord.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function deleteNextWord(operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).deleteNextWord(operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if ((!operationState) || ((operationState.anchorPosition == operationState.activePosition) && (operationState.anchorPosition >= textFlow.textLength - 1)))
				return;
				
			var nextWordSelState:SelectionState = getNextWordForDelete(operationState.absoluteStart);
			if (nextWordSelState.anchorPosition == nextWordSelState.activePosition)
				//nothing to delete. No operation required.
				return;			

			setSelectionState(new SelectionState(textFlow, operationState.absoluteStart, operationState.absoluteStart, new TextLayoutFormat(textFlow.findLeaf(operationState.absoluteStart).format)));
			doOperation(new DeleteTextOperation(operationState, nextWordSelState, false));						
		}

		// Sadly, this is NOT the same as the cursor key movement - specialized for delete forward one word
		private function getNextWordForDelete(absoluteStart:int):SelectionState
		{
			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
			var paraEl:ParagraphElement = leafEl.getParagraph();
			var paraElAbsStart:int = paraEl.getAbsoluteStart();
			
			var nextPosition:int = -1;
			
			if ((absoluteStart - paraElAbsStart) >= (paraEl.textLength - 1))
			{
				// We're at the end of the paragraph, delete the following newline
				nextPosition = NavigationUtil.nextAtomPosition(textFlow, absoluteStart);
			}
			else
			{
				var curPos:int = absoluteStart - paraElAbsStart;			
				var curPosCharCode:int = paraEl.getCharCodeAtPosition(curPos);
				var prevPosCharCode:int = -1;
				if (curPos > 0) prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
				var nextPosCharCode:int = paraEl.getCharCodeAtPosition(curPos + 1);
				if (!CharacterUtil.isWhitespace(curPosCharCode) && ((curPos == 0) || ((curPos > 0) && CharacterUtil.isWhitespace(prevPosCharCode)))) {
					nextPosition = NavigationUtil.nextWordPosition(textFlow, absoluteStart);
				} else {
					if (CharacterUtil.isWhitespace(curPosCharCode) && ((curPos > 0) && !CharacterUtil.isWhitespace(prevPosCharCode))) {
						//if at beginning of space word then get through all the spaces					
						curPos = paraEl.findNextWordBoundary(curPos);
					}
					nextPosition = paraElAbsStart + paraEl.findNextWordBoundary(curPos);
				}
			}
			return new SelectionState(textFlow, absoluteStart, nextPosition, pointFormat);
		}
		
		/**
		 * @copy IEditManager#deletePreviousCharacter()
		 * @includeExample examples\EditManager_deletePreviousCharacter.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function deletePreviousCharacter(operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).deletePreviousCharacter(operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			var deleteOp:DeleteTextOperation;
			if (operationState.absoluteStart == operationState.absoluteEnd)
			{	
				// with a caret selection, generally delete the previous character, but also check whether to move the paragraph out of its parent chain (like backspacing at the beginning of a list)
				var leaf:FlowLeafElement = textFlow.findLeaf(operationState.absoluteStart);
				var para:ParagraphElement = leaf.getParagraph();
				var parent:FlowGroupElement = para.parent;
				
				var movePara:Boolean = false;
				if(!(parent is TextFlow))
				{
					if(operationState.absoluteStart == para.getAbsoluteStart() && parent.getChildIndex(para) == 0 && // cursor is at start of this paragraph AND para is at beginning of parent AND
						(!(parent is ListItemElement) || parent.parent.getChildIndex(parent) == 0)) // if parent is a listItem, it's the first item in the list
					{
						movePara = true;
					}
				}
				if(movePara)
				{
					/*
					should not be necessary...
					// mjzhang: fix for table feature
					if ( para.isInTable() )
						return;
					*/
					var source:FlowGroupElement;
					var target:FlowGroupElement;
					var numElementsToMove:int;
					var targetIndex:int;
					
					if(parent is ListItemElement)
					{
						if(parent.parent.parent is ListElement)
						{
							// move the whole list item to grandparent list
							source = parent.parent;
							numElementsToMove = 1;
							target = parent.parent.parent;
							targetIndex = parent.parent.parent.getChildIndex(parent.parent);
						}
						else
						{
							// move everything inside the list item out into grandparent
							source = para.parent;
							numElementsToMove = para.parent.numChildren;
							target = parent.parent.parent;
							targetIndex = parent.parent.parent.getChildIndex(parent.parent);
						}
					}
					else
					{
						// move just the first paragraph out into grandparent
						source = para.parent;
						numElementsToMove = 1;
						target = parent.parent;
						targetIndex = parent.parent.getChildIndex(parent);
					}
					doOperation(new MoveChildrenOperation(operationState, source, 0, numElementsToMove, target, targetIndex));
				}
				else
				{
					var beginPrevious:int = NavigationUtil.previousAtomPosition(textFlow, operationState.absoluteStart);
					deleteOp = new DeleteTextOperation(operationState, new SelectionState(textFlow, beginPrevious, operationState.absoluteStart), true /* allowMerge */);
					doOperation(deleteOp);
				}
			}
			else	// just delete the range
			{
				deleteOp = new DeleteTextOperation(operationState);
				doOperation(deleteOp);
			}
		}
		
		/** 
		 * @copy IEditManager#deletePreviousWord()
		 * @includeExample examples\EditManager_deletePreviousWord.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function deletePreviousWord(operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).deletePreviousWord(operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
				
			var prevWordSelState:SelectionState = getPreviousWordForDelete(operationState.absoluteStart);
			if (prevWordSelState.anchorPosition == prevWordSelState.activePosition)
				//there is nothing to delete.  No operation required
				return;			
				
			setSelectionState(new SelectionState(textFlow, operationState.absoluteStart, operationState.absoluteStart, new TextLayoutFormat(textFlow.findLeaf(operationState.absoluteStart).format)));
			doOperation(new DeleteTextOperation(operationState, prevWordSelState, false /* don't allow merge */));						
		}		
		
		// Sadly, this is NOT the same as the cursor key movement - specialized for delete backward one word
		private function getPreviousWordForDelete(absoluteStart:int):SelectionState
		{
			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
			var paraEl:ParagraphElement = leafEl.getParagraph();
			var paraElAbsStart:int = paraEl.getAbsoluteStart();

			if (absoluteStart == paraElAbsStart)		// at the start of the paragraph, delete the previous newline. Should insert a space after punctuation.
			{
				var beginPrevious:int = NavigationUtil.previousAtomPosition(textFlow, absoluteStart);
				return new SelectionState(textFlow, beginPrevious, absoluteStart);				
			}

			var curPos:int = absoluteStart - paraElAbsStart;
			var curPosCharCode:int = paraEl.getCharCodeAtPosition(curPos);
			var prevPosCharCode:int = paraEl.getCharCodeAtPosition(curPos - 1);
			var curAbsStart:int = absoluteStart;
			
			if (CharacterUtil.isWhitespace(curPosCharCode) && (curPos != (paraEl.textLength - 1)))
			{
				if (CharacterUtil.isWhitespace(prevPosCharCode)) //this will get you past the spaces
				{
					curPos = paraEl.findPreviousWordBoundary(curPos);
				}
				if (curPos > 0) {
					curPos = paraEl.findPreviousWordBoundary(curPos); //this will get you to the beginning of the word before the space.
					if (curPos > 0) {
						prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
						if (CharacterUtil.isWhitespace(prevPosCharCode)) {
							curPos = paraEl.findPreviousWordBoundary(curPos);
						}
					}
				}
			} else { //you are here if you are not on a space
				if (CharacterUtil.isWhitespace(prevPosCharCode))
				{
					curPos = paraEl.findPreviousWordBoundary(curPos); //this will get you past the spaces
					if (curPos > 0) {
						curPos = paraEl.findPreviousWordBoundary(curPos);
						// mjzhang : Fix for bug#2821844 Text controls make bad assumptions with Ctrl Backspace
						//if (curPos > 0) {
						//	prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
						//	if (!CharacterUtil.isWhitespace(prevPosCharCode)) {
						//		curAbsStart--; //Microsoft Word insists on keeping the original space
						//		               //if the ending position does not have a space.
						//	}
						//}
					}
				} else { //just delete to the previous word boundary
					curPos = paraEl.findPreviousWordBoundary(curPos);
				}
			}
			return new SelectionState(textFlow, paraElAbsStart + curPos, curAbsStart);
		}		

		public function insertTableElement(table:TableElement, operationState:SelectionState = null):void
		{
			// handle insertions when a table cells is active. (nested tables probably do not work now though...)
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).insertTableElement(table, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			
			var operation:InsertTableElementOperation = new InsertTableElementOperation(operationState, table);
			doOperation(operation);
		}
		
		/** 
		 * @copy IEditManager#insertText()
		 * @includeExample examples\EditManager_insertText.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function insertText(text:String, origOperationState:SelectionState = null):void
		{
			// handle insertions when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).insertText(text, origOperationState);
				return;
			}
			// if there's another insert operation waiting to be executed, 
			// just add to it, if possible
			if (origOperationState == null && pendingInsert)
				pendingInsert.text += text;
			else 
			{
				var operationState:SelectionState = defaultOperationState(origOperationState);
				if (!operationState)
					return;
				
				// rather than execute the insert immediately, create
				// it and wait for the next frame, in order to batch
				// keystrokes.
				pendingInsert = new InsertTextOperation(operationState, text);
				
				var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
				if (captureLevel == 0 && origOperationState == null && controller && controller.container && allowDelayedOperations)
				{
					enterFrameListener = controller.container;
					enterFrameListener.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 1.0, true);
				}
				else
					flushPendingOperations();
			}
		}
				

		
		/** 
		 * @copy IEditManager#overwriteText()
		 * 
		 * @includeExample examples\EditManager_overwriteText.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function overwriteText(text:String, operationState:SelectionState = null):void
		{
			// handle overwrites when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).overwriteText(text, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			var selState:SelectionState = getSelectionState();
			NavigationUtil.nextCharacter(selState,true);
			doOperation(new InsertTextOperation(operationState, text, selState));
		}

		/** 
		 * @copy IEditManager#insertInlineGraphic()
		 * Returns the new InlineGraphicElement that was created.
		 * @includeExample examples\EditManager_insertInlineGraphic.as -noswf
		 * 
		 * @playerversion Flash 10 + 10.2
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * @see flash.text.engine.TextRotation
		 */			
		public function insertInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):InlineGraphicElement
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				return (subManager as IEditManager).insertInlineGraphic(source, width, height, options, operationState);

			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;

			var operation:InsertInlineGraphicOperation = new InsertInlineGraphicOperation(operationState, source, width, height, options);
			doOperation(operation);
			return operation.newInlineGraphicElement;
		}	
		
		/** 
		 * @copy IEditManager#modifyInlineGraphic()
		 * @includeExample examples\EditManager_modifyInlineGraphic.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */			
		public function modifyInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).modifyInlineGraphic(source, width, height, options, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			doOperation(new ModifyInlineGraphicOperation(operationState, source, width, height, options));
		}					
		
		/** 
		 * @copy IEditManager#applyFormat()
		 * 
		 * @includeExample examples\EditManager_applyFormat.as -noswf
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function applyFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).applyFormat(leafFormat, paragraphFormat, containerFormat, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			// apply to the current selection else remember new format for next char typed
			doOperation(new ApplyFormatOperation(operationState, leafFormat, paragraphFormat, containerFormat));
		}
		/** 
		 * @copy IEditManager#clearFormat()
		 * 
		 * Known issue is that undefines of leafFormat values with a point selection are not applied at the next insertion.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function clearFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).clearFormat(leafFormat, paragraphFormat, containerFormat, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			
			// apply to the current selection else remember new format for next char typed
			doOperation(new ClearFormatOperation(operationState, leafFormat, paragraphFormat, containerFormat));
		}
		/** 
		 * @copy IEditManager#applyLeafFormat()
		 * 
		 * @includeExample examples\EditManager_applyLeafFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function applyLeafFormat(characterFormat:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				(subManager as IEditManager).applyLeafFormat(characterFormat, operationState);
			else 
				applyFormat(characterFormat, null, null, operationState);
		}

		/** 
		 * @copy IEditManager#applyParagraphFormat()
		 * 
		 * @includeExample examples\EditManager_applyParagraphFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 		 */		
		public function applyParagraphFormat(paragraphFormat:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				(subManager as IEditManager).applyParagraphFormat(paragraphFormat, operationState);
			else
				applyFormat(null, paragraphFormat, null, operationState);
		}

		/** 
		 * @copy IEditManager#applyContainerFormat()
		 * 
		 * @includeExample examples\EditManager_applyContainerFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */		
		public function applyContainerFormat(containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				(subManager as IEditManager).applyContainerFormat(containerFormat, operationState);
			else
				applyFormat(null, null, containerFormat, operationState);
		}
		
		/** 
		 * @copy IEditManager#applyFormatToElement()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function applyFormatToElement(targetElement:FlowElement, format:ITextLayoutFormat, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			doOperation(new ApplyFormatToElementOperation(operationState, targetElement, format, relativeStart, relativeEnd));
		}

		/** 
		 * @copy IEditManager#clearFormatOnElement()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */	
		public function clearFormatOnElement(targetElement:FlowElement, format:ITextLayoutFormat, operationState:SelectionState = null):void
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			
			doOperation(new ClearFormatOnElementOperation(operationState, targetElement, format));
		}
		
		/** 
		 * @copy IEditManager#cutTextScrap()
		 * @includeExample examples\EditManager_cutTextScrap.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 *  @see flashx.textLayout.edit.TextScrap
		 */
		public function cutTextScrap(operationState:SelectionState = null):TextScrap
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				return (subManager as IEditManager).cutTextScrap(operationState);
			
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
				
			if (operationState.anchorPosition == operationState.activePosition)
				return null;

			var tScrap:TextScrap = TextScrap.createTextScrap(operationState);			
			var beforeOpLen:int = textFlow.textLength;						
			doOperation(new CutOperation(operationState, tScrap));
			if (operationState.textFlow.textLength != beforeOpLen)
			{
				return tScrap;
			}									
			return null;			
		}
		
		/** 
		 * @copy IEditManager#pasteTextScrap()
		 * @includeExample examples\EditManager_pasteTextScrap.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 *  @see flashx.textLayout.edit.TextScrap
		 */
		public function pasteTextScrap(scrapToPaste:TextScrap, operationState:SelectionState = null):void
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
			{
				(subManager as IEditManager).pasteTextScrap(scrapToPaste, operationState);
				return;
			}
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			doOperation(new PasteOperation(operationState, scrapToPaste));	
		}
		
		/** 
		 * @copy IEditManager#applyTCY()
		 * Returns the new TCYElement that was created.
		 * @includeExample examples\EditManager_applyTCY.as -noswf
		 * 
		 * @playerversion Flash 10 + 10.2
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */			
		public function applyTCY(tcyOn:Boolean, operationState:SelectionState = null):TCYElement
		{
			// handle when a table cells is active.
			if(subManager && subManager is IEditManager)
				return (subManager as IEditManager).applyTCY(tcyOn, operationState);

			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;

			var operation:ApplyTCYOperation = new ApplyTCYOperation(operationState, tcyOn);
			doOperation(operation);
			return operation.newTCYElement;
		}
		
		/** 
		 * @copy IEditManager#applyLink()
		 * Returns the new LinkElement that was created.
		 * @includeExample examples\EditManager_applyLink.as -noswf
		 * 
		 * @playerversion Flash 10 + 10.2
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */			
		public function applyLink(href:String, targetString:String = null, extendToLinkBoundary:Boolean=false, operationState:SelectionState = null):LinkElement
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return null;
				
			if (operationState.absoluteStart == operationState.absoluteEnd)
				return null;

			var operation:ApplyLinkOperation = new ApplyLinkOperation(operationState, href, targetString, extendToLinkBoundary);
			doOperation(operation);
			return operation.newLinkElement;
		}
		
		/**
		 * @copy IEditManager#changeElementID()
		 * @includeExample examples\EditManager_changeElementID.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0 
	 	*/
		public function changeElementID(newID:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
				
			if (operationState.absoluteStart == operationState.absoluteEnd)
				return;

			doOperation(new ApplyElementIDOperation(operationState, targetElement, newID, relativeStart, relativeEnd));
		}
		
		[Deprecated(replacement="applyFormatToElement", deprecatedSince="2.0")]
		/**
		 * @copy IEditManager#changeStyleName()
		 * @includeExample examples\EditManager_changeStyleName.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0 
		 */
		public function changeStyleName(newName:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.styleName = newName;
			doOperation(new ApplyFormatToElementOperation(operationState, targetElement, format, relativeStart, relativeEnd));
		}
		
		/**
		 * @copy IEditManager#changeTypeName()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0 
		 */
		public function changeTypeName(newName:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;
			
			doOperation(new ApplyElementTypeNameOperation(operationState, targetElement, newName, relativeStart, relativeEnd));
		}
		
		/* CompositeOperations
			Normally when you call doOperation, it gets executed immediately. By calling beginCompositeOperation, you can instead accumulate the
			operations into a CompositeOperation. The CompositeOperation is completed and returned when you call endCompositeOperation, and 
			processing returns to normal state. The client code can then either call doOperation on the CompositeOperation that was returned, 
			or just drop it if the operation should be aborted.
			
			The parentStack is a stack of pending CompositeOperations. 
		*/
		private var parentStack:Array;
		
		/** 
		 * @copy IEditManager#beginCompositeOperation()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @includeExample examples\EditManager_beginCompositeOperation.as -noswf
		 */
		public function beginCompositeOperation():void
		{
			// not sure if there's issues with composite operations and tables
			flushPendingOperations();
			
			if (!parentStack)
				parentStack = [];
			var operation:CompositeOperation = new CompositeOperation();
			
			if (!_imeSession)
			{	
				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,false,operation,captureLevel,null);
				textFlow.dispatchEvent(opEvent);
			}
			
			CONFIG::debug { assert(!operation.operations  || operation.operations.length == 0, "opening a composite operation that already has operations"); }
			operation.setGenerations(textFlow.generation, 0);
			++captureLevel;
			var parent:Object = new Object();
			parent.operation = operation;
			parent.captureLevel = captureLevel;
			parentStack.push(parent);
		}
		
		/** 
		 * @copy IEditManager#endCompositeOperation()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @includeExample examples\EditManager_beginCompositeOperation.as -noswf
		 */
		public function endCompositeOperation():void
		{
			// not sure if there's issues with composite operations and tables
			CONFIG::debug { assert( parentStack.length > 0 || captureLevel <= 0, "EditManager.endOperation - no composite operation in progress"); }
			
			--captureLevel;
			
			var parent:Object = parentStack.pop();
			var operation:FlowOperation = parent.operation;
			if (!_imeSession)
			{	
				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,false,operation,captureLevel,null);
				textFlow.dispatchEvent(opEvent);
			}
			operation.setGenerations(operation.beginGeneration, textFlow.generation);
			finalizeDo(operation);
		}
		
		/** @private
		 * Handler function called when the selection has been changed.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * @param doDispatchEvent	true if a selection changed event will be sent
		 * @param resetPointFormat	true if the attributes associated with the caret should be discarded
		 */
		tlf_internal override function selectionChanged(doDispatchEvent:Boolean = true, resetPointFormat:Boolean=true):void
		{	
			if (_imeSession)
				_imeSession.selectionChanged();
			
			super.selectionChanged(doDispatchEvent, resetPointFormat);
		}


	}
}
