////////////////////////////////////////////////////////////////////////////////
//
//  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.IFlowComposer;
    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 the Text Layout Framework (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();
                
                // If we switch into read-only mode, make sure the cursor isn't showing a text selection IBeam
                if (!value) // see Watson 2637162
                    setMouseCursor(MouseCursor.AUTO);
        
                _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
                        
            // make sure we aren't selecting after the flow terminating character
            endIdx = Math.min(endIdx, _textFlow.textLength - 1);
            
            if (!extendSelection)
                begIdx = endIdx;                            

            if (begIdx == 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 (!_textFlow)
                 return;
             
            //  trace("setFocus sm", id);

            // container with the activePosition gets the key focus
            if (_textFlow.flowComposer)
                _textFlow.flowComposer.setFocus(activePosition,false);
            setSelectionFormatState(SelectionFormatState.FOCUSED);
         }
         
        /** 
         * Set the Mouse cursor. 
         * @param cursor    New cursor value, MouseCursor.AUTO if mouse is going off text, MouseCursor.IBEAM if mouse is going into text
         * 
         * @playerversion Flash 10.2
         * @playerversion AIR 2.0
         * @langversion 3.0
         */
        protected function setMouseCursor(cursor:String):void
        {
            Mouse.cursor = cursor;
        }
        
        /**
         *  @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;
            }
            
            var lastSelectablePos:int = (_textFlow.textLength > 0) ? _textFlow.textLength - 1 : 0;
            
            if (anchorPosition != -1 && activePosition != -1)
            {
                if (anchorPosition > lastSelectablePos)
                    anchorPosition = lastSelectablePos;
                
                if (activePosition > lastSelectablePos)
                    activePosition = lastSelectablePos;
            }

            _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
        {
            if (_textFlow.flowComposer)
            {
                // selection may need to be constrainted due to model changes that weren't done with the EditManager
                internalSetSelection(_textFlow,anchorMark.position,activeMark.position,_pointFormat);
                
                // 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
        {
            var flowComposer:IFlowComposer = _textFlow ? _textFlow.flowComposer : null; 
            if (flowComposer)
            {
                var containerIter:int = 0;
                while(containerIter < flowComposer.numControllers)
                {
                    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
                var lastPosition:int = _textFlow.textLength > 0 ? _textFlow.textLength - 1 : 0;
                rslt += assert(anchorMark.position >= 0 && anchorMark.position <= lastPosition,"SelectionManager:validate selBegIdx is out of range");
                rslt += assert(activeMark.position >= 0 && activeMark.position <= lastPosition,"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)
                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 textFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(lineIndex);
            var textLine:TextLine = textFlowLine.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 startOnNextLineIfNecessary:Boolean = false;
            
            var lastAtom:int = -1;
            if (isDirectionRTL) {
                lastAtom = textLine.atomCount - 1;
            } else {
                if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.getAbsoluteStart() + textFlowLine.paragraph.textLength) {
                    if (textLine.atomCount > 1) lastAtom = 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) lastAtom = textLine.atomCount - 2;
                    } else {
                        startOnNextLineIfNecessary = true;
                        if (textLine.atomCount > 0) lastAtom = textLine.atomCount - 1;
                    }
                }
            }
            var lastAtomRect:Rectangle = (lastAtom > 0) ? textLine.getAtomBounds(lastAtom) : new Rectangle(0, 0, 0, 0);
                        
            if (!isTTB)
            {
                if (localX < 0)
                    localX = 0;
                else if (localX > (lastAtomRect.x + lastAtomRect.width))
                {
                    if (startOnNextLineIfNecessary) 
                        return textFlowLine.absoluteStart + textFlowLine.textLength - 1;
                    if (lastAtomRect.x + lastAtomRect.width > 0)
                        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 - 1;    
                    if (lastAtomRect.y + lastAtomRect.height > 0)
                        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 (textLine.parent)
                    pt = textLine.parent.globalToLocal(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.getTotalPaddingLeft()+bounds.width : curContainerController.compositionWidth;
                        var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.getTotalPaddingTop()+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) 
                setMouseCursor(MouseCursor.IBEAM);          
            if (event.buttonDown)
                handleMouseEventForSelection(event, true);
        }
        
        /** @private */
        tlf_internal 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))
            {
                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)
            {
                setMouseCursor(MouseCursor.AUTO);
            }
        }
        
        private function atBeginningWordPos(activePara:ParagraphElement, pos:int):Boolean
        {
            if (pos == 0) return true;
			
			// mjzhang : for fix bug 2835316, will force to compose to paragraph end to avoid invalid textLine
			var paraEnd:Number = activePara.getAbsoluteStart() + activePara.textLength;
			activePara.getTextFlow().flowComposer.composeToPosition(paraEnd);
			
            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) 
                setMouseCursor(MouseCursor.IBEAM);  
            else 
                setMouseCursor(MouseCursor.AUTO);                               
        }

        /** 
         * @copy IInteractionEventHandler#mouseOutHandler()
         * 
         * @playerversion Flash 10
         * @playerversion AIR 1.5
         * @langversion 3.0
         */                 
        public function mouseOutHandler(event:MouseEvent):void
        {
            _mouseOverSelectionArea = false;            
            setMouseCursor(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.
        }
        
        /** 
         * @copy IInteractionEventHandler#softKeyboardActivatingHandler()
         * 
         * @playerversion Flash 10.2
         * @playerversion AIR 1.5
         * @langversion 3.0
         */
        public function softKeyboardActivatingHandler(event:Event):void
        {
            // Do nothing -- this is handled in the EditManager if editing is supported
        }
        
        /**
         *  @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):TextLayoutFormat
        {
            if (!range && !hasSelection())
                return null;
            
            var selRange:ElementRange = ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd);
            var rslt:TextLayoutFormat = selRange.getCommonCharacterFormat();
                
            // include any attributes set on a point selection but not yet applied  
            if (selRange.absoluteEnd == selRange.absoluteStart && pointFormat)
                rslt.apply(pointFormat)
    
            return rslt;
        }
        
         
         /**
         * @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):TextLayoutFormat
        {
            if (!range && !hasSelection())
                return null;
            
            return ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd).getCommonParagraphFormat();
         }
         
        /**
         * @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):TextLayoutFormat
        {
            if (!range && !hasSelection())
                return null;
            
            return ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd).getCommonContainerFormat();
        }
         
        /**
         * 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;
                }
            }
        }
    }
}
