////////////////////////////////////////////////////////////////////////////////
//
//  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.TableDataCellElement;
	import flashx.textLayout.elements.TableElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.elements.TextRange;
	import flashx.textLayout.events.FlowOperationEvent;
	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
	{
		 /**
		 *  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;
							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 shift 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
							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
						{
							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;
		}
		
		/** @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;
			}

			if (textFlow.flowComposer)
			{
				 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);	
				}
			}

			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
		{

			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
		{
			operationState = defaultOperationState(operationState);
			if (!operationState)
				return;

			// 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
		{
			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
		{
			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)
				{
					// 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
		{
			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
		{
			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
		{
			// 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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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
		{
			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);
		}


	}
}
