////////////////////////////////////////////////////////////////////////////////
//
//  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.desktop.Clipboard;
	import flash.desktop.ClipboardFormats;
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Stage;
	import flash.errors.IllegalOperationError;
	import flash.events.ContextMenuEvent;
	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.text.engine.TextLine;
	import flash.text.engine.TextLineValidity;
	import flash.text.engine.TextRotation;
	import flash.ui.ContextMenu;
	import flash.ui.Keyboard;
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	import flash.utils.getQualifiedClassName;
	
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.container.ColumnState;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.elements.TextRange;
	import flashx.textLayout.events.FlowOperationEvent;
	import flashx.textLayout.events.SelectionEvent;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Category;
	import flashx.textLayout.formats.Direction;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.operations.CopyOperation;
	import flashx.textLayout.operations.FlowOperation;
	import flashx.textLayout.property.Property;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.NavigationUtil;
	
	use namespace tlf_internal;
	
	/** 
	 * The SelectionManager class manages text selection in a text flow.
	 * 
	 * <p>The selection manager keeps track of the selected text range, manages its formatting, 
	 * and can handle events affecting the selection. To allow a user to make selections in
	 * a text flow, assign a SelectionManager object to the <code>interactionManager</code>
	 * property of the flow. (To allow editing, assign an instance of the EditManager class,
	 * which extends SelectionManager.)</p>
	 *
	 * <p>The following table describes how the SelectionManager class handles keyboard shortcuts:</p>
	 *
	 * <table class="innertable" width="100%">
	 * <thead>
	 * <tr><th></th><th></th><th align = "center">TB,LTR</th><th align = "right"></th><th></th><th align = "center">TB,RTL</th><th></th><th></th><th align = "center">TL,LTR</th><th></th><th></th><th align = "center">RL,RTL</th><th></th></tr>
	 * <tr><th></th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th></tr>
	 * </thead>
	 * <tr><td>leftarrow</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td></tr>
	 * <tr><td>uparrow</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td></tr>
	 * <tr><td>rightarrow</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td></tr>
	 * <tr><td>downarrow</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td></tr>
	 * <tr><td>home</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td></tr>
	 * <tr><td>end</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td></tr>
	 * <tr><td>pagedown</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td></tr>
	 * <tr><td>pageup</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td></tr>
	 * </table>
	 *
	 * <p><strong>Key:</strong>
	 * <ul>
	 *	<li>none = no modifier</li>
	 *	<li>ctrl, shift, alt = modifiers</li>
	 *	<li>alt-key and ctrl+alt-key are the same on all platforms (on some platforms alt-key does not get to TLF)</li>
	 *	<li>shift key modifes to extend the active end of the selection in the specified manner</li>			
	 *	<li>TB (top-to-bottom),RL (right-to-left) are textFlow level <code>blockProgression</code> settings</li>						
	 * 	<li>LTR (left-to-right),RTL (right-to-left) are textFlow level <code>direction</code> settings</li>					
	 *	<li>next and prev in logical order in the textFlow - the effect in RTL text is that the selection moves in the physical direction</li>
	 * </ul></p>
	 * 
	 * @see EditManager
	 * @see flashx.elements.TextFlow
	 * 
	 * @includeExample examples\SelectionManager_example.as -noswf
	 * 
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
 	 * @langversion 3.0
	 */
	public class SelectionManager implements ISelectionManager
	{		
		private var _focusedSelectionFormat:SelectionFormat;
		private var _unfocusedSelectionFormat:SelectionFormat;
		private var _inactiveSelectionFormat:SelectionFormat;
		private var _selFormatState:String = SelectionFormatState.UNFOCUSED;
		private var _isActive:Boolean;
		
		/** The TextFlow of the selection. */
		private var _textFlow:TextFlow;
		
		// current range of selection
		/** Anchor point of the current selection, as an index into the TextFlow. */
		private var anchorMark:Mark;
		/** Active end of the current selection, as an index into the TextFlow. */
		private var activeMark:Mark;
		
		// used to save pending attributes at a point selection
		private var _pointFormat:ITextLayoutFormat;
		/** 
		 * The format that will be applied to inserted text. 
		 * 
		 * TBD: pointFormat needs to be extended to remember user styles and "undefine" of formats from calls to IEditManager.undefineFormat with leafFormat values on a point selection.
		 */
		protected function get pointFormat():ITextLayoutFormat
		{ return _pointFormat; }

		
		/** @private
		 * Ignore the next text input event. This is needed because the player may send a text input event
		 * following by a key down event when ctrl+key is entered. 
		 */
		protected var ignoreNextTextEvent:Boolean = false;
		
		/**
		 *  @private
		 *  For usability reasons, operations are sometimes grouped (merged) so they 
		 *  can be undone together. Certain events, such as changing the selection, may make merging 
		 *  inappropriate. This flag is used to keep track of when operation merging
		 *  is appropriate.  This might need to be moved to SelectionManager later. I'm keeping it
		 *  here for now since I'm unsure if other regular selection operations that we add can
		 *  be undone.
		 */
		protected var allowOperationMerge:Boolean = false;
		
		private var _mouseOverSelectionArea:Boolean = false;	

		CONFIG::debug 
		{
			protected var id:String;
			static private var smCount:int = 0;
		}
		
		/** 
		 * 
		 * Creates a SelectionManager object.
		 * 
		 * <p>Assign a SelectionManager object to the <code>interactionManager</code> property of
		 * a text flow to enable text selection.</p>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function SelectionManager()
		{
			_textFlow = null;
			anchorMark = createMark();
			activeMark = createMark();
			_pointFormat = null;
			_isActive = false;
			CONFIG::debug 
			{
				this.id = smCount.toString();
				smCount++;
			}
		}
		/**
		 * @copy ISelectionManager#getSelectionState()
		 * 
		 * @includeExample examples\SelectionManager_getSelectionState.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.SelectionState
		 */
		public function getSelectionState():SelectionState
		{
			return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat);
		}
				
		/**
		 * @copy ISelectionManager#setSelectionState()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.edit.SelectionState
		 */
		public function setSelectionState(sel:SelectionState):void
		{
			internalSetSelection(sel.textFlow, sel.anchorPosition, sel.activePosition, sel.pointFormat);
		}

		/**
		 *  @copy ISelectionManager#hasSelection()
		 * 
		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function hasSelection():Boolean
		{ return anchorMark.position != -1; }

		/** 
		 *  @copy ISelectionManager#isRangeSelection()
		 * 
		 * @includeExample examples\SelectionManager_isRangeSelection.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */				
		public function isRangeSelection():Boolean
		{ return anchorMark.position != -1 && anchorMark.position != activeMark.position; }
		
		/**
		 * The TextFlow object managed by this selection manager. 
		 * 
		 * <p>A selection manager manages a single text flow. A selection manager can also be
		 * assigned to a text flow by setting the <code>interactionManager</code> property of the
		 * TextFlow object.</p>
		 * 
		 * @see flashx.textLayout.elements.TextFlow#interactionManager
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 		 * @langversion 3.0
 		 */
		public function get textFlow():TextFlow
		{
			return _textFlow;
		}
		public function set textFlow(value:TextFlow):void
		{
			if (_textFlow != value)
			{
				if (_textFlow)
					flushPendingOperations();
				
				clear();
				
				_textFlow = value;
				
				if (_textFlow && _textFlow.interactionManager != this)
					_textFlow.interactionManager = this;
			}
		}  
		
		/**
		 *  @copy ISelectionManager#editingMode
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.EditingMode
		 */
		 public function get editingMode():String
		 {
		 	return EditingMode.READ_SELECT;
		 }				 
		 
		/** 
		 *  @copy ISelectionManager#windowActive
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		 public function get windowActive():Boolean
		 {
		 	return _selFormatState != SelectionFormatState.INACTIVE;
		 }
		 
		/** 
		 *  @copy ISelectionManager#focused
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/
		 public function get focused():Boolean
		 {
		 	return _selFormatState == SelectionFormatState.FOCUSED;
		 }
		 
		/**
		 *  @copy ISelectionManager#currentSelectionFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.SelectionFormat
		 */
		 public function get currentSelectionFormat():SelectionFormat
		 { 
		 	if (_selFormatState == SelectionFormatState.UNFOCUSED)
		 	{
		 		return unfocusedSelectionFormat;
		 	}
		 	else if (_selFormatState == SelectionFormatState.INACTIVE)
		 	{
		 		return inactiveSelectionFormat;
		 	}
		 	return focusedSelectionFormat;
		 }
		 
		/**
		 *  @copy ISelectionManager#focusedSelectionFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.SelectionFormat
		 */
		 public function set focusedSelectionFormat(val:SelectionFormat):void
		 { 
	 		_focusedSelectionFormat = val;
		 	if (this._selFormatState == SelectionFormatState.FOCUSED)
		 		refreshSelection();
		 }
		 
		/**
		 * @private - docs on setter
		 */
		 public function get focusedSelectionFormat():SelectionFormat
		 { 
		 	return _focusedSelectionFormat ? _focusedSelectionFormat : (_textFlow ? _textFlow.configuration.focusedSelectionFormat : null);
		 }		 

		/**
		 *  @copy ISelectionManager#unfocusedSelectionFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.SelectionFormat
		 */
		 public function set unfocusedSelectionFormat(val:SelectionFormat):void
		 { 
	 		_unfocusedSelectionFormat = val;
	 		if (this._selFormatState == SelectionFormatState.UNFOCUSED)
	 			refreshSelection();
		 }		 	
		 
		/**
		 *  @private - docs on setter
		 */
		 public function get unfocusedSelectionFormat():SelectionFormat
		 { 
		 	return _unfocusedSelectionFormat ? _unfocusedSelectionFormat : (_textFlow ? _textFlow.configuration.unfocusedSelectionFormat : null);
		 }
		 
		/**
		 *  @copy ISelectionManager#inactiveSelectionFormat
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.edit.SelectionFormat
		 */
		 public function set inactiveSelectionFormat(val:SelectionFormat):void
		 { 
	 		_inactiveSelectionFormat = val;
	 		if (this._selFormatState == SelectionFormatState.INACTIVE)
	 			refreshSelection();
		 }		 	
		 
		/**
		 * @private - docs on setter
		 */
		 public function get inactiveSelectionFormat():SelectionFormat
		 { 
		 	return _inactiveSelectionFormat ? _inactiveSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
		 }		 
		 
		 /** @private - returns the selectionFormatState.  @see flashx.textLayout.edit.SelectionFormatState */
		 tlf_internal function get selectionFormatState():String
		 { return _selFormatState; }
		 
		 /** @private - sets the SelectionFormatState. @see flashx.textLayout.edit.SelectionFormatState */
		 tlf_internal function setSelectionFormatState(selFormatState:String):void
		 {
		 	if (selFormatState != _selFormatState)
		 	{		 			
		 	//	trace("changing selection state: was", _selFormatState, "switching to", selFormatState, "on selectionManager", id);
			 	var oldSelectionFormat:SelectionFormat = currentSelectionFormat;
			 	_selFormatState = selFormatState;
			 	var newSelectionFormat:SelectionFormat = currentSelectionFormat;
			 	if (!newSelectionFormat.equals(oldSelectionFormat))
			 	{
			 		refreshSelection();
			 	}
			 }
		 }
		 
		 /** @private */
		 tlf_internal function cloneSelectionFormatState(oldISelectionManager:ISelectionManager):void
		 {
			var oldSelectionManager:SelectionManager = oldISelectionManager as SelectionManager;
			if (oldSelectionManager)
			{
				_isActive = oldSelectionManager._isActive;
				_mouseOverSelectionArea = oldSelectionManager._mouseOverSelectionArea;
				setSelectionFormatState(oldSelectionManager.selectionFormatState);
			}
		 }
		 
		/**
		 * Gets the SelectionState at the specified mouse position.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * @see flashx.textLayout.edit.SelectionState
		 * @param currentTarget		The object that is actively processing the Event object with an event listener.
		 * @param target			The InteractiveObject instance under the pointing device. The target is not always the object in the display list that registered the event listener. Use the currentTarget property to access the object in the display list that is currently processing the event.
		 * @param localX			The horizontal coordinate at which the event occurred relative to the containing sprite.
		 * @param localY			The vertical coordinate at which the event occurred relative to the containing sprite.
		 * @param extendSelection	Indicates that only activeIndex should move
		 * @return the resulting SelectionState
		 */		 		 		 		 		 		 		 		 		 		 		 		 		 		 
		 private function selectionPoint(currentTarget:Object, target:InteractiveObject, localX:Number, localY:Number, extendSelection:Boolean = false):SelectionState
		 {
		 	//trace("selectionPoint");
		 	if (!_textFlow) 
		 		return null;
		 	if (!hasSelection()) 
		 		extendSelection = false;
		 	
			var begIdx:int = anchorMark.position;
			var endIdx:int = activeMark.position;
		 	
			endIdx = computeSelectionIndex(_textFlow, target, currentTarget, localX, localY);
			if (endIdx == -1)
				return null;	// ignore
			
			// attempt to position in the logical hierarchy
			var leaf:FlowLeafElement = _textFlow.findLeaf(endIdx);
			
			// make sure we aren't selecting after the paragraph terminating character
			var para:ParagraphElement = leaf.getParagraph();
			if (endIdx == para.getAbsoluteStart() + para.textLength)
				endIdx--;
				
			if (!extendSelection)
				begIdx = endIdx;							

			if (begIdx == endIdx)
			{
				if (leaf is InlineGraphicElement) {
					endIdx++;
				}
				begIdx = NavigationUtil.updateStartIfInReadOnlyElement(_textFlow, begIdx);
				endIdx = NavigationUtil.updateEndIfInReadOnlyElement(_textFlow, endIdx);
			} else {
				endIdx = NavigationUtil.updateEndIfInReadOnlyElement(_textFlow, endIdx);
			}			
		 	return new SelectionState(textFlow, begIdx, endIdx);
		 }		 		 		 
		 
		/** 
		 *  @copy ISelectionManager#setFocus()
		 * 
		 * @includeExample examples\SelectionManager_setFocus.as -noswf
		 * 
		* @playerversion Flash 10
		* @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/
		 public function setFocus():void
		 {
			if (hasSelection())
		 	{
			 //	trace("setFocus sm", id);

		 		// container with the activePosition gets the key focus
		 		if (_textFlow.flowComposer)
		 			_textFlow.flowComposer.setFocus(activePosition,false);
		 		setSelectionFormatState(SelectionFormatState.FOCUSED);
		 	}
		 }
		 
		/**
		 *  @copy ISelectionManager#anchorPosition
		 */
		public function get anchorPosition() : int
		{
			return anchorMark.position;
		}
		/**
		 *  @copy ISelectionManager#activePosition
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function get activePosition() : int
		{
			return activeMark.position;			
		}
		/**
		 *  @copy ISelectionManager#absoluteStart
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function get absoluteStart() : int
		{
			return (anchorMark.position < activeMark.position) ? anchorMark.position : activeMark.position;
		}
		/**
		 *  @copy ISelectionManager#absoluteEnd
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function get absoluteEnd() : int
		{
			return (anchorMark.position > activeMark.position) ? anchorMark.position : activeMark.position;
		}
		
		/** 
		 *  @copy ISelectionManager#selectAll
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.compose.IFlowComposer
		 */
		public function selectAll() : void
		{
			selectRange(0, int.MAX_VALUE);
		}
		
		/** 
		 *  @copy ISelectionManager#selectRange
		 * 
		 * @includeExample examples\SelectionManager_selectRange.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
 	 	 * 
		 * @see flashx.textLayout.compose.IFlowComposer
		 */
		public function selectRange(anchorPosition:int, activePosition:int) : void
		{
			flushPendingOperations();
			
			// anchor and active can be in any order
			// TODO: range check and clamp anchor,active
			if (anchorPosition != anchorMark.position || activePosition != activeMark.position)
			{	
				clearSelectionShapes();
					
				internalSetSelection(_textFlow, anchorPosition, activePosition);
				
				// selection changed
				selectionChanged();		
				
				allowOperationMerge = false;
			}
		}
		
		private function internalSetSelection(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null) : void
		{
			_textFlow = root;
			
			// clamp anchor/active
			if (anchorPosition < 0 || activePosition < 0)
			{
				anchorPosition = -1;
				activePosition = -1;
			}
			
			if (anchorPosition != -1 && activePosition != -1)
			{
				if (anchorPosition >= _textFlow.textLength)
					anchorPosition = _textFlow.textLength - 1;
				
				if (activePosition >= _textFlow.textLength)
					activePosition = _textFlow.textLength - 1;
			}

			_pointFormat = format;
			anchorMark.position = anchorPosition; // NavigationUtil.updateStartIfInReadOnlyElement(root, anchorPosition);
			activeMark.position = activePosition; // NavigationUtil.updateEndIfInReadOnlyElement(root, activePosition);
		//	trace("Selection ", anchorMark, "to", activeMark.position);
		}		
		
		/** Clear any active selections.
		 */
		private function clear(): void
		{
			if (hasSelection())
			{
				flushPendingOperations();
				clearSelectionShapes();
				internalSetSelection(_textFlow, -1, -1);
				// selection cleared
				selectionChanged();
				allowOperationMerge = false;
			}
		}
		
		private function addSelectionShapes():void
		{
			var blinking:Boolean = (currentSelectionFormat.pointBlinkRate != 0);
			if (_textFlow.flowComposer && (blinking || (!blinking && (activeMark.position != anchorMark.position))))
			{
				// zero alpha means nothing is drawn so skip it
				if (currentSelectionFormat && 
					(((absoluteStart == absoluteEnd) &&  (currentSelectionFormat.pointAlpha != 0)) ||
					 ((absoluteStart != absoluteEnd) && (currentSelectionFormat.rangeAlpha != 0))))
				{
					var containerIter:int = 0;
					while(containerIter < _textFlow.flowComposer.numControllers)
					{
						_textFlow.flowComposer.getControllerAt(containerIter++).addSelectionShapes(currentSelectionFormat, absoluteStart, absoluteEnd);
					}
				} 
			}
		}
		
		private function clearSelectionShapes():void
		{
			if (_textFlow.flowComposer)
			{
				var containerIter:int = 0;
				while(containerIter < _textFlow.flowComposer.numControllers)
				{
					_textFlow.flowComposer.getControllerAt(containerIter++).clearSelectionShapes();
				}
			}
		}
		
		/** 
		 *  @copy ISelectionManager#refreshSelection()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/
		public function refreshSelection(): void
		{
			if (hasSelection())
			{
				clearSelectionShapes();
				addSelectionShapes();
			}
		}
		
		/** Verifies that the selection is in a legal state. @private */
		CONFIG::debug public function debugCheckSelectionManager():int
		{
			var rslt:int = 0;
			if (hasSelection())
			{
				// both points must be within the flow - may not include trailing \n in final paragraph
				rslt+= assert(anchorMark.position >= 0 && anchorMark.position < _textFlow.textLength,"SelectionManager:validate selBegIdx is out of range");
				rslt += assert(activeMark.position >= 0 && activeMark.position < _textFlow.textLength,"SelectionManager:validate selEndIdx is out of range");
			}
			return rslt;
		}
		
		// ////////////////////////////////////
		// internal selection handling methods
		// ////////////////////////////////////
		
		/** @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 function selectionChanged(doDispatchEvent:Boolean = true, resetPointFormat:Boolean=true):void
		{
			CONFIG::debug { debugCheckSelectionManager(); }	// validates the selection
			
			// clear any remembered attributes for the next character
			if (resetPointFormat) 
				_pointFormat = null;
			
			if (doDispatchEvent)
				textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
		}

		// TODO: this routine could be much more efficient - instead of iterating over all lines in the TextFlow it should iterate over 
		// the visible lines in the container.  Todo that move this routine into ContainerController and use the shapeChildren along with the logic in fillShapeChildren
		static private function computeSelectionIndexInContainer(textFlow:TextFlow, controller:ContainerController, localX:Number, localY:Number):int
		{
			//var origX:Number = localX;
			//var origY:Number = localY;
			var lineIndex:int = -1;
			
			var firstCharVisible:int = controller.absoluteStart;
			var length:int  = controller.textLength;
			
			// try to find a point on the line
			var bp:String = textFlow.computedFormat.blockProgression;
			var isTTB:Boolean = (bp == BlockProgression.RL);
			var isDirectionRTL:Boolean = (textFlow.computedFormat.direction == Direction.RTL);
			
			//Establish perpendicular the coordinate for use with TTB or LTR/RTL lines
			var perpCoor:Number = isTTB ? localX : localY;
			
			//get the nearest column so we can ignore lines which aren't in the column we're looking for.
			//if we don't do this, we won't be able to select across column boundaries.
			var nearestColIdx:int = locateNearestColumn(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
			
			var prevLineBounds:Rectangle = null;
			var previousLineIndex:int = -1;
			
			var lastLineIndexInColumn:int = -1;
			
			// Matching TextFlowLine and TextLine - they are not necessarily valid
			var rtline:TextFlowLine;
			var rtTextLine:TextLine;
			
			for (var testIndex:int = textFlow.flowComposer.numLines - 1; testIndex >= 0; testIndex--)
			{
				rtline = textFlow.flowComposer.getLineAt(testIndex);
				if (rtline.controller != controller || rtline.columnIndex != nearestColIdx)
				{
					// use last line in previous column
					if (lastLineIndexInColumn != -1)
					{
						lineIndex = testIndex+1;
						break;
					}
					continue;
				}
					
				// is this line even displayed?
				if (rtline.absoluteStart < firstCharVisible || rtline.absoluteStart >= firstCharVisible+length)
					continue;
				rtTextLine = rtline.getTextLine();
				if (rtTextLine == null || rtTextLine.parent == null)
					continue;
				
				if (lastLineIndexInColumn == -1)
					lastLineIndexInColumn = testIndex;
					
				var bounds:Rectangle = rtTextLine.getBounds(DisplayObject(controller.container));
				// trace(testIndex.toString(),":",bounds.toString());
				
				var linePerpCoor:Number = isTTB ? bounds.left : bounds.bottom;
				var midPerpCoor:Number = -1;//will be a positive value if prevLineBounds is not null
				
				//if this is not the first test loop, use the prevLineBounds to find the mid-point between the current
				//line, which will be logically up from the previous line - we're walking back-to-front
				if(prevLineBounds)
				{
					//if it's ttb, use the right bounds (ie the top of the line)...
					var prevPerpCoor:Number = (isTTB ? prevLineBounds.right : prevLineBounds.top);
					//calculate the midpoint
					midPerpCoor = (linePerpCoor + prevPerpCoor)/2;
				}
				
				//if the current line is below the click, then this OR the previous line, is the line we're looking for
				var isLineBelow:Boolean = (isTTB ? linePerpCoor > perpCoor : linePerpCoor < perpCoor);
				if(isLineBelow || testIndex == 0)
				{
					//if we haven't calculated the midPerpCoor (-1), then this is the first loop and we want to use the 
					//current line,. Otherwise, if the click's perpendicular coordinate is below the mid point between the current
					//line or below it, then we want to use the line below (ie the previous line, but logically the one after the current)
					var inPrevLine:Boolean = midPerpCoor != -1 && (isTTB ? perpCoor < midPerpCoor : perpCoor > midPerpCoor);
					lineIndex = inPrevLine && testIndex != lastLineIndexInColumn ? testIndex+1 : testIndex;	
					break;
				}
				else
				{
					//this line is below the click, so set the prevLineBounds to bounds of the current line and move on...
					prevLineBounds = bounds;
					previousLineIndex = testIndex;
				}
			}

			if (lineIndex == -1)
			{
				lineIndex = previousLineIndex;
				if (lineIndex == -1)
					return -1;	// no lines in container
			}	
				
			//Get a valid textLine -- check to make sure line is valid, regenerate if necessary, make sure it has correct container relative coordinates
			var tfl:TextFlowLine = textFlow.flowComposer.getLineAt(lineIndex);
			var textLine:TextLine = tfl.getTextLine(true);
			
			// adjust localX,localY to be relative to the textLine.  
			// Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
			// we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
			// but then we'll need to provisionally place a virtualized TextLine in its parent container
			localX -= textLine.x;
			localY -= textLine.y;
			/* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
			localPoint = textLine.globalToLocal(localPoint);
			localX = localPoint.x;
			localY = localPoint.y; */
			
			var lastAtomRect:Rectangle = new Rectangle(0, 0, 0, 0);
			var textFlowLine:TextFlowLine = TextFlowLine(textLine.userData);
			var startOnNextLineIfNecessary:Boolean = false;
			
			if (isDirectionRTL) {
				lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 1);
			} else {
				if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.textLength) {
					if (textLine.atomCount > 1) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 2);
				} else {
					var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
					var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
					if (lastChar == " ") {
						if (textLine.atomCount > 1) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 2);
					} else {
						startOnNextLineIfNecessary = true;
						if (textLine.atomCount > 0) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 1);
					}
				}
			}
						
			if (!isTTB)
			{
				if (localX < 0)
					localX = 0;
				else if (localX > (lastAtomRect.x + lastAtomRect.width))
				{
					if (startOnNextLineIfNecessary) 
						return textFlowLine.absoluteStart + textFlowLine.textLength;
					localX = lastAtomRect.x + lastAtomRect.width;
				}
			}
			else
			{	
				if (localY < 0)
					localY = 0;
				else if (localY > (lastAtomRect.y + lastAtomRect.height))
				{
					if (startOnNextLineIfNecessary) 
						return textFlowLine.absoluteStart + textFlowLine.textLength;			
					localY = lastAtomRect.y + lastAtomRect.height;
				}
			}
			
			var result:int = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
			// trace("computeSelectionIndexInContainer:(",origX,origY,")",textFlow.flowComposer.getControllerIndex(controller).toString(),lineIndex.toString(),result.toString());
			return result != -1 ? result : firstCharVisible + length;	
		}
		
		static private function locateNearestColumn(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):int
		{
			var colIdx:int = 0;
			//if we only have 1 column, no need to perform calculation...
			var columnState:ColumnState = container.columnState;

			//we need to compare the current column to the nextColmn
			while(colIdx < columnState.columnCount - 1)
			{
				var curCol:Rectangle  = columnState.getColumnAt(colIdx);
				var nextCol:Rectangle = columnState.getColumnAt(colIdx + 1);
				
				if(curCol.contains(localX, localY)) //in current column
					break;
				
				if(nextCol.contains(localX, localY))//in next column
				{
					++colIdx;
					break;
				}
				else
				{
					if(wm == BlockProgression.RL)
					{
						//if localY is above curCol || between columns, but close to current
						if(localY < curCol.top || localY < nextCol.top && Math.abs(curCol.bottom - localY) <= Math.abs(nextCol.top - localY))
							break;
						
						if(localY > nextCol.top)//between but closer to nextCol
						{
							++colIdx;
							break;
						}
					}
					else
					{
						if(direction  == Direction.LTR)
						{
							//if localX is left of curCol || between columns but closer to current, break here
							if(localX < curCol.left || localX < nextCol.left && Math.abs(curCol.right - localX) <= Math.abs(nextCol.left - localX)) 
								break;
							if(localX < nextCol.left) // between, but closer to next column
							{
								++colIdx;
								break;
							}
						}
						else
						{
							//if localX is right of curCol || between columns, but closer to current
							if(localX > curCol.right || localX > nextCol.right && Math.abs(curCol.left - localX) <= Math.abs(nextCol.right - localX))
								break;
							
							if(localX > nextCol.right) // between, but closer to next column
							{
								++colIdx;
								break;
							}
						} 
					}
				}
				
				//increment colIdx.  If this is the last pass through, then the conditions above were never met
				//so we want the last column
				++colIdx;
			}

			
			return colIdx;
		}
		
		static private function computeSelectionIndexInLine(textFlow:TextFlow, textLine:TextLine,localX:Number,localY:Number):int
		{
			if (!(textLine.userData is TextFlowLine))
				return -1;	// not a TextLayout generated line
				
			var rtline:TextFlowLine = TextFlowLine(textLine.userData);
			if (rtline.validity == TextLineValidity.INVALID)
				return -1;	// not currently composed 
			textLine = rtline.getTextLine(true);	// make sure the TextLine is not released
			
				
			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
			var perpCoor:Number = isTTB ? localX : localY;
			
			// new code for builds 385 and later
			var pt:Point = new Point();
			pt.x = localX;
			pt.y = localY;
			
			// in most cases, we want to "fixup" the coordiates of the x and y coordinates
			//because we could be getting a positive results for a click in the line, but the
			//coordinates do not match any particular glyph.  However, there are cases where the 
			//fix leads to bad results. For example, if there is a TCY run, this code will always cause
			//a selection to be created in the middle of the run, meaning idividual glyphs cannot be selected.
			//
			//As a result, we need to be performing the less common case check prior to adjusting the 
			//coordinates.
			pt = textLine.localToGlobal(pt);
			var elemIdx:int = textLine.getAtomIndexAtPoint(pt.x,pt.y);
			//trace("global point: " + pt);
			//trace("elemIdx: " + elemIdx);
			if(elemIdx == -1)
			{
				//reset the pt
				pt.x = localX;
				pt.y = localY;
				
				//make adjustments
				if (pt.x < 0 || (isTTB && perpCoor > textLine.ascent))
					pt.x = 0;
				if (pt.y < 0 || (!isTTB && perpCoor > textLine.descent))
					pt.y = 0;
				
				//get the global again and get try for the element again
				pt = textLine.localToGlobal(pt);
				elemIdx = textLine.getAtomIndexAtPoint(pt.x,pt.y);
				//trace("global point (second): " + pt);
				//trace("elemIdx (second): " + elemIdx);
			}
			
			//now we REALLY don't have a glyph, so return the head or tail of the line.
			if (elemIdx == -1)
			{
				//we need to use global coordinates here.  reset pt and get conversion...
				pt.x = localX;
				pt.y = localY;
				pt = textLine.localToGlobal(pt)
				
				if(!isTTB)
					return (pt.x <= textLine.x) ? rtline.absoluteStart : (rtline.absoluteStart + rtline.textLength - 1);
				else
					return (pt.y <= textLine.y) ? rtline.absoluteStart : (rtline.absoluteStart + rtline.textLength - 1);
			}
			
			// get the character box and if check we are past the middle select past this character. 
			var glyphRect:Rectangle = textLine.getAtomBounds(elemIdx);
			// trace("idx",elemIdx,"x",glyphRect.x,"y",glyphRect.y,"width",glyphRect.width,"height",glyphRect.height,"localX",localX,"localY",localY,"textLine.x",textLine.x);
			var leanRight:Boolean = false;
			if(glyphRect)
			{	
				//if this is TTB and NOT TCY determine lean based on Y coordinates...
				if(isTTB && textLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
					leanRight = (localY > (glyphRect.y + glyphRect.height/2));
				else //use X..
					leanRight = (localX > (glyphRect.x + glyphRect.width/2));
			}
			
			var paraSelectionIdx:int;
			if ((textLine.getAtomBidiLevel(elemIdx) % 2) != 0) // Right to left case, right is "start" unicode
				paraSelectionIdx = leanRight ? textLine.getAtomTextBlockBeginIndex(elemIdx) : textLine.getAtomTextBlockEndIndex(elemIdx);
			else  // Left to right case, right is "end" unicode
				paraSelectionIdx = leanRight ? textLine.getAtomTextBlockEndIndex(elemIdx) : textLine.getAtomTextBlockBeginIndex(elemIdx);

			//we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
			
			return rtline.paragraph.getAbsoluteStart() + paraSelectionIdx;
		}
		
		static private function checkForDisplayed(container:DisplayObject):Boolean
		{
			try
			{
				while (container)
				{
					if (!container.visible)
						return false;
					container = container.parent;
					if (container is Stage)
						return true;					
				}
			}
			catch (e:Error)
			{ return true; }
			return false;	// not on the stage

		}
		/** @private - given a target and location compute the selectionIndex */
		static tlf_internal function computeSelectionIndex(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number,localY:Number):int
		{			
			//trace("computeSelectionIndex");
			var rslt:int = 0;
			var containerPoint:Point; // scratch
			
			//Make sure that if the target is a line, that it is part of THIS textFlow and not another.  Can happen
			//when holding down mouse and moving out of one flow and over another. Could also happen when moving over
			//TextLines that are either non-TLF or generated from a factory. 
			var useTargetedTextLine:Boolean = false;
			if (target is TextLine)
			{
				var tfl:TextFlowLine = TextLine(target).userData as TextFlowLine;
				if (tfl)
				{
					var para:ParagraphElement = tfl.paragraph;
					if(para.getTextFlow() == textFlow)
						useTargetedTextLine = true;
				}
			}
			/* trace("got target class", target.toString(), "at (", localX, localY, ")");
			trace("Mapping",localX,localY,"for",target);
			containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
			trace("... Global",containerPoint.x,containerPoint.y);
			containerPoint = DisplayObject(currentTarget).globalToLocal(containerPoint);
			trace("... container Local",containerPoint.x,containerPoint.y); */
			
			if (useTargetedTextLine)
				rslt = computeSelectionIndexInLine(textFlow, TextLine(target), localX, localY);
			else
			{
				var controller:ContainerController;
				for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
				{
					var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
					if (testController.container == target || testController.container == currentTarget)
					{
						controller = testController;
						break;
					}
				}
				if (controller)
				{	
					if (target != controller.container)
					{
						containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
						containerPoint = DisplayObject(controller.container).globalToLocal(containerPoint);
						localX = containerPoint.x;
						localY = containerPoint.y;
					}
					rslt = computeSelectionIndexInContainer(textFlow, controller, localX, localY);			
				} 
				else 
				{
					//the point is someplace else on stage.  Map the target 
					//to the textFlow.container.
					CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"computeSelectionIndex: invalid textFlow"); }
					
					
					// result of the search
					var controllerCandidate:ContainerController = null;
					var candidateLocalX:Number;
					var candidateLocalY:Number;
					var relDistance:Number = Number.MAX_VALUE;
					
					for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
					{
						var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
						
						// displayed??
						if (!checkForDisplayed(curContainerController.container as DisplayObject))
							continue;

						// handle measured containers??
						var bounds:Rectangle = curContainerController.getContentBounds();
						var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.effectivePaddingLeft+bounds.width : curContainerController.compositionWidth;
						var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.effectivePaddingTop+bounds.height : curContainerController.compositionHeight;
						
						containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
						containerPoint = DisplayObject(curContainerController.container).globalToLocal(containerPoint);
						
						// remove scrollRect effects for the distance test but add it back in for the result
						var adjustX:Number = 0;
						var adjustY:Number = 0;
						
						if (curContainerController.hasScrollRect)
						{
							containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
							containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
						}
						
						if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
							(containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
						{
							controllerCandidate = curContainerController;
							candidateLocalX = containerPoint.x+adjustX;
							candidateLocalY = containerPoint.y+adjustY;
							break;
						}
						
						// figure minimum distance of containerPoint to curContainerController - 8 cases
						var relDistanceX:Number = 0;
						var relDistanceY:Number = 0;

						if (containerPoint.x < 0)
						{
							relDistanceX = containerPoint.x;
							if (containerPoint.y < 0)
								relDistanceY = containerPoint.y;
							else if (containerPoint.y > containerHeight)
								relDistanceY = containerPoint.y-containerHeight;
						}
						else if (containerPoint.x > containerWidth)
						{
							relDistanceX = containerPoint.x-containerWidth;
							if (containerPoint.y < 0)
								relDistanceY = containerPoint.y;
							else if (containerPoint.y > containerHeight)
								relDistanceY = containerPoint.y-containerHeight;
						}
						else if (containerPoint.y < 0)
							relDistanceY = -containerPoint.y;
						else
							relDistanceY = containerPoint.y-containerHeight;
						var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;	// could do sqrt but why bother - there is no Math.hypot function
						if (tempDist <= relDistance)
						{
							relDistance = tempDist;
							controllerCandidate = curContainerController;
							candidateLocalX = containerPoint.x+adjustX;
							candidateLocalY = containerPoint.y+adjustY;
						}
					}


					rslt = controllerCandidate ? computeSelectionIndexInContainer(textFlow, controllerCandidate, candidateLocalX, candidateLocalY) : -1;
				}
			}
			
			if (rslt >= textFlow.textLength)
				rslt = textFlow.textLength-1;
			return rslt;
		}
		
		/** initialize a new point selection at click point @private */
		tlf_internal function setNewSelectionPoint(currentTarget:Object, target:InteractiveObject, localX:Number, localY:Number, extendSelection:Boolean = false):Boolean
		{
			var selState:SelectionState = selectionPoint(currentTarget, target, localX, localY, extendSelection);
			if (selState == null)
				return false;	// ignore
			
			if (selState.anchorPosition != anchorMark.position || selState.activePosition != activeMark.position)
			{
			//	clear(false);
			//	internalSetSelection(_textFlow, selState.anchorPosition, selState.activePosition);
				selectRange(selState.anchorPosition, selState.activePosition);
				return true;
			}
			return false;
		}
		
		// ///////////////////////////////////
		// Mouse and keyboard methods 
		// ///////////////////////////////////
		
		/** 
		 *  @copy IInteractionEventHandler#mouseDownHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function mouseDownHandler(event:MouseEvent):void
		{
			handleMouseEventForSelection(event, event.shiftKey);
		}
		
		/**
		 * @copy IInteractionEventHandler#mouseMoveHandler()
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function mouseMoveHandler(event:MouseEvent):void
		{
			var wmode:String = textFlow.computedFormat.blockProgression;			
			if (wmode != BlockProgression.RL) 
				Mouse.cursor = MouseCursor.IBEAM;			
			if (event.buttonDown)
				handleMouseEventForSelection(event, true);
		}
		
		private function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean):void
		{
			var startSelectionActive:Boolean = hasSelection();
			
			if (setNewSelectionPoint(event.currentTarget, event.target as InteractiveObject, event.localX, event.localY, startSelectionActive && allowExtend))
			{
				selectionChanged();
				if (startSelectionActive)
					clearSelectionShapes();

				if (hasSelection())
					addSelectionShapes();
			}		
			allowOperationMerge = false;
		}
		
		/** 
		 * @copy IInteractionEventHandler#mouseUpHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function mouseUpHandler(event:MouseEvent):void
		{
			if (!_mouseOverSelectionArea)
			{
				Mouse.cursor = MouseCursor.AUTO;
			}
		}
		
		private function atBeginningWordPos(activePara:ParagraphElement, pos:int):Boolean
		{
			if (pos == 0) return true;
			var nextPos:int = activePara.findNextWordBoundary(pos);
			nextPos = activePara.findPreviousWordBoundary(nextPos);
			return (pos == nextPos);
		}
				
		
		/** 
		 * @copy IInteractionEventHandler#mouseDoubleClickHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function mouseDoubleClickHandler(event:MouseEvent):void
		{
			if (!hasSelection())
				return;

			// We got a previous single click event that set the selection.
			// Extend it into a selection for the entire word.

			// Adjust the active end to the beginning or end of the nearest word, depending on which end of the selection is active
			var activePara:ParagraphElement = _textFlow.findAbsoluteParagraph(activeMark.position);
			var activeParaStart:int = activePara.getAbsoluteStart();
			var newActiveIndex:int; // adjusted active index
			if (anchorMark.position <= activeMark.position)
				newActiveIndex = activePara.findNextWordBoundary(activeMark.position - activeParaStart) + activeParaStart;
			else
				newActiveIndex = activePara.findPreviousWordBoundary(activeMark.position - activeParaStart) + activeParaStart;
				
			// don't include end of paragraph marker
			if (newActiveIndex == activeParaStart+activePara.textLength)
				newActiveIndex--;

			// Adjust the anchor end. If we're doing a dbl-click shift select to extend the selection, the anchor point stays the same.
			// Otherwise adjust it to the beginning or end of the nearest word, depending on which end of the selection is active
			var newAnchorIndex:int; // adjusted anchor index
			if (event.shiftKey)	
				newAnchorIndex = anchorMark.position;
			else
			{
				var anchorPara:ParagraphElement = _textFlow.findAbsoluteParagraph(anchorMark.position);
				var anchorParaStart:int = anchorPara.getAbsoluteStart();
				if (atBeginningWordPos(anchorPara, anchorMark.position - anchorParaStart))
				{
					newAnchorIndex = anchorMark.position;					
				}
				else
				{
					if (anchorMark.position <= activeMark.position)
						newAnchorIndex = anchorPara.findPreviousWordBoundary(anchorMark.position - anchorParaStart) + anchorParaStart;
					else
						newAnchorIndex = anchorPara.findNextWordBoundary(anchorMark.position - anchorParaStart) + anchorParaStart;
					// don't include end of paragraph marker
					if (newAnchorIndex == anchorParaStart+anchorPara.textLength)
						newAnchorIndex--;
				}	
			}
			
			if (newAnchorIndex != anchorMark.position || newActiveIndex != activeMark.position)
			{
				internalSetSelection(_textFlow, newAnchorIndex, newActiveIndex, null);				
				selectionChanged();
				clearSelectionShapes();

				if (hasSelection())
					addSelectionShapes();
			}
			
			allowOperationMerge = false;
		}

		/** 
		 * @copy IInteractionEventHandler#mouseOverHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */							
		public function mouseOverHandler(event:MouseEvent):void
		{
			_mouseOverSelectionArea = true;
			var wmode:String = textFlow.computedFormat.blockProgression;
			if (wmode != BlockProgression.RL) 
				Mouse.cursor = MouseCursor.IBEAM;	
			else 
				Mouse.cursor = MouseCursor.AUTO;								
		}

		/** 
		 * @copy IInteractionEventHandler#mouseOutHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */					
		public function mouseOutHandler(event:MouseEvent):void
		{
			_mouseOverSelectionArea = false;			
			Mouse.cursor = MouseCursor.AUTO;									
		}		
		
		/** 
		 * @copy IInteractionEventHandler#focusInHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function focusInHandler(event:FocusEvent):void
		{			
			// The focusIn can come before the activate. If so, we don't want the later activate to wipe out the focusIn
			_isActive = true;	
			
			//trace("focusIn event on selectionManager", this.id);
			setSelectionFormatState(SelectionFormatState.FOCUSED);		
		}
		 
		/** 
		 * @copy IInteractionEventHandler#focusOutHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function focusOutHandler(event:FocusEvent):void
		{
			//trace("focusOut event on selectionManager", this.id);
			if (_isActive)	// don't do it if we aren't active
				setSelectionFormatState(SelectionFormatState.UNFOCUSED);			
		}

		/** 
		 * @copy IInteractionEventHandler#activateHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */				
		public function activateHandler(event:Event):void
		{
			//trace("activate selectionManager", id);
			// If there are multiple containers, the selection manager will get multiple activate & deactivate events,
			// one per container. We only want to respond to the first one, because otherwise a focus event that comes
			// in the middle will get its state change overwritten.
			if (!_isActive)
			{		
				_isActive = true;
				setSelectionFormatState(SelectionFormatState.UNFOCUSED);
			}	
		}
		
		/** 
		 * @copy IInteractionEventHandler#deactivateHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */				
		public function deactivateHandler(event:Event):void
		{
			//trace("deactivate selectionManager", id);
			// If there are multiple containers, the selection manager will get multiple activate & deactivate events,
			// one per container. We only want to respond to the first one, because otherwise a focus event that comes
			// in the middle will get its state change overwritten.
			if (_isActive)
			{
				_isActive = false;
				setSelectionFormatState(SelectionFormatState.INACTIVE);			
			}
		}
		
		/** Perform a SelectionManager operation - these may never modify the flow but clients still are able to cancel them. 
		  * 
		  * @playerversion Flash 10
		  * @playerversion AIR 1.5
 	 	  * @langversion 3.0
		  */
		public function doOperation(op:FlowOperation):void
		{
			var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,op,0,null);
			textFlow.dispatchEvent(opEvent);
			if (!opEvent.isDefaultPrevented())
			{
				op = opEvent.operation;
				
				// only copy operation is allowed
				if (!(op is CopyOperation))
					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(op) ]));
				var opError:Error = null;
				try
				{
					op.doOperation();
				}
				catch(e:Error)
				{
					opError = e;
				}
				// operation completed - send event whether it succeeded or not.
				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,op,0,opError);
				textFlow.dispatchEvent(opEvent);
				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
				if (opError)
					throw (opError);
				textFlow.dispatchEvent(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,op,0,null));
			}			
		}

		/** 
		 * @copy IInteractionEventHandler#editHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 		 * @langversion 3.0
		 */	
		public function editHandler(event:Event):void
		{
			switch (event.type)
			{
				case Event.COPY:
					flushPendingOperations();
					doOperation(new CopyOperation(getSelectionState()));

					break;
				case Event.SELECT_ALL:
					flushPendingOperations();
					selectAll();
					refreshSelection();
					break;	
			}
			
		}

		private function handleLeftArrow(event:KeyboardEvent):SelectionState
		{			
			var selState:SelectionState = getSelectionState();
			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
			{
				if(_textFlow.computedFormat.direction == Direction.LTR)
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.previousWord(selState,event.shiftKey);
					else
						NavigationUtil.previousCharacter(selState,event.shiftKey);
				}
				else
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.nextWord(selState,event.shiftKey);
					else
						NavigationUtil.nextCharacter(selState,event.shiftKey);
				}
			} 
			else 
			{
				// always test for altkey first - that way ctrl-alt is the same as alt
				if (event.altKey)
					NavigationUtil.endOfParagraph(selState,event.shiftKey);
				else if (event.ctrlKey)
					NavigationUtil.endOfDocument(selState,event.shiftKey);
				else
					NavigationUtil.nextLine(selState,event.shiftKey);
			}
			return selState;
		}
		
		private function handleUpArrow(event:KeyboardEvent):SelectionState
		{			
			var selState:SelectionState = getSelectionState();
			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
			{
				// always test for altkey first - that way ctrl-alt is the same as alt
				if (event.altKey)
					NavigationUtil.startOfParagraph(selState,event.shiftKey);
				else if (event.ctrlKey)
					NavigationUtil.startOfDocument(selState,event.shiftKey);
				else
					NavigationUtil.previousLine(selState,event.shiftKey);
			}
			else
			{
				if(_textFlow.computedFormat.direction == Direction.LTR)
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.previousWord(selState,event.shiftKey);
					else
						NavigationUtil.previousCharacter(selState,event.shiftKey); 
				}
				else
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.nextWord(selState,event.shiftKey);
					else
						NavigationUtil.nextCharacter(selState,event.shiftKey);
				}
			}
			return selState;
		}
		
		private function handleRightArrow(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			
		 	if(_textFlow.computedFormat.blockProgression  != BlockProgression.RL)
		 	{
		 		if(_textFlow.computedFormat.direction == Direction.LTR)
		 		{
			 		if (event.ctrlKey || event.altKey)
			 			NavigationUtil.nextWord(selState,event.shiftKey);
			 		else
			 			NavigationUtil.nextCharacter(selState,event.shiftKey);
			 	}
			 	else
			 	{
			 		if (event.ctrlKey || event.altKey)
						NavigationUtil.previousWord(selState,event.shiftKey);
					else
						NavigationUtil.previousCharacter(selState,event.shiftKey);
			 	}
		 	}
		 	else
		 	{
				// always test for altkey first - that way ctrl-alt is the same as alt
				if (event.altKey)
					NavigationUtil.startOfParagraph(selState,event.shiftKey);
				else if (event.ctrlKey)
					NavigationUtil.startOfDocument(selState,event.shiftKey);
				else
					NavigationUtil.previousLine(selState,event.shiftKey);
			}
			return selState;
		}
		
		private function handleDownArrow(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			
			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
			{
				// always test for altkey first - that way ctrl-alt is the same as alt
				if (event.altKey)
					NavigationUtil.endOfParagraph(selState,event.shiftKey);
				else if (event.ctrlKey)
					NavigationUtil.endOfDocument(selState,event.shiftKey);
				else
					NavigationUtil.nextLine(selState,event.shiftKey);
			}
			else
			{
				if(_textFlow.computedFormat.direction == Direction.LTR)
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.nextWord(selState,event.shiftKey);
					else
						NavigationUtil.nextCharacter(selState,event.shiftKey);
				}
				else
				{
					if (event.ctrlKey || event.altKey)
						NavigationUtil.previousWord(selState,event.shiftKey);
					else
						NavigationUtil.previousCharacter(selState,event.shiftKey); 
				}
			}

			return selState;
		}
		
		private function handleHomeKey(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			if (event.ctrlKey && !event.altKey)
				NavigationUtil.startOfDocument(selState,event.shiftKey);
			else
				NavigationUtil.startOfLine(selState,event.shiftKey);
			return selState;
		}
		
		private function handleEndKey(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			if (event.ctrlKey && !event.altKey)
				NavigationUtil.endOfDocument(selState,event.shiftKey);
			else
				NavigationUtil.endOfLine(selState,event.shiftKey);
			return selState;
		}
		
		private function handlePageUpKey(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			NavigationUtil.previousPage(selState,event.shiftKey);
			return selState;
		}

		private function handlePageDownKey(event:KeyboardEvent):SelectionState
		{
			var selState:SelectionState = getSelectionState();
			NavigationUtil.nextPage(selState,event.shiftKey);
			return selState;
		}		
						
		private function handleKeyEvent(event:KeyboardEvent):void
		{
			var selState:SelectionState = null;
			flushPendingOperations();			
			
			switch(event.keyCode)
			{
				case Keyboard.LEFT:
					selState = handleLeftArrow(event);
					break;
				case Keyboard.UP:
					selState = handleUpArrow(event);
					break;
				case Keyboard.RIGHT:
					selState = handleRightArrow(event);
					break;
				case Keyboard.DOWN:
					selState = handleDownArrow(event);
					break;
				case Keyboard.HOME:
					selState = handleHomeKey(event);
					break;
				case Keyboard.END:
					selState = handleEndKey(event);
					break;
				case Keyboard.PAGE_DOWN:
					selState = handlePageDownKey(event);
					break;
				case Keyboard.PAGE_UP:
					selState = handlePageUpKey(event);
					break;
			}

			if (selState != null)
			{
				event.preventDefault();
				updateSelectionAndShapes(_textFlow, selState.anchorPosition, selState.activePosition);

				// make sure the active end is visible in the container -- scroll if necessary
				if (_textFlow.flowComposer && _textFlow.flowComposer.numControllers != 0)
					 _textFlow.flowComposer.getControllerAt(_textFlow.flowComposer.numControllers-1).scrollToRange(selState.activePosition,selState.activePosition);
			}
			allowOperationMerge = false;
		}																										
			
		/** 
		 * @copy IInteractionEventHandler#keyDownHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */	
		public function keyDownHandler(event:KeyboardEvent):void
		{
			if (!hasSelection() || event.isDefaultPrevented())
				return;

			if (event.charCode == 0)
			{	
				// the keycodes that we currently handle
				switch(event.keyCode)
				{
					case Keyboard.LEFT:
					case Keyboard.UP:
					case Keyboard.RIGHT:
					case Keyboard.DOWN:
					case Keyboard.HOME:
					case Keyboard.END:
					case Keyboard.PAGE_DOWN:
					case Keyboard.PAGE_UP:
					case Keyboard.ESCAPE:
						handleKeyEvent(event);
						break;
				}
			}
			else if (event.keyCode == Keyboard.ESCAPE)
				handleKeyEvent(event);
		}

		/** 
		 * @copy IInteractionEventHandler#keyUpHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * 	@param	event	the keyUp event
		 */			
		public function keyUpHandler(event:KeyboardEvent):void
		{
			//do nothing here
		}
		
		/** 
		 * @copy IInteractionEventHandler#keyFocusChangeHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 * 	@param	event	the FocusChange event
		 */	
		public function keyFocusChangeHandler(event:FocusEvent):void
		{
			return;	// ignores manageTabKey if not editable
		}	
		
		/** 
		 * @copy IInteractionEventHandler#textInputHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/
		public function textInputHandler(event:TextEvent):void
		{
			// do nothing
			ignoreNextTextEvent = false;
		}

		/** 
		 * @copy IInteractionEventHandler#imeStartCompositionHandler()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		*/
		public function imeStartCompositionHandler(event:IMEEvent):void
		{
			// Do nothing -- this is handled in the EditManager if editing is supported
			// If there is no EditManager, doing nothing will refuse the IME session.
		}
		
		/**
		 *  @private
		 * 
		 *  Execute asynchronous operations at the beginning of a frame. This
		 *  event listener is called only if there is work that needs to be done.
		 */
		protected function enterFrameHandler(event:Event):void
		{
			flushPendingOperations();
		}

		/**
		 * @copy IInteractionEventHandler#focusChangeHandler()
		 */
		public function focusChangeHandler(event:FocusEvent):void
		{ }
		
		/**
		 * @copy IInteractionEventHandler#menuSelectHandler()
		 */
		public function menuSelectHandler(event:ContextMenuEvent):void
		{
			var menu:ContextMenu = event.target as ContextMenu;
			
			if (activePosition != anchorPosition)
			{
				menu.clipboardItems.copy = true;
				menu.clipboardItems.cut = editingMode == EditingMode.READ_WRITE;
				menu.clipboardItems.clear = editingMode == EditingMode.READ_WRITE;
			} else {
				menu.clipboardItems.copy = false;
				menu.clipboardItems.cut = false;
				menu.clipboardItems.clear = false;
			}
			
			var systemClipboard:Clipboard = Clipboard.generalClipboard;
			if (activePosition != -1 && editingMode == EditingMode.READ_WRITE && (systemClipboard.hasFormat(TextClipboard.TEXT_LAYOUT_MARKUP) || systemClipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)))
			{
				menu.clipboardItems.paste = true;
			} else {
				menu.clipboardItems.paste = false;
			}
			menu.clipboardItems.selectAll = true;		
		}
		
		/**
		 * @copy IInteractionEventHandler#mouseWheelHandler()
		 */
		public function mouseWheelHandler(event:MouseEvent):void
		{ }				
		/**
		 * @copy IInteractionEventHandler#flushPendingOperations()
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function flushPendingOperations():void
		{	}

		/**
		 * @copy ISelectionManager#getCommonCharacterFormat()
		 * 
		 * @includeExample examples\SelectionManager_getCommonCharacterFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function getCommonCharacterFormat(range:TextRange=null):ITextLayoutFormat
		{
			if (!range && !hasSelection())
				return null;
			
			var selRange:ElementRange = ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd);
			
			var leaf:FlowLeafElement = selRange.firstLeaf;
			var attr:TextLayoutFormat = new TextLayoutFormat(leaf.computedFormat);
	
			// include any attributes set on a point selection but not yet applied	and return	
			if (!isRangeSelection())
			{
				if (pointFormat)
					attr.apply(pointFormat)
			}
			else
			{
				for (;;)
				{
					if (leaf == selRange.lastLeaf)
						break;
					leaf = leaf.getNextLeaf();
					attr.removeClashing(leaf.computedFormat);
				}
			}
			
			return Property.extractInCategory(TextLayoutFormat, TextLayoutFormat.description, attr, Category.CHARACTER) as ITextLayoutFormat;
		}
		
		 
		 /**
		 * @copy ISelectionManager#getCommonParagraphFormat()
		 * 
		 * @includeExample examples\SelectionManager_getCommonParagraphFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function getCommonParagraphFormat (range:TextRange=null):ITextLayoutFormat
		{
			if (!range && !hasSelection())
				return null;
			
			var selRange:ElementRange = ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd);
			
			var para:ParagraphElement = selRange.firstParagraph;
			var attr:TextLayoutFormat = new TextLayoutFormat(para.computedFormat);
			for (;;)
			{
				if (para == selRange.lastParagraph)
					break;
				para = _textFlow.findAbsoluteParagraph(para.getAbsoluteStart()+para.textLength);
				attr.removeClashing(para.computedFormat);
			}
			return Property.extractInCategory(TextLayoutFormat,TextLayoutFormat.description,attr,Category.PARAGRAPH) as ITextLayoutFormat;
		 }
		 
		/**
		 * @copy ISelectionManager#getCommonContainerFormat()
		 * 
		 * @includeExample examples\SelectionManager_getCommonContainerFormat.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function getCommonContainerFormat (range:TextRange=null):ITextLayoutFormat
		{
			if (!range && !hasSelection())
				return null;
			
			// TODO: FIX THIS - tlf_core supports mulutiple containers
		 	// container attributes changes through the UI apply to TextFlow and all containers 
		 	// as of changelist# 625596, so all attributes values are 'common'.
		 	// note: that's true of your UI but that's no guarantee of common - the API supports users doing direct modifications outside the UI
		 	// need to revisit this when there are linked controllers
		 	CONFIG::debug { assert(textFlow.flowComposer.numControllers  == 1,"multiple containers not supported by SelectionManager.getCommonContainerFormat"); }
		 	return Property.extractInCategory(TextLayoutFormat,TextLayoutFormat.description,textFlow.flowComposer.getControllerAt(0).computedFormat,Category.CONTAINER) as ITextLayoutFormat;
		}
		 
		/**
		 * Refreshes and displays TextFlow selection defined by a beginning and ending index.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		private function updateSelectionAndShapes(tf:TextFlow, begIdx:int, endIdx:int):void
		{
			internalSetSelection(tf, begIdx, endIdx);
			if (_textFlow.flowComposer && _textFlow.flowComposer.numControllers != 0)
				_textFlow.flowComposer.getControllerAt(_textFlow.flowComposer.numControllers-1).scrollToRange(activeMark.position,anchorMark.position);
				
			selectionChanged();
			clearSelectionShapes();
			addSelectionShapes();
		}
		
		/** @private */
		CONFIG::debug tlf_internal function debugCheckTextFlow():int
		{
			if (flashx.textLayout.debug.Debugging.debugOn)
				return _textFlow.debugCheckTextFlow();
			return 0;
		}
		
		private var marks:Array = [];
		
		/** @private */
		tlf_internal function createMark():Mark
		{
			var mark:Mark = new Mark(-1);
			marks.push(mark);
			return mark;
		}
		/** @private */
		tlf_internal function removeMark(mark:Mark):void
		{
			var idx:int = marks.indexOf(mark);
			if (idx != -1)
				marks.splice(idx,idx+1);
		}
		
		/** 
		 * @copy ISelectionManager#notifyInsertOrDelete()
		 * 
		 * @includeExample examples\SelectionManager_notifyInsertOrDelete.as -noswf
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
 	 	 * @langversion 3.0
		 */
		public function notifyInsertOrDelete(absolutePosition:int, length:int):void
		{
			if (length == 0)
				return;
			for (var i:int = 0; i < marks.length; i++)
			{
				var mark:Mark = marks[i];
				if (mark.position >= absolutePosition)
				{
					if (length < 0)
						mark.position = (mark.position + length < absolutePosition) ? absolutePosition : mark.position + length;
					else
						mark.position += length;
				}
			}
		}
	}
}
