TextSelection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / TextSelection.cs / 1305600 / TextSelection.cs

                            //---------------------------------------------------------------------------- 
//
// File: TextSelection.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: Holds and manipulates the text selection state for TextEditor. 
// 
//---------------------------------------------------------------------------
 
namespace System.Windows.Documents
{
    using MS.Internal;
    using System.Collections.Generic; 
    using System.Globalization;
    using System.Windows.Controls.Primitives;  // TextBoxBase 
    using System.Windows.Input; 
    using System.Windows.Media;
    using System.Windows.Threading; 
    using System.Threading;
    using System.Security;
    using System.Security.Permissions;
    using System.IO; 
    using System.Xml;
    using MS.Win32; 
    using System.Windows.Controls; 

    ///  
    /// The TextSelection class encapsulates selection state for the RichTextBox
    /// control.  It has no public constructor, but is exposed via a public
    /// property on RichTextBox.
    ///  
    public sealed class TextSelection : TextRange, ITextSelection
    { 
        #region Constructors 

        //----------------------------------------------------- 
        //
        //  Constructors
        //
        //----------------------------------------------------- 

        // Contstructor. 
        // TextSelection does not have a public constructor.  It is only accessible 
        // through TextEditor's Selection property.
        internal TextSelection(TextEditor textEditor) 
            : base(textEditor.TextContainer.Start, textEditor.TextContainer.Start)
        {
            ITextSelection thisSelection = (ITextSelection)this;
 
            Invariant.Assert(textEditor.UiScope != null);
 
            // Attach the selection to its editor 
            _textEditor = textEditor;
 
            // Initialize active pointers of the selection - anchor and moving pointers
            SetActivePositions(/*AnchorPosition:*/thisSelection.Start, thisSelection.End);

            // Activate selection in case if this control has keyboard focus already 
            thisSelection.UpdateCaretAndHighlight();
        } 
 
        #endregion Constructors
 
        // ******************************************************
        // *****************************************************
        // ******************************************************
        // 
        // Abstract TextSelection Implementation
        // 
        // ****************************************************** 
        // *****************************************************
        // ****************************************************** 

        //-----------------------------------------------------
        //
        // ITextRange implementation 
        //
        //----------------------------------------------------- 
 
        #region ITextRange Implementation
 
        //......................................................
        //
        // Selection Building
        // 
        //......................................................
 
        ///  
        /// 
        ///  
        void ITextRange.Select(ITextPointer anchorPosition, ITextPointer movingPosition)
        {
            TextRangeBase.BeginChange(this);
            try 
            {
                TextRangeBase.Select(this, anchorPosition, movingPosition); 
                SetActivePositions(anchorPosition, movingPosition); 
            }
            finally 
            {
                TextRangeBase.EndChange(this);
            }
        } 

        ///  
        ///  
        /// 
        void ITextRange.SelectWord(ITextPointer position) 
        {
            TextRangeBase.BeginChange(this);
            try
            { 
                TextRangeBase.SelectWord(this, position);
 
                ITextSelection thisSelection = this; 
                SetActivePositions(/*anchorPosition:*/thisSelection.Start, thisSelection.End);
            } 
            finally
            {
                TextRangeBase.EndChange(this);
            } 
        }
 
        ///  
        /// 
        ///  
        void ITextRange.SelectParagraph(ITextPointer position)
        {
            TextRangeBase.BeginChange(this);
            try 
            {
                TextRangeBase.SelectParagraph(this, position); 
 
                //
                ITextSelection thisSelection = this; 
                SetActivePositions(/*anchorPosition:*/position, thisSelection.End);
            }
            finally
            { 
                TextRangeBase.EndChange(this);
            } 
        } 

        ///  
        /// 
        /// 
        void ITextRange.ApplyTypingHeuristics(bool overType)
        { 
            TextRangeBase.BeginChange(this);
            try 
            { 
                TextRangeBase.ApplyInitialTypingHeuristics(this);
 
                // For non-empty selection start with saving current formatting
                if (!this.IsEmpty && _textEditor.AcceptsRichContent)
                {
                    SpringloadCurrentFormatting(); 
                    // Note: we springload formatting before overtype expansion
                } 
 
                TextRangeBase.ApplyFinalTypingHeuristics(this, overType);
            } 
            finally
            {
                TextRangeBase.EndChange(this);
            } 
        }
 
        ///  
        /// 
        ///  
        object ITextRange.GetPropertyValue(DependencyProperty formattingProperty)
        {
            object propertyValue;
 
            if (this.IsEmpty && TextSchema.IsCharacterProperty(formattingProperty))
            { 
                // For empty selection return springloaded formatting (only character formatting properties can be springloaded) 
                propertyValue = ((TextSelection)this).GetCurrentValue(formattingProperty);
            } 
            else
            {
                // Otherwise return base implementation from a TextRange.
                propertyValue = TextRangeBase.GetPropertyValue(this, formattingProperty); 
            }
 
            return propertyValue; 
        }
 
        //......................................................
        //
        // Plain Text Modification
        // 
        //......................................................
 
        //----------------------------------------------------- 
        //
        //  Overrides 
        //
        //------------------------------------------------------

        // Set true if a Changed event is pending. 
        bool ITextRange._IsChanged
        { 
            get 
            {
                return _IsChanged; 
            }

            set
            { 
                // TextStore needs to know about state changes
                // from false to true. 
                if (!_IsChanged && value) 
                {
                    if (this.TextStore != null) 
                    {
                        this.TextStore.OnSelectionChange();
                    }
                    if (this.ImmComposition != null) 
                    {
                        this.ImmComposition.OnSelectionChange(); 
                    } 
                }
 
                _IsChanged = value;
            }
        }
 
        /// 
        ///  
        void ITextRange.NotifyChanged(bool disableScroll, bool skipEvents) 
        {
            // Notify text store about selection movement. 
            if (this.TextStore != null)
            {
                this.TextStore.OnSelectionChanged();
            } 
            // Notify ImmComposition about selection movement.
            if (this.ImmComposition != null) 
            { 
                this.ImmComposition.OnSelectionChanged();
            } 

            if (!skipEvents)
            {
                TextRangeBase.NotifyChanged(this, disableScroll); 
            }
 
            if (!disableScroll) 
            {
                // Force a synchronous layout update.  If the update was big enough, background layout 
                // kicked in and the caret won't otherwise be updated.  Note this will block the thread
                // while layout runs.
                //
                // It's possible an application repositioned the caret 
                // while listening to a change event just raised, but in that case the following
                // code should be harmless. 
                ITextPointer movingPosition = ((ITextSelection)this).MovingPosition; 
                if (this.TextView != null && this.TextView.IsValid &&
                    !this.TextView.Contains(movingPosition)) 
                {
                    movingPosition.ValidateLayout();
                }
                // If layout wasn't valid, then there's a pending caret update 
                // that will proceed correctly now.  Otherwise the whole operation
                // is a nop. 
            } 

            // Fixup the caret. 
            UpdateCaretState(disableScroll ? CaretScrollMethod.None : CaretScrollMethod.Simple);
        }

        //----------------------------------------------------- 
        //
        //  ITextRange Properties 
        // 
        //------------------------------------------------------
 
        //......................................................
        //
        //  Content - rich and plain
        // 
        //......................................................
 
        ///  
        /// 
        ///  
        string ITextRange.Text
        {
            get
            { 
                return TextRangeBase.GetText(this);
            } 
 
            set
            { 
                TextRangeBase.BeginChange(this);
                try
                {
                    TextRangeBase.SetText(this, value); 

                    if (this.IsEmpty) 
                    { 
                        // We need to ensure appropriate caret visual position.
                        ((ITextSelection)this).SetCaretToPosition(((ITextRange)this).End, LogicalDirection.Forward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/false); 
                    }

                    Invariant.Assert(!this.IsTableCellRange);
                    SetActivePositions(((ITextRange)this).Start, ((ITextRange)this).End); 
                }
                finally 
                { 
                    TextRangeBase.EndChange(this);
                } 
            }
        }

        #endregion ITextRange Implementation 

        //------------------------------------------------------ 
        // 
        // ITextSelection implementation
        // 
        //-----------------------------------------------------

        #region ITextSelection Implementation
 
        void ITextSelection.UpdateCaretAndHighlight()
        { 
            if (this.UiScope.IsEnabled && this.TextView != null && this.UiScope.IsKeyboardFocused) 
            {
                // Update the TLS first, so that EnsureCaret is working in 
                // the correct context.
                SetThreadSelection();

                // Make caret visible and blinking 
                EnsureCaret(/*isBlinkEnabled:*/true, CaretScrollMethod.None);
                // Highlight selection 
                Highlight(); 
            }
            else if (this.UiScope.IsEnabled && this.TextView != null && 
             this.UiScope.IsFocused && IsRootElement(FocusManager.GetFocusScope(this.UiScope)) &&
             (IsFocusWithinRoot() ||                   // either UiScope root window has keyboard focus
             _textEditor.IsContextMenuOpen))          // or UiScope has a context menu open
            { 
                // Update the TLS first, so that EnsureCaret is working in
                // the correct context. 
                SetThreadSelection(); 

                // just stop the caret from blinking 
                EnsureCaret(/*isBlinkEnabled:*/false, CaretScrollMethod.None);
                // Highlight selection
                Highlight();
            } 
            else
            { 
                // Update the TLS first, so that the caret is working in 
                // the correct context.
                ClearThreadSelection(); 

                // delete the caret
                DetachCaretFromVisualTree();
                // Remove highlight 
                Unhighlight();
            } 
        } 

        ///  
        /// 
        ITextPointer ITextSelection.AnchorPosition
        {
            get 
            {
                Invariant.Assert(this.IsEmpty || _anchorPosition != null); 
                Invariant.Assert(_anchorPosition == null || _anchorPosition.IsFrozen); 
                return this.IsEmpty ? ((ITextSelection)this).Start : _anchorPosition;
            } 
        }

        /// 
        /// The position within this selection that responds to user input. 
        /// 
        ITextPointer ITextSelection.MovingPosition 
        { 
            get
            { 
                ITextSelection thisSelection = this;
                ITextPointer movingPosition;

                if (this.IsEmpty) 
                {
                    movingPosition = thisSelection.Start; 
                } 
                else
                { 
                    switch (_movingPositionEdge)
                    {
                        case MovingEdge.Start:
                            movingPosition = thisSelection.Start; 
                            break;
 
                        case MovingEdge.StartInner: 
                            movingPosition = thisSelection.TextSegments[0].End;
                            break; 

                        case MovingEdge.EndInner:
                            movingPosition = thisSelection.TextSegments[thisSelection.TextSegments.Count - 1].Start;
                            break; 

                        case MovingEdge.End: 
                            movingPosition = thisSelection.End; 
                            break;
 
                        case MovingEdge.None:
                        default:
                            Invariant.Assert(false, "MovingEdge should never be None with non-empty TextSelection!");
                            movingPosition = null; 
                            break;
                    } 
 
                    movingPosition = movingPosition.GetFrozenPointer(_movingPositionDirection);
                } 

                return movingPosition;
            }
        } 

        ///  
        ///  
        void ITextSelection.SetCaretToPosition(ITextPointer caretPosition, LogicalDirection direction, bool allowStopAtLineEnd, bool allowStopNearSpace)
        { 
            // We need a pointer with appropriate direction,
            // becasue it will be used in textRangeBase.Select method for
            // pointer normalization.
            caretPosition = caretPosition.CreatePointer(direction); 

            // Normalize the position in its logical direction - to get to text content over there. 
            caretPosition.MoveToInsertionPosition(direction); 

            // We need a pointer with the reverse direction to confirm 
            // the line wrapping position. So we can ensure Bidi caret navigation.
            // Bidi can have the different caret position by setting the
            // logical direction, so we have to only set the logical direction
            // as the forward for the real line wrapping position. 
            ITextPointer reversePosition = caretPosition.CreatePointer(direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward);
 
            // Check line wrapping condition 
            if (!allowStopAtLineEnd &&
                ((TextPointerBase.IsAtLineWrappingPosition(caretPosition, this.TextView) && 
                  TextPointerBase.IsAtLineWrappingPosition(reversePosition, this.TextView)) ||
                 TextPointerBase.IsNextToPlainLineBreak(caretPosition, LogicalDirection.Backward) ||
                 TextSchema.IsBreak(caretPosition.GetElementType(LogicalDirection.Backward))))
            { 
                // Caret is at wrapping position, and we are not allowed to stay at end of line,
                // so we choose forward direction to appear in the begiinning of a second line 
                caretPosition.SetLogicalDirection(LogicalDirection.Forward); 
            }
            else 
            {
                if (caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text &&
                    caretPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                { 
                    // This is statistically most typical case. No "smartness" needed
                    // to choose standard Forward orientation for the caret. 
                    // NOTE: By using caretPosition's direction we solve BiDi caret orientation case: 
                    // The orietnation reflects a direction from where caret has been moved
                    // or orientation where mouse clicked. So we will stick with appropriate 
                    // character.

                    // Nothing to do. The caretPosition is good to go.
                } 
                else if (!allowStopNearSpace)
                { 
                    // There are some tags around, and we are not allowed to choose a side near to space. 
                    // So we need to perform some content analysis.
 
                    char[] charBuffer = new char[1];

                    if (caretPosition.GetPointerContext(direction) == TextPointerContext.Text &&
                        caretPosition.GetTextInRun(direction, charBuffer, 0, 1) == 1 && 
                        Char.IsWhiteSpace(charBuffer[0]))
                    { 
                        LogicalDirection oppositeDirection = direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward; 

                        // Check formatting switch condition at this position 
                        FlowDirection initialFlowDirection = (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty);

                        bool moved = caretPosition.MoveToInsertionPosition(oppositeDirection);
 
                        if (moved &&
                            initialFlowDirection == (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty) && 
                            (caretPosition.GetPointerContext(oppositeDirection) != TextPointerContext.Text || 
                             caretPosition.GetTextInRun(oppositeDirection, charBuffer, 0, 1) != 1 ||
                             !Char.IsWhiteSpace(charBuffer[0]))) 
                        {
                            // In the opposite direction we have a non-space
                            // character. So we choose that direction
                            direction = oppositeDirection; 
                            caretPosition.SetLogicalDirection(direction);
                        } 
                    } 
                }
            } 

            // Now that orientation of a caretPosition is identified,
            // build an empty selection at this position
            TextRangeBase.BeginChange(this); 
            try
            { 
                TextRangeBase.Select(this, caretPosition, caretPosition); 

                // Note how Select method works for the case of empty range: 
                // It creates a single instance TextPointer normalized and oriented
                // in a direction taken from caretPosition:
                ITextSelection thisSelection = this;
                Invariant.Assert(thisSelection.Start.LogicalDirection == caretPosition.LogicalDirection); // orientation must be as passed 
                Invariant.Assert(this.IsEmpty);
                //Invariant.Assert((object)thisSelection.Start == (object)thisSelection.End); // it must be the same instance of TextPointer 
                //Invariant.Assert(TextPointerBase.IsAtInsertionPosition(thisSelection.Start, caretPosition.LogicalDirection)); // normalization must be done in the same diredction as orientation 

                // Clear active positions when selection is empty 
                SetActivePositions(null, null);
            }
            finally
            { 
                TextRangeBase.EndChange(this);
            } 
        } 

        //...................................................... 
        //
        //  Extending via movingEnd movements
        //
        //...................................................... 

        // Worker for ExtendToPosition, handles all ITextContainers. 
        void ITextSelection.ExtendToPosition(ITextPointer position) 
        {
            TextRangeBase.BeginChange(this); 
            try
            {
                ITextSelection thisSelection = (ITextSelection)this;
 
                // Store initial anchor position
                ITextPointer anchorPosition = thisSelection.AnchorPosition; 
 
                //Build new selection
                TextRangeBase.Select(thisSelection, anchorPosition, position); 

                // Store active positions.
                SetActivePositions(anchorPosition, position);
            } 
            finally
            { 
                TextRangeBase.EndChange(this); 
            }
        } 

        // Worker for ExtendToNextInsertionPosition, handles all ITextContainers.
        bool ITextSelection.ExtendToNextInsertionPosition(LogicalDirection direction)
        { 
            bool moved = false;
 
            TextRangeBase.BeginChange(this); 
            try
            { 
                ITextPointer anchorPosition = ((ITextSelection)this).AnchorPosition;
                ITextPointer movingPosition = ((ITextSelection)this).MovingPosition;
                ITextPointer newMovingPosition;
 
                if (this.IsTableCellRange)
                { 
                    // Both moving and anchor positions are within a single Table, in seperate 
                    // cells.  Select next cell.
                    newMovingPosition = TextRangeEditTables.GetNextTableCellRangeInsertionPosition(this, direction); 
                }
                else if (movingPosition is TextPointer && TextPointerBase.IsAtRowEnd(movingPosition))
                {
                    // Moving position at at a Table row end, anchor position is outside 
                    // the Table.  Select next row.
                    newMovingPosition = TextRangeEditTables.GetNextRowEndMovingPosition(this, direction); 
                } 
                else if (movingPosition is TextPointer && TextRangeEditTables.MovingPositionCrossesCellBoundary(this))
                { 
                    // Moving position at at a Table row start, anchor position is outside
                    // the Table.  Select next row.
                    newMovingPosition = TextRangeEditTables.GetNextRowStartMovingPosition(this, direction);
                } 
                else
                { 
                    // No Table logic. 
                    newMovingPosition = GetNextTextSegmentInsertionPosition(direction);
                } 

                if (newMovingPosition == null && direction == LogicalDirection.Forward)
                {
                    // When moving forward we cannot find next insertion position, set the end of selection after the last paragraph 
                    // (which is not an insertion position)
                    if (movingPosition.CompareTo(movingPosition.TextContainer.End) != 0) 
                    { 
                        newMovingPosition = movingPosition.TextContainer.End;
                    } 
                }

                // Now that new movingPosition is prepared, build the new selection
                if (newMovingPosition != null) 
                {
                    moved = true; 
 
                    // Re-build a range for the new pair of positions
                    TextRangeBase.Select(this, anchorPosition, newMovingPosition); 

                    // Make sure that active positions are inside of a selection
                    // Set the moving position direction to point toward the inner content.
                    LogicalDirection contentDirection = (anchorPosition.CompareTo(newMovingPosition) <= 0) ? 
                                                 LogicalDirection.Backward : LogicalDirection.Forward;
                    newMovingPosition = newMovingPosition.GetFrozenPointer(contentDirection); 
 
                    SetActivePositions(anchorPosition, newMovingPosition);
                } 
            }
            finally
            {
                TextRangeBase.EndChange(this); 
            }
 
            return moved; 
        }
 
        // Finds new movingPosition for the selection when it is in TextSegment state.
        // Returns null if there is no next insertion position in the requested direction.
        private ITextPointer GetNextTextSegmentInsertionPosition(LogicalDirection direction)
        { 
            ITextSelection thisSelection = (ITextSelection)this;
 
            // Move one over symbol in a given direction 
            return thisSelection.MovingPosition.GetNextInsertionPosition(direction);
        } 

        bool ITextSelection.Contains(Point point)
        {
            ITextSelection thisSelection = (ITextSelection)this; 

            if (thisSelection.IsEmpty) 
            { 
                return false;
            } 

            if (this.TextView == null || !this.TextView.IsValid)
            {
                return false; 
            }
 
            bool contains = false; 

            ITextPointer position = this.TextView.GetTextPositionFromPoint(point, /*snapToText:*/false); 

            // Did we hit any text?
            if (position != null && thisSelection.Contains(position))
            { 
                // If we did, make sure the range covers at least one full character.
                // Check both character edges. 
 
                position = position.GetNextInsertionPosition(position.LogicalDirection);
 
                if (position != null && thisSelection.Contains(position))
                {
                    contains = true;
                } 
            }
 
            // Point snapped to text did not hit anything, but we still have a chance 
            // to hit selection - in inter-paragraph or end-of-paragraph areas - highlighted by selection
            if (!contains) 
            {
                if (_caretElement != null && _caretElement.SelectionGeometry != null &&
                    _caretElement.SelectionGeometry.FillContains(point))
                { 
                    contains = true;
                } 
            } 

            return contains; 
        }

        #region ITextSelection Implementation
 
        //......................................................
        // 
        //  Interaction with Selection host 
        //
        //...................................................... 


        // Called by TextEditor.OnDetach, when the behavior is shut down.
        void ITextSelection.OnDetach() 
        {
            ITextSelection thisSelection = (ITextSelection)this; 
 
            // Check if we need to deactivate the selection
            thisSelection.UpdateCaretAndHighlight(); 

            // Delete highlight layer created for this selection (if any)
            if (_highlightLayer != null && thisSelection.Start.TextContainer.Highlights.GetLayer(typeof(TextSelection)) == _highlightLayer)
            { 
                thisSelection.Start.TextContainer.Highlights.RemoveLayer(_highlightLayer);
            } 
            _highlightLayer = null; 

            // Detach the selection from its editor 
            _textEditor = null;
        }

        // ITextView.Updated event listener. 
        // Called by the TextEditor.
        void ITextSelection.OnTextViewUpdated() 
        { 
            if ((this.UiScope.IsKeyboardFocused || this.UiScope.IsFocused))
            { 
                // Use the locally defined caretElement because _caretElement can be null by
                // detaching CaretElement object
                // Stress bug#1583327 indicate that _caretElement can be set to null by
                // detaching. So the below code is caching the caret element instance locally. 
                CaretElement caretElement = _caretElement;
                if (caretElement != null) 
                { 
                    caretElement.OnTextViewUpdated();
                } 
            }

            if (_pendingUpdateCaretStateCallback)
            { 
                // The TextView calls this method synchronously, before it finishes its Arrange
                // pass, so defer the remaining work until the TextView is valid. 
                Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(UpdateCaretStateWorker), null); 
            }
        } 

        // Perform any cleanup necessary when removing the current UiScope
        // from the visual tree (eg, during a template change).
        void ITextSelection.DetachFromVisualTree() 
        {
            DetachCaretFromVisualTree(); 
        } 

        // Italic command event handler. Called by TextEditor. 
        void ITextSelection.RefreshCaret()
        {
            // Update the caret to show it as italic or normal caret.
            RefreshCaret(_textEditor, _textEditor.Selection); 
        }
 
        // This is called from TextStore when the InterimSelection style of the current selection is changed. 
        void ITextSelection.OnInterimSelectionChanged(bool interimSelection)
        { 
            // Update the caret to show or remove the interim block caret.
            UpdateCaretState(CaretScrollMethod.None);
        }
 
        //......................................................
        // 
        //  Selection Heuristics 
        //
        //...................................................... 


        // Moves the selection to the mouse cursor position.
        // Extends the active end if extend == true, otherwise the selection 
        // is collapsed to a caret.
        void ITextSelection.SetSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint) 
        { 
            ITextSelection thisSelection = (ITextSelection)this;
 
            if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
            {
                // Shift modifier pressed - extending selection from existing one
                thisSelection.ExtendSelectionByMouse(cursorPosition, /*forceWordSelection:*/false, /*forceParagraphSelection*/false); 
            }
            else 
            { 
                // No shift modifier pressed - move selection to a cursor position
                MoveSelectionByMouse(cursorPosition, cursorMousePoint); 
            }
        }

        // Extends the selection to the mouse cursor position. 
        void ITextSelection.ExtendSelectionByMouse(ITextPointer cursorPosition, bool forceWordSelection, bool forceParagraphSelection)
        { 
            ITextSelection thisSelection = (ITextSelection)this; 

            // Check whether the cursor has been actually moved - compare with the previous position 
            if (forceParagraphSelection || _previousCursorPosition != null && cursorPosition.CompareTo(_previousCursorPosition) == 0)
            {
                // Mouse was not actually moved. Ignore the event.
                return; 
            }
 
            thisSelection.BeginChange(); 
            try
            { 
                if (!BeginMouseSelectionProcess(cursorPosition))
                {
                    return;
                } 

                // Get anchor position 
                ITextPointer anchorPosition = ((ITextSelection)this).AnchorPosition; 

                // Identify words on selection ends 
                TextSegment anchorWordRange;
                TextSegment cursorWordRange;
                IdentifyWordsOnSelectionEnds(anchorPosition, cursorPosition, forceWordSelection, out anchorWordRange, out cursorWordRange);
 
                // Calculate selection boundary positions
                ITextPointer startPosition; 
                ITextPointer movingPosition; 
                if (anchorWordRange.Start.CompareTo(cursorWordRange.Start) <= 0)
                { 
                    startPosition = anchorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward);
                    movingPosition = cursorWordRange.End.GetFrozenPointer(LogicalDirection.Backward); ;
                }
                else 
                {
                    startPosition = anchorWordRange.End.GetFrozenPointer(LogicalDirection.Backward); 
                    movingPosition = cursorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward); ; 
                }
 
                // Note that we use includeCellAtMovingPosition=true because we want that hit-tested table cell
                // be included into selection no matter whether it's empty or not.
                TextRangeBase.Select(this, startPosition, movingPosition, /*includeCellAtMovingPosition:*/true);
                SetActivePositions(anchorPosition, movingPosition); 

                // Store previous cursor position - for the next extension event 
                _previousCursorPosition = cursorPosition.CreatePointer(); 

                Invariant.Assert(thisSelection.Contains(thisSelection.AnchorPosition)); 
            }
            finally
            {
                thisSelection.EndChange(); 
            }
        } 
 
        // Part of ExtendSelectionByMouse method:
        // Checks whether selection has been started and initiates selection process 
        // Usually always returns true,
        // returns false only as a special value indicating that we need to return without executing selection expansion code.
        private bool BeginMouseSelectionProcess(ITextPointer cursorPosition)
        { 
            if (_previousCursorPosition == null)
            { 
                // This is a beginning of mouse selection guesture. 
                // Initialize the guesture state
                // initially autoword expansion of both ends is enabled 
                _anchorWordRangeHasBeenCrossedOnce = false;
                _allowWordExpansionOnAnchorEnd = true;
                _reenterPosition = null;
 
                if (this.GetUIElementSelected() != null)
                { 
                    // This means that we have just received mousedown event and selected embedded element in this event. 
                    // MoveMove event is sent immediately, but we don't want to loose UIElement selection,
                    // so we do not extend to the cursorPosition now. 
                    _previousCursorPosition = cursorPosition.CreatePointer();
                    return false;
                }
            } 

            return true; 
        } 

        // Part of ExtendSelectionByMouse method: 
        // Identifies words on selection ends.
        private void IdentifyWordsOnSelectionEnds(ITextPointer anchorPosition, ITextPointer cursorPosition, bool forceWordSelection, out TextSegment anchorWordRange, out TextSegment cursorWordRange)
        {
            if (forceWordSelection) 
            {
                anchorWordRange = TextPointerBase.GetWordRange(anchorPosition); 
                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection); 
            }
            else 
            {
                // Define whether word adjustment is allowed. Pressing Shift+Control prevents from auto-word expansion.
                bool disableWordExpansion = _textEditor.AutoWordSelection == false || ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 && (Keyboard.Modifiers & ModifierKeys.Control) != 0);
 
                if (disableWordExpansion)
                { 
                    anchorWordRange = new TextSegment(anchorPosition, anchorPosition); 
                    cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                } 
                else
                {
                    // Autoword expansion heuristics
                    // ----------------------------- 

                    // Word autoword heuristics: 
                    // a) After active end returned to selected area, autoword expansion on active end is disabled 
                    // b) After active end returned to the very first word, expansion on anchor word is disabled either
                    //    We do this though only if selection has crossed initial word boundary at least once. 
                    // c) After active end crosses new word, autoword expansion of active end is enabled again

                    // Calculate a word range for anchor position
                    anchorWordRange = TextPointerBase.GetWordRange(anchorPosition); 

                    // Check if we re-entering selection or moving outside 
                    // and set autoexpansion flags accordingly 
                    if (_previousCursorPosition != null &&
                        (anchorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(_previousCursorPosition) < 0 || 
                        _previousCursorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(anchorPosition) < 0))
                    {
                        // Re-entering selection.
 
                        // Store position of reentering
                        _reenterPosition = cursorPosition.CreatePointer(); 
 
                        // When re-entering reaches initial word, disable word expansion on anchor end either
                        if (_anchorWordRangeHasBeenCrossedOnce && anchorWordRange.Contains(cursorPosition)) 
                        {
                            _allowWordExpansionOnAnchorEnd = false;
                        }
                    } 
                    else
                    { 
                        // Extending the selection. 

                        // Check if we are crossing a boundary of last reentered word to re-enable word expansion on moving end 
                        if (_reenterPosition != null)
                        {
                            TextSegment lastReenteredWordRange = TextPointerBase.GetWordRange(_reenterPosition);
                            if (!lastReenteredWordRange.Contains(cursorPosition)) 
                            {
                                _reenterPosition = null; 
                            } 
                        }
                    } 

                    // Identify expanded range on both ends
                    //
 
                    if (anchorWordRange.Contains(cursorPosition) ||
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Forward)) || 
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Backward))) 
                    {
                        // Selection does not cross word boundary, so shrink selection to exact anchor/cursor positions 
                        anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                    }
                    else 
                    {
                        // Selection crosses word boundary. 
                        _anchorWordRangeHasBeenCrossedOnce = true; 

                        if (!_allowWordExpansionOnAnchorEnd || // 
                            TextPointerBase.IsAtWordBoundary(anchorPosition, /*insideWordDirection:*/LogicalDirection.Forward))
                        {
                            // We collapse anchorPosition in two cases:
                            // If we have been re-entering the initial word before - 
                            // then we treat it as an indicator that user wants exact position on anchor end
                            // or 
                            // if selection starts exactly on word boundary - 
                            // then we should not include the following word (when selection extends backward).
                            // 
                            // So in the both cases we collapse anchorWordRange to exact _anchorPosition
                            anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        }
 
                        if (TextPointerBase.IsAfterLastParagraph(cursorPosition) ||
                            TextPointerBase.IsAtWordBoundary(cursorPosition, /*insideWordDirection:*/LogicalDirection.Forward)) 
                        { 
                            cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                        } 
                        else
                        {
                            if (_reenterPosition == null)
                            { 
                                // We are not in re-entering mode; expand moving end to word boundary
                                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection); 
                            } 
                            else
                            { 
                                // We are in re-entering mode; use exact moving end position
                                cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                            }
                        } 
                    }
                } 
            } 
        }
 
        //......................................................
        //
        //  Table Selection
        // 
        //......................................................
 
        ///  
        /// Extends table selection by one row in a given direction
        ///  
        /// 
        /// LogicalDirection.Forward means moving active cell one row down,
        /// LogicalDirection.Backward - one row up.
        ///  
        bool ITextSelection.ExtendToNextTableRow(LogicalDirection direction)
        { 
            TableCell anchorCell; 
            TableCell movingCell;
            TableRowGroup rowGroup; 
            int nextRowIndex;
            TableCell nextCell;

            if (!this.IsTableCellRange) 
            {
                return false; 
            } 

            Invariant.Assert(!this.IsEmpty); 
            Invariant.Assert(_anchorPosition != null);
            Invariant.Assert(_movingPositionEdge != MovingEdge.None);

            if (!TextRangeEditTables.IsTableCellRange((TextPointer)_anchorPosition, (TextPointer)((ITextSelection)this).MovingPosition, /*includeCellAtMovingPosition:*/false, out anchorCell, out movingCell)) 
            {
                return false; 
            } 

            Invariant.Assert(anchorCell != null && movingCell != null); 

            rowGroup = movingCell.Row.RowGroup;

            nextCell = null; 

            if (direction == LogicalDirection.Forward) 
            { 
                // Move movingPosition to the following row.
                // Find a row in the forward direction 
                nextRowIndex = movingCell.Row.Index + movingCell.RowSpan;
                if (nextRowIndex < rowGroup.Rows.Count)
                {
                    nextCell = FindCellAtColumnIndex(rowGroup.Rows[nextRowIndex].Cells, movingCell.ColumnIndex); 
                }
            } 
            else 
            {
                // Find preceding row containing a cell in position of movingCell's first column 
                nextRowIndex = movingCell.Row.Index - 1;
                while (nextRowIndex >= 0)
                {
                    nextCell = FindCellAtColumnIndex(rowGroup.Rows[nextRowIndex].Cells, movingCell.ColumnIndex); 
                    if (nextCell != null)
                    { 
                        break; 
                    }
                    nextRowIndex--; 
                }
            }

            if (nextCell != null) 
            {
                // 
                ITextPointer movingPosition = nextCell.ContentEnd.CreatePointer(); 
                movingPosition.MoveToNextInsertionPosition(LogicalDirection.Forward);
 
                TextRangeBase.Select(this, _anchorPosition, movingPosition);

                // Make sure that active positions are inside of a selection
                SetActivePositions(_anchorPosition, movingPosition); 

                return true; 
            } 

            return false; 
        }

        //------------------------------------------------------
        // 
        //  ITextSelection Properties
        // 
        //----------------------------------------------------- 

        // True if the current seleciton is for interim character. 
        // Korean Interim character is now invisilbe selection (no highlight) and the controls needs to
        // have the block caret to indicate the interim character.
        // This should be updated by TextStore.
        internal bool IsInterimSelection 
        {
            get 
            { 
                if (this.TextStore != null)
                { 
                    return TextStore.IsInterimSelection;
                }

                return false; 
            }
        } 
 
        // IsInterimSelection wrapper for ITextSelection.
        bool ITextSelection.IsInterimSelection 
        {
            get
            {
                return this.IsInterimSelection; 
            }
        } 
 
        #endregion ITextSelection Implementation
 

        // *****************************************************
        // *****************************************************
        // ****************************************************** 
        //
        // Concrete TextSelection Implementation 
        // 
        // *****************************************************
        // ****************************************************** 
        // ******************************************************


        //----------------------------------------------------- 
        //
        //  Public Methods 
        // 
        //------------------------------------------------------
 
        //......................................................
        //
        //  Selection extension (moving active end)
        // 
        //......................................................
 
        ///  
        /// Potential public method - concrete equivalent of abstract method
        ///  
        internal TextPointer AnchorPosition
        {
            get
            { 
                // ATTENTION: This method is supposed to be a pure redirection
                // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent 
                return (TextPointer)((ITextSelection)this).AnchorPosition; 
            }
        } 

        /// 
        /// Potential public method - concrete equivalent of abstract method
        ///  
        internal TextPointer MovingPosition
        { 
            get 
            {
                // ATTENTION: This method is supposed to be a pure redirection 
                // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
                return (TextPointer)((ITextSelection)this).MovingPosition;
            }
        } 

        ///  
        /// Potential public method - concrete equivalent of abstract method 
        /// 
        internal void SetCaretToPosition(TextPointer caretPosition, LogicalDirection direction, bool allowStopAtLineEnd, bool allowStopNearSpace) 
        {
            // ATTENTION: This method is supposed to be a pure redirection
            // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
            ((ITextSelection)this).SetCaretToPosition(caretPosition, direction, allowStopAtLineEnd, allowStopNearSpace); 
        }
 
        // 
        internal bool ExtendToNextInsertionPosition(LogicalDirection direction)
        { 
            // ATTENTION: This method is supposed to be a pure redirection
            // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
            return ((ITextSelection)this).ExtendToNextInsertionPosition(direction);
        } 

        #endregion Public Methods 
 
        #region Internal Methods
 
        //-----------------------------------------------------
        //
        //  Internal Methods
        // 
        //-----------------------------------------------------
 
        // InputLanguageChanged event handler. Called by TextEditor. 
        internal static void OnInputLanguageChanged(CultureInfo cultureInfo)
        { 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;

            // Check the changed input language of the cultureInfo to draw the BiDi caret in case of BiDi language
            // like as Arabic or Hebrew input language. 
            if (IsBidiInputLanguage(cultureInfo))
            { 
                threadLocalStore.Bidi = true; 
            }
            else 
            {
                threadLocalStore.Bidi = false;
            }
 
            // Update caret on focused text editor
            if (threadLocalStore.FocusedTextSelection != null) 
            { 
                ((ITextSelection)threadLocalStore.FocusedTextSelection).RefreshCaret();
            } 
        }

        // Returns true if the text matching a pixel position falls within
        // the selection. 
        internal bool Contains(Point point)
        { 
            return ((ITextSelection)this).Contains(point); 
        }
 
        //-----------------------------------------------------
        //
        // Internal Virtual Methods - TextSelection Extensibility
        // 
        //------------------------------------------------------
 
        //...................................................... 
        //
        //  Formatting 
        //
        //......................................................

        ///  
        ///  Append an object at the end of the TextRange.
        ///  
        internal override void InsertEmbeddedUIElementVirtual(FrameworkElement embeddedElement) 
        {
            TextRangeBase.BeginChange(this); 
            try
            {
                base.InsertEmbeddedUIElementVirtual(embeddedElement);
 
                this.ClearSpringloadFormatting();
            } 
            finally 
            {
                TextRangeBase.EndChange(this); 
            }
        }

        ///  
        /// Applies a property value to a selection.
        /// In case of empty selection sets property to springloaded property set. 
        ///  
        internal override void ApplyPropertyToTextVirtual(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction)
        { 
            if (!TextSchema.IsParagraphProperty(formattingProperty) && !TextSchema.IsCharacterProperty(formattingProperty))
            {
                return; // Ignore any unknown property
            } 

            // Check whether we are in a situation when auto-word formatting must happen 
            if (this.IsEmpty && TextSchema.IsCharacterProperty(formattingProperty) && 
                !applyToParagraphs &&
                formattingProperty != FrameworkElement.FlowDirectionProperty) // We dont want to apply flowdirection property to inlines when selection is empty. 
            {
                TextSegment autoWordRange = TextRangeBase.GetAutoWord(this);
                if (autoWordRange.IsNull)
                { 
                    // This property goes to springload formatting. We should not create undo unit for it.
                    if (_springloadFormatting == null) 
                    { 
                        _springloadFormatting = new DependencyObject();
                    } 

                    _springloadFormatting.SetValue(formattingProperty, value);
                }
                else 
                {
                    // TextRange will create undo unit with proper name 
                    new TextRange(autoWordRange.Start, autoWordRange.End).ApplyPropertyValue(formattingProperty, value); 
                }
            } 
            else
            {
                // No word to auto-format. Apply property to a selection.
                // TextRange will create undo unit with proper name 
                base.ApplyPropertyToTextVirtual(formattingProperty, value, applyToParagraphs, propertyValueAction);
                this.ClearSpringloadFormatting(); 
            } 
        }
 
        internal override void ClearAllPropertiesVirtual()
        {
            // Character property - applies to text runs in selected range, or springloaded if selection is empty
            if (this.IsEmpty) 
            {
                this.ClearSpringloadFormatting(); 
            } 
            else
            { 
                TextRangeBase.BeginChange(this);
                try
                {
                    base.ClearAllPropertiesVirtual(); 

                    this.ClearSpringloadFormatting(); 
                } 
                finally
                { 
                    TextRangeBase.EndChange(this);
                }
            }
        } 

        //...................................................... 
        // 
        //  Range Serialization
        // 
        //......................................................

        // Worker for Xml property setter; enables extensibility for TextSelection
        internal override void SetXmlVirtual(TextElement fragment) 
        {
            TextRangeBase.BeginChange(this); 
            try 
            {
                base.SetXmlVirtual(fragment); 

                this.ClearSpringloadFormatting();
            }
            finally 
            {
                TextRangeBase.EndChange(this); 
            } 
        }
 
        // Worker for Load public method; enables extensibility for TextSelection
        internal override void LoadVirtual(Stream stream, string dataFormat)
        {
            TextRangeBase.BeginChange(this); 
            try
            { 
                base.LoadVirtual(stream, dataFormat); 

                this.ClearSpringloadFormatting(); 
            }
            finally
            {
                TextRangeBase.EndChange(this); 
            }
        } 
 
        //......................................................
        // 
        //  Table Editing
        //
        //......................................................
 
        // Worker for InsertTable; enables extensibility for TextSelection
        internal override Table InsertTableVirtual(int rowCount, int columnCount) 
        { 
            using (DeclareChangeBlock())
            { 
                Table table = base.InsertTableVirtual(rowCount, columnCount);

                if (table != null)
                { 
                    TextPointer cellStart = table.RowGroups[0].Rows[0].Cells[0].ContentStart;
 
                    this.SetCaretToPosition(cellStart, LogicalDirection.Backward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/false); 
                }
 
                return table;
            }
        }
 
        // ..............................................................
        // 
        // Springload Formatting 
        //
        // .............................................................. 

        #region Springload Formatting

        ///  
        /// Function used in OnApplyProperty commands for character formatting properties.
        /// It takes care of springload formatting (applied to empty selection). 
        ///  
        /// 
        /// Property whose value is subject to be toggled. 
        /// 
        /// 
        /// The value of a property
        ///  
        internal object GetCurrentValue(DependencyProperty formattingProperty)
        { 
            ITextSelection thisSelection = this; 
            object propertyValue = DependencyProperty.UnsetValue;
 
            if (thisSelection.Start is TextPointer)
            {
                if (_springloadFormatting != null && this.IsEmpty)
                { 
                    // Get springload value
                    propertyValue = _springloadFormatting.ReadLocalValue(formattingProperty); 
                    if (propertyValue == DependencyProperty.UnsetValue) 
                    {
                        propertyValue = this.Start.Parent.GetValue(formattingProperty); 
                    }
                }
            }
 
            // If there's no spring loaded value, read the local value.
            if (propertyValue == DependencyProperty.UnsetValue) 
            { 
                propertyValue = this.PropertyPosition.GetValue(formattingProperty);
            } 

            return propertyValue;
        }
 
        /// 
        /// Reads a set of current formatting properties (from selection start) 
        /// into _springloadFormatting - to apply potentially for the following input. 
        /// 
        internal void SpringloadCurrentFormatting() 
        {
            if (((ITextSelection)this).Start is TextPointer)
            {
                TextPointer start = this.Start; 

                Inline ancestor = start.GetNonMergeableInlineAncestor(); 
                if (ancestor != null) 
                {
                    // Unless the selection is wholly contained within a Hyperlink, we don't 
                    // want to springload its character properties.
                    if (this.End.GetNonMergeableInlineAncestor() != ancestor)
                    {
                        start = ancestor.ElementEnd; 
                    }
                } 
 
                if (_springloadFormatting == null)
                { 
                    SpringloadCurrentFormatting(start.Parent);
                }
            }
        } 

        private void SpringloadCurrentFormatting(DependencyObject parent) 
        { 
            // Create new bag for formatting properties
            _springloadFormatting = new DependencyObject(); 

            // Check if we have an object to read from
            if (parent == null)
            { 
                return;
            } 
 
            DependencyProperty[] inheritableProperties = TextSchema.GetInheritableProperties(typeof(Inline));
            DependencyProperty[] noninheritableProperties = TextSchema.GetNoninheritableProperties(typeof(Span)); 

            // Walk up the tree.  At each step, if the element is typographical only,
            // grab all non-inherited values.  When we reach the top of the tree, grab all
            // values. 
            DependencyObject element = parent;
            while (element is Inline) 
            { 
                TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(element.GetType(), typeof(TextElementEditingBehaviorAttribute));
                if (att.IsTypographicOnly) 
                {
                    for (int i = 0; i < inheritableProperties.Length; i++)
                    {
                        if (_springloadFormatting.ReadLocalValue(inheritableProperties[i]) == DependencyProperty.UnsetValue && 
                            inheritableProperties[i] != FrameworkElement.LanguageProperty &&
                            inheritableProperties[i] != FrameworkElement.FlowDirectionProperty && 
                            System.Windows.DependencyPropertyHelper.GetValueSource(element, inheritableProperties[i]).BaseValueSource != BaseValueSource.Inherited) 
                        {
                            object value = parent.GetValue(inheritableProperties[i]); 
                            _springloadFormatting.SetValue(inheritableProperties[i], value);
                        }
                    }
                    for (int i = 0; i < noninheritableProperties.Length; i++) 
                    {
                        if (_springloadFormatting.ReadLocalValue(noninheritableProperties[i]) == DependencyProperty.UnsetValue && 
                            noninheritableProperties[i] != TextElement.TextEffectsProperty && 
                            System.Windows.DependencyPropertyHelper.GetValueSource(element, noninheritableProperties[i]).BaseValueSource != BaseValueSource.Inherited)
                        { 
                            object value = parent.GetValue(noninheritableProperties[i]);
                            _springloadFormatting.SetValue(noninheritableProperties[i], value);
                        }
                    } 
                }
                element = ((TextElement)element).Parent; 
            } 
        }
 
        /// 
        /// Clears springload formatting, so that the following text input
        /// will use formatting from a current position.
        ///  
        internal void ClearSpringloadFormatting()
        { 
            if (((ITextSelection)this).Start is TextPointer) 
            {
                // Delete all springloaded values 
                _springloadFormatting = null;

                // Update caret italic state
                ((ITextSelection)this).RefreshCaret(); 
            }
        } 
 
        /// 
        /// Applies springload formatting to a given content range. 
        /// Clears springloadFormatting after applying it.
        /// 
        internal void ApplySpringloadFormatting()
        { 
            if (!(((ITextSelection)this).Start is TextPointer))
            { 
                return; 
            }
 
            if (this.IsEmpty)
            {
                // We can't apply formatting to non-TextContainers or empty selection.
                return; 
            }
 
            if (_springloadFormatting != null) 
            {
                Invariant.Assert(this.Start.LogicalDirection == LogicalDirection.Backward); 
                Invariant.Assert(this.End.LogicalDirection == LogicalDirection.Forward);

                LocalValueEnumerator springloadFormattingValues = _springloadFormatting.GetLocalValueEnumerator();
 
                while (!this.IsEmpty && springloadFormattingValues.MoveNext())
                { 
                    // Note: we repeatedly check for IsEmpty because the selection 
                    // may become empty as a result of normalization after formatting
                    // (thai character sequence). 
                    LocalValueEntry propertyEntry = springloadFormattingValues.Current;
                    Invariant.Assert(TextSchema.IsCharacterProperty(propertyEntry.Property));
                    base.ApplyPropertyValue(propertyEntry.Property, propertyEntry.Value);
                } 

                ClearSpringloadFormatting(); 
            } 
        }
 
        #endregion Springload Formatting

        #region Caret Support
 
        // ..............................................................
        // 
        // Caret Support 
        //
        // .............................................................. 

        // Shows/hides the caret and scrolls it into view if requested.
        // Called when the range is moved or layout is updated.
        internal void UpdateCaretState(CaretScrollMethod caretScrollMethod) 
        {
            Invariant.Assert(caretScrollMethod != CaretScrollMethod.Unset); 
 
            if (_pendingCaretNavigation)
            { 
                caretScrollMethod = CaretScrollMethod.Navigation;
                _pendingCaretNavigation = false;
            }
 
            if (_caretScrollMethod == CaretScrollMethod.Unset)
            { 
                _caretScrollMethod = caretScrollMethod; 

                // Post a "Loaded" priority operation to the dispatcher queue. 

                // Operations at Loaded priority are processed when layout and render is
                // done but just before items at input priority are serviced.
                // We want the update caret worker to run after layout is clean. 
                if (_textEditor.TextView != null && _textEditor.TextView.IsValid)
                { 
                    UpdateCaretStateWorker(null); 
                }
                else 
                {
                    _pendingUpdateCaretStateCallback = true;
                }
            } 
            else if (caretScrollMethod != CaretScrollMethod.None)
            { 
                _caretScrollMethod = caretScrollMethod; 
            }
        } 

        // Get the caret brush that is the inverted color from the system window or background color.
        internal static Brush GetCaretBrush(TextEditor textEditor)
        { 
            Color backgroundColor;
            ITextSelection focusedTextSelection; 
            object backgroundPropertyValue; 

            // If TextBoxBase.CaretBrush has been set, use that instead of the default inverting behavior. 
            Brush caretBrush = (Brush)textEditor.UiScope.GetValue(TextBoxBase.CaretBrushProperty);
            if (caretBrush != null)
            {
                return caretBrush; 
            }
 
            // Get the default background from the system color or UiScope's background 
            backgroundPropertyValue = textEditor.UiScope.GetValue(System.Windows.Controls.Panel.BackgroundProperty);
            if (backgroundPropertyValue != null && backgroundPropertyValue != DependencyProperty.UnsetValue && 
                backgroundPropertyValue is SolidColorBrush)
            {
                backgroundColor = ((SolidColorBrush)backgroundPropertyValue).Color;
            } 
            else
            { 
                backgroundColor = SystemColors.WindowColor; 
            }
 
            // Get the background color from current selection
            focusedTextSelection = textEditor.Selection;
            if (focusedTextSelection is TextSelection)
            { 
                backgroundPropertyValue = ((TextSelection)focusedTextSelection).GetCurrentValue(TextElement.BackgroundProperty);
                if (backgroundPropertyValue != null && backgroundPropertyValue != DependencyProperty.UnsetValue) 
                { 
                    if (backgroundPropertyValue is SolidColorBrush)
                    { 
                        backgroundColor = ((SolidColorBrush)backgroundPropertyValue).Color;
                    }
                }
            } 

            // Invert the color to get the caret color from the system window or background color. 
            byte r = (byte)~(backgroundColor.R); 
            byte g = (byte)~(backgroundColor.G);
            byte b = (byte)~(backgroundColor.B); 

            caretBrush = new SolidColorBrush(Color.FromRgb(r, g, b));
            caretBrush.Freeze();
            return caretBrush; 
        }
 
        #endregion Caret Support 

        #region Bidi Support 

        //......................................................
        //
        //  BIDI Support 
        //
        //...................................................... 
 
        /// 
        /// Check the installed bidi input language from the current 
        /// input keyboard list.
        /// 
        /// 
        /// Critical - calls unmanaged code to get the current available keyboard list. 
        /// TreatAsSafe - data exposed (user using bidi) is safe to release
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static bool IsBidiInputLanguageInstalled()
        { 
            bool bidiInputLanguageInstalled;

            bidiInputLanguageInstalled = false;
 
            int keyboardListCount = (int)SafeNativeMethods.GetKeyboardLayoutList(0, null);
            if (keyboardListCount > 0) 
            { 
                int keyboardListIndex;
                IntPtr[] keyboardList; 

                keyboardList = new IntPtr[keyboardListCount];

                keyboardListCount = SafeNativeMethods.GetKeyboardLayoutList(keyboardListCount, keyboardList); 

                for (keyboardListIndex = 0; 
                     (keyboardListIndex < keyboardList.Length) && (keyboardListIndex < keyboardListCount); 
                     keyboardListIndex++)
                { 
                    CultureInfo cultureInfo = new CultureInfo((short)keyboardList[keyboardListIndex]);

                    if (IsBidiInputLanguage(cultureInfo))
                    { 
                        bidiInputLanguageInstalled = true;
                        break; 
                    } 
                }
            } 

            return bidiInputLanguageInstalled;
        }
 
        #endregion Bidi Support
 
        // Forces a synchronous layout validation, up to the selection moving position. 
        void ITextSelection.ValidateLayout()
        { 
            ((ITextSelection)this).MovingPosition.ValidateLayout();
        }

        #endregion Internal methods 

        //----------------------------------------------------- 
        // 
        //  Internal Properties
        // 
        //------------------------------------------------------

        #region Internal Properties
 
        // Caret associated with this TextSelection.
        internal CaretElement CaretElement 
        { 
            get
            { 
                return _caretElement;
            }
        }
 
        // Caret associated with this TextSelection.
        CaretElement ITextSelection.CaretElement 
        { 
            get
            { 
                return this.CaretElement;
            }
        }
 
        // Returns true iff there are no additional insertion positions are either
        // end of the selection. 
        bool ITextSelection.CoversEntireContent 
        {
            get 
            {
                ITextSelection This = this;

                return (This.Start.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text && 
                        This.End.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text &&
                        This.Start.GetNextInsertionPosition(LogicalDirection.Backward) == null && 
                        This.End.GetNextInsertionPosition(LogicalDirection.Forward) == null); 
            }
        } 

        #endregion Internal Properties

        //------------------------------------------------------ 
        //
        //  Private Methods 
        // 
        //-----------------------------------------------------
 
        #region Private Methods

        // Stores this TextSelection into our TLS slot.
        private void SetThreadSelection() 
        {
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; 
 
            // Store this selection as focused one
            threadLocalStore.FocusedTextSelection = this; 
        }

        // Removes this TextSelection from our TLS slot.
        private void ClearThreadSelection() 
        {
            // Clear currently focused selection, if it's us 
            if (TextEditor._ThreadLocalStore.FocusedTextSelection == this) 
            {
                TextEditor._ThreadLocalStore.FocusedTextSelection = null; 
            }
        }

        // GotKeyboardFocus event handler.  Called by UpdateCaretAndHighlight. 
        private void Highlight()
        { 
            ITextContainer textContainer = ((ITextSelection)this).Start.TextContainer; 

            // Only fixed documents use the highlight layer for selection. In all other cases, 
            // selection is rendered on the adorner layer. Since we split up individual runs
            // fed in to TextFormatter at highlight boundaries, using the highlight layer for
            // selection can affect measure.
            if (textContainer is TextContainer || textContainer is PasswordTextContainer) 
            {
                return; 
            } 

            // Make sure that a highlight layer exists for drawing this selection 
            if (_highlightLayer == null)
            {
                _highlightLayer = new TextSelectionHighlightLayer(this);
            } 

            // Make selection visible 
            if (textContainer.Highlights.GetLayer(typeof(TextSelection)) == null) 
            {
                textContainer.Highlights.AddLayer(_highlightLayer); 
            }
        }

        // LostKeyboardFocus event handler.  Called by UpdateCaretAndHighlight. 
        private void Unhighlight()
        { 
            ITextContainer textContainer = ((ITextSelection)this).Start.TextContainer; 
            TextSelectionHighlightLayer highlightLayer = textContainer.Highlights.GetLayer(typeof(TextSelection)) as TextSelectionHighlightLayer;
            if (highlightLayer != null) 
            {
                textContainer.Highlights.RemoveLayer(highlightLayer);
                Invariant.Assert(textContainer.Highlights.GetLayer(typeof(TextSelection)) == null);
            } 
        }
 
        //...................................................... 
        //
        //  Active Positions of Selection 
        //
        //......................................................

        ///  
        /// Stores normalized anchor and moving positions for the selection.
        /// Ensures that they are both inside of range Start/End. 
        ///  
        /// 
        /// A position which must be stored as initial position for the selection. 
        /// 
        /// 
        /// The "hot" or active selection edge which responds to user input.
        ///  
        private void SetActivePositions(ITextPointer anchorPosition, ITextPointer movingPosition)
        { 
            // The following settings are used in auto-word exapnsion. 
            // By setting a _previousPosition we are clearing them all -
            // they will be re-initialized in the beginning of a selection 
            // expansion guesture in ExtendSelectionByMouse method
            // Previous position is needed for selection gestures to remember
            // where mouse drag happed last time. Used for word autoexpansion.
            _previousCursorPosition = null; 

            if (this.IsEmpty) 
            { 
                _anchorPosition = null;
                _movingPositionEdge = MovingEdge.None; 
                return;
            }

            Invariant.Assert(anchorPosition != null); 

            ITextSelection thisSelection = (ITextSelection)this; 
 
            // Normalize and store new selection anchor position
            _anchorPosition = anchorPosition.GetInsertionPosition(anchorPosition.LogicalDirection); 

            // Ensure that anchor position is within one of text segments
            if (_anchorPosition.CompareTo(thisSelection.Start) < 0)
            { 
                _anchorPosition = thisSelection.Start.GetFrozenPointer(_anchorPosition.LogicalDirection);
            } 
            else if (_anchorPosition.CompareTo(thisSelection.End) > 0) 
            {
                _anchorPosition = thisSelection.End.GetFrozenPointer(_anchorPosition.LogicalDirection); 
            }

            _movingPositionEdge = ConvertToMovingEdge(anchorPosition, movingPosition);
            _movingPositionDirection = movingPosition.LogicalDirection; 
        }
 
        // Uses the current selection state to match an ITextPointer to one of the possible 
        // moving position edges.
        private MovingEdge ConvertToMovingEdge(ITextPointer anchorPosition, ITextPointer movingPosition) 
        {
            ITextSelection thisSelection = this;
            MovingEdge movingEdge;
 
            if (thisSelection.IsEmpty)
            { 
                // Empty selections have no moving edge. 
                movingEdge = MovingEdge.None;
            } 
            else if (thisSelection.TextSegments.Count < 2)
            {
                // Simple text selections move opposite their anchor positions.
                movingEdge = (anchorPosition.CompareTo(movingPosition) <= 0) ? MovingEdge.End : MovingEdge.Start; 
            }
            else 
            { 
                // Table selection.  Look for an exact match.
                if (movingPosition.CompareTo(thisSelection.Start) == 0) 
                {
                    movingEdge = MovingEdge.Start;
                }
                else if (movingPosition.CompareTo(thisSelection.End) == 0) 
                {
                    movingEdge = MovingEdge.End; 
                } 
                else if (movingPosition.CompareTo(thisSelection.TextSegments[0].End) == 0)
                { 
                    movingEdge = MovingEdge.StartInner;
                }
                else if (movingPosition.CompareTo(thisSelection.TextSegments[thisSelection.TextSegments.Count-1].Start) == 0)
                { 
                    movingEdge = MovingEdge.EndInner;
                } 
                else 
                {
                    movingEdge = (anchorPosition.CompareTo(movingPosition) <= 0) ? MovingEdge.End : MovingEdge.Start; 
                }
            }

            return movingEdge; 
        }
 
        //...................................................... 
        //
        //  Selection Building With Mouse 
        //
        //......................................................

        // Moves the selection to the mouse cursor position. 
        // If the cursor is facing a UIElement, select the UIElement.
        // Sets new selection anchor to a given cursorPosition. 
        private void MoveSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint) 
        {
            ITextSelection thisSelection = (ITextSelection)this; 

            if (this.TextView == null)
            {
                return; 
            }
            Invariant.Assert(this.TextView.IsValid); // We just checked RenderScope. We'll use TextView below 
 
            ITextPointer movingPosition = null;
 
            if (cursorPosition.GetPointerContext(cursorPosition.LogicalDirection) == TextPointerContext.EmbeddedElement)
            {
                Rect objectEdgeRect = this.TextView.GetRectangleFromTextPosition(cursorPosition);
 
                // Check for embedded object.
                // If the click happend inside of it we need to select it as a whole, when content is not read-only. 
                if (!_textEditor.IsReadOnly && ShouldSelectEmbeddedObject(cursorPosition, cursorMousePoint, objectEdgeRect)) 
                {
                    movingPosition = cursorPosition.GetNextContextPosition(cursorPosition.LogicalDirection); 
                }
            }

            // Move selection to this position 
            if (movingPosition == null)
            { 
                thisSelection.SetCaretToPosition(cursorPosition, cursorPosition.LogicalDirection, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/false); 
            }
            else 
            {
                thisSelection.Select(cursorPosition, movingPosition);
            }
        } 

        // Helper for MoveSelectionByMouse 
        private bool ShouldSelectEmbeddedObject(ITextPointer cursorPosition, Point cursorMousePoint, Rect objectEdgeRect) 
        {
            // Although we now know that cursorPosition is facing an embedded object, 
            // we still need an additional test to determine if the original mouse point
            // fell within the object or outside it's bouding box (which can happen when
            // a mouse click is snapped to the nearest content).
            // If the mouse point is outside the object, we don't want to select it. 
            if (!objectEdgeRect.IsEmpty &&
                cursorMousePoint.Y >= objectEdgeRect.Y && cursorMousePoint.Y < objectEdgeRect.Y + objectEdgeRect.Height) 
            { 
                // Compare X coordinates of mouse down point and object edge rect,
                // depending on the FlowDirection of the render scope and paragraph content. 

                FlowDirection renderScopeFlowDirection = (FlowDirection)this.TextView.RenderScope.GetValue(Block.FlowDirectionProperty);
                FlowDirection paragraphFlowDirection = (FlowDirection)cursorPosition.GetValue(Block.FlowDirectionProperty);
 
                if (renderScopeFlowDirection == FlowDirection.LeftToRight)
                { 
                    if (paragraphFlowDirection == FlowDirection.LeftToRight && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X < cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X < objectEdgeRect.X)) 
                    {
                        return true;
                    }
                    else if (paragraphFlowDirection == FlowDirection.RightToLeft && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X > cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X > objectEdgeRect.X)) 
                    { 
                        return true;
                    } 
                }
                else
                {
                    if (paragraphFlowDirection == FlowDirection.LeftToRight && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X > cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X > objectEdgeRect.X)) 
                    { 
                        return true;
                    } 
                    else if (paragraphFlowDirection == FlowDirection.RightToLeft &&
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X < cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X < objectEdgeRect.X))
                    { 
                        return true;
                    } 
                } 
            }
 
            return false;
        }

        //...................................................... 
        //
        //  Caret Support 
        // 
        //......................................................
 
        // Redraws a caret using current setting for italic - taking springload formatting into account.
        private static void RefreshCaret(TextEditor textEditor, ITextSelection textSelection)
        {
            object fontStylePropertyValue; 
            bool italic;
 
            if (textSelection == null || textSelection.CaretElement == null) 
            {
                return; 
            }

            // NOTE: We are using GetCurrentValue to take springload formatting into account.
            fontStylePropertyValue = ((TextSelection)textSelection).GetCurrentValue(TextElement.FontStyleProperty); 
            italic = (textEditor.AcceptsRichContent && fontStylePropertyValue != DependencyProperty.UnsetValue && (FontStyle)fontStylePropertyValue == FontStyles.Italic);
 
            textSelection.CaretElement.RefreshCaret(italic); 
        }
 
        // Called after a caret navigation, to signal that the next caret
        // scroll-into-view should include hueristics to include following
        // text.
        internal void OnCaretNavigation() 
        {
            _pendingCaretNavigation = true; 
        } 

        // Called after a caret navigation, to signal that the next caret 
        // scroll-into-view should include hueristics to include following
        // text.
        void ITextSelection.OnCaretNavigation()
        { 
            OnCaretNavigation();
        } 
 
        // Callback for UpdateCaretState worker.
        private object UpdateCaretStateWorker(object o) 
        {
            _pendingUpdateCaretStateCallback = false;

            // This can happen if selection has been detached by TextEditor.OnDetach. 
            if (_textEditor == null)
            { 
                return null; 
            }
 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;

            CaretScrollMethod caretScrollMethod = _caretScrollMethod;
            _caretScrollMethod = CaretScrollMethod.Unset; 

            // Use the locally defined caretElement because _caretElement can be null by 
            // detaching CaretElement object 
            CaretElement caretElement = _caretElement;
 
            if (caretElement == null)
            {
                return null;
            } 

            if (threadLocalStore.FocusedTextSelection == null) 
            { 
                // If we have multiple windows open, a non-blinking caret might be showing
                // in the given TextEditor's UiScope.  If the selection for that Editor is 
                // not empty, we need to hide the caret.
                if (!this.IsEmpty)
                {
                    caretElement.Hide(); 
                }
 
                return null; 
            }
 
            // When the TextView is not valid, there is nothing to do
            if (_textEditor.TextView == null || !_textEditor.TextView.IsValid)
            {
                // 
                return null;
            } 
 
            if (!this.VerifyAdornerLayerExists())
            { 
                caretElement.Hide();
            }

            // Identify caret position 
            // Make sure that moving position is inside of selection
            ITextPointer caretPosition = IdentifyCaretPosition(this); 
 
            // If caret position is not valid in focusedTextSelection.TextView, we cannot update it.
            if (caretPosition.HasValidLayout) 
            {
                Rect caretRectangle;
                bool italic = false;
                bool caretVisible = this.IsEmpty && (!_textEditor.IsReadOnly || _textEditor.IsReadOnlyCaretVisible); 

                if (!this.IsInterimSelection) 
                { 
                    caretRectangle = CalculateCaretRectangle(this, caretPosition);
 
                    if (this.IsEmpty)
                    {
                        // Identify italic condition (including springload) - to use for caret shaping
                        object fontStylePropertyValue = GetPropertyValue(TextElement.FontStyleProperty); 
                        italic = (_textEditor.AcceptsRichContent && fontStylePropertyValue != DependencyProperty.UnsetValue && (FontStyle)fontStylePropertyValue == FontStyles.Italic);
                    } 
                } 
                else
                { 
                    caretRectangle = CalculateInterimCaretRectangle(this);

                    // Caret always visible on the interim input mode.
                    caretVisible = true; 
                }
 
                Brush caretBrush = GetCaretBrush(_textEditor); 

                // Calculate the scroll origin position to scroll it with the caret position. 
                double scrollToOriginPosition = CalculateScrollToOriginPosition(_textEditor, caretPosition, caretRectangle.X);

                // Re-render the caret.
                // Get a bounding rect from the active end of selection. 
                caretElement.Update(caretVisible, caretRectangle, caretBrush, 1.0, italic, caretScrollMethod, scrollToOriginPosition);
            } 
 
            //  CaretElement.Update(...) makes a conditional call to BringIntoView()
            //  on the text view's associated element, which makes the view invalid... 
            if (this.TextView.IsValid && !this.TextView.RendersOwnSelection)
            {
                // Re-render selection. Need to do this to invalidate and update adorner for this caret element.
                caretElement.UpdateSelection(); 
            }
 
            return null; 
        }
 
        // Helper for UpdateCaretState -- identifies caret position from text selection.
        private static ITextPointer IdentifyCaretPosition(ITextSelection currentTextSelection)
        {
            ITextPointer caretPosition = currentTextSelection.MovingPosition; 

            if (!currentTextSelection.IsEmpty) 
            { 
                // Even when we do not draw the blinking caret, we need this position
                // for scrolling caret position into view. 

                // Special case for nonempty selection extended beyond end of line
                if ((caretPosition.LogicalDirection == LogicalDirection.Backward && //
                     caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) || // 
                    TextPointerBase.IsAfterLastParagraph(caretPosition))
                { 
                    // This means that selection has been expanded by ExtendToLineEnd/ExtendToDocumentEnd command. 
                    // TextView in this case cannot give the rect from this position;
                    // we need to move backward to the end of content 
                    caretPosition = caretPosition.CreatePointer();
                    caretPosition.MoveToNextInsertionPosition(LogicalDirection.Backward);
                    caretPosition.SetLogicalDirection(LogicalDirection.Forward);
                } 
            }
 
            // TextView.GetRectangleFromTextPosition returns the end of character rect in case of Backward 
            // logical direction at the start caret position of the docuemtn or paragraph, so we reset the
            // logical direction with Forward to get the right rect of caret at the start position of 
            // document or paragraph.
            if (caretPosition.LogicalDirection == LogicalDirection.Backward && //
                caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart && //
                (caretPosition.GetNextInsertionPosition(LogicalDirection.Backward) == null || // 
                 TextPointerBase.IsNextToAnyBreak(caretPosition, LogicalDirection.Backward)))
            { 
                caretPosition = caretPosition.CreatePointer(); 
                caretPosition.SetLogicalDirection(LogicalDirection.Forward);
            } 

            return caretPosition;
        }
 
        // Helper for UpdateCaretState -- calculates caret rectangle from text selection.
        // regular (non-interim) case of caret positioning 
        private static Rect CalculateCaretRectangle(ITextSelection currentTextSelection, ITextPointer caretPosition) 
        {
            Transform caretTransform; 
            Rect caretRectangle = currentTextSelection.TextView.GetRawRectangleFromTextPosition(caretPosition, out caretTransform);

            if (caretRectangle.IsEmpty)
            { 
                // Caret is not at an insertion position, it has no geometry
                // and will not be displayed. 
                return Rect.Empty; 
            }
 
            // Convert to local coordiantes.
            caretRectangle = caretTransform.TransformBounds(caretRectangle);

            // We will use the system defined caret width later. 
            caretRectangle.Width = 0;
 
            if (currentTextSelection.IsEmpty) 
            {
                // Calculate caret height - from current font size (ignoring a rect returned by TextView, 
                // as it can be a rect of embedded object, which should not affect caret height)
                double fontSize = (double)currentTextSelection.GetPropertyValue(TextElement.FontSizeProperty);
                FontFamily fontFamily = (FontFamily)currentTextSelection.GetPropertyValue(TextElement.FontFamilyProperty);
                double caretHeight = fontFamily.LineSpacing * fontSize; 
                if (caretHeight < caretRectangle.Height)
                { 
                    // Decrease the height of caret to the font height and lower the caret to keep its bottom 
                    // staying on the baseline.
                    caretRectangle.Y += caretRectangle.Height - caretHeight; 
                    caretRectangle.Height = caretHeight;
                }

                if (!caretTransform.IsIdentity) 
                {
                    Point top = new Point(caretRectangle.X, caretRectangle.Y); 
                    Point bottom = new Point(caretRectangle.X, caretRectangle.Y + caretRectangle.Height); 
                    caretTransform.TryTransform(top, out top);
                    caretTransform.TryTransform(bottom, out bottom); 
                    caretRectangle.Y += caretRectangle.Height - Math.Abs(bottom.Y - top.Y);
                    caretRectangle.Height = Math.Abs(bottom.Y - top.Y);
                }
            } 

            return caretRectangle; 
        } 

        // Helper for UpdateCaretState -- handles the korean interim caret. 
        private static Rect CalculateInterimCaretRectangle(ITextSelection focusedTextSelection)
        {
            //
 
            // Get the current flow direction on the selection of interim.
            // This is for getting the right size of distance on the interim character 
            // whatever the current flow direction is. 
            FlowDirection flowDirection = (FlowDirection)focusedTextSelection.Start.GetValue(FrameworkElement.FlowDirectionProperty);
 
            ITextPointer nextCharacterPosition;
            Rect nextCharacterRectangle;
            Rect caretRectangle;
 
            if (flowDirection != FlowDirection.RightToLeft)
            { 
                // Flow direction is Left-to-Right 
                // Get the rectangle for both interim selection start position and the next character
                // position. 
                nextCharacterPosition = focusedTextSelection.Start.CreatePointer(LogicalDirection.Forward);
                caretRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition);

                // Get the next character position from the start position of the interim selection 
                // on the left to right flow direction.
                nextCharacterPosition.MoveToNextInsertionPosition(LogicalDirection.Forward); 
                nextCharacterPosition.SetLogicalDirection(LogicalDirection.Backward); 
                nextCharacterRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition);
            } 
            else
            {
                // Flow direction is Right-to-Left
                // Get the rectangle for both interim selection end position and the next character 
                // position.
                nextCharacterPosition = focusedTextSelection.End.CreatePointer(LogicalDirection.Backward); 
                caretRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition); 

                // Get the next character position from the end position of the interim selection 
                // on the right to left flow direction.
                nextCharacterPosition.MoveToNextInsertionPosition(LogicalDirection.Backward);
                nextCharacterPosition.SetLogicalDirection(LogicalDirection.Forward);
                nextCharacterRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition); 
            }
 
            // The interim next character position should be great than the current interim position. 
            // Otherwise, we show the caret as the normal state that use the system caret width.
            // In case of BiDi character, the next character position can be greater than the current position. 
            if (!caretRectangle.IsEmpty && !nextCharacterRectangle.IsEmpty && nextCharacterRectangle.Left > caretRectangle.Left)
            {
                // Get the interim caret width to show the interim block caret.
                caretRectangle.Width = nextCharacterRectangle.Left - caretRectangle.Left; 
            }
 
            return caretRectangle; 
        }
 
        // Helper for UpdateCaretStateWorker -- Calculate the scroll origin position to scroll caret
        // with the scroll origin position so that we can ensure of displaying caret with the wrapped word.
        //
        // There are four cases of different corrdinate by the flow direction on UiScope and Paragraph. 
        // UiScope has two flow direction which is LeftToRightflow directioin and another is RightToLeft.
        // Paragraph has also two flow direction which is LeftToRightflow directioin and another is RightToLeft. 
        // 
        // The below is the example of how horizontal corrdinate and scroll origin value base on the different
        // four cases. So we have to calculate the scroll to origin position base on the case. Simply we can 
        // get the scroll to origin value as zero if UiScope and Paragraph's flow direction is the same.
        // Otherwise, the scroll to origin value is the extent width value that is the max width.
        //
        // <> 
        //  Case 1.
        //      UiScope FlowDirection:              LTR(LeftToRight) 
        //      Paragraph FlowDirection:            LTR(LefTToRight) 
        //          Horizontal origin:              "Left"
        //          Scroll horizontal origin:       "0" 
        //          Wrapping to:                    "Left"
        //              ABC ......
        //              XYZ|
        // 
        //  Case 2.
        //      UiScope FlowDirection:              LTR(LeftToRight) 
        //      Paragraph FlowDirection:            RTL(RightToLeft) 
        //          Horizontal origin:              "Left"
        //          Scroll horizontal origin:       "Max:Extent Width" 
        //          Wrapping to:                    "Right"
        //              ......ABC
        //                    XYZ|
        // 
        //  Case 3.
        //      UiScope FlowDirection:              RTL(RightToLeft) 
        //      Paragraph FlowDirection:            RTL(RightToLeft) 
        //          horizontal origin:              "Right"
        //          Scroll horizontal origin:       "0" 
        //          Wrapping to:                    "Right"
        //              ......ABC
        //                    XYZ|
        // 
        //  Case 4.
        //      UiScope FlowDirection:              RTL(RightToLeft) 
        //      Paragraph FlowDirection:            LTR(LefTToRight) 
        //          horizontal origin:              "Right"
        //          Scroll horizontal origin:       "Max:Extent Width" 
        //          Wrapping to:                    "Left"
        //              ABC ......
        //              XYZ|
        private static double CalculateScrollToOriginPosition(TextEditor textEditor, ITextPointer caretPosition, double horizontalCaretPosition) 
        {
            double scrollToOriginPosition = double.NaN; 
 
            if (textEditor.UiScope is TextBoxBase)
            { 
                double viewportWidth = ((TextBoxBase)textEditor.UiScope).ViewportWidth;
                double extentWidth = ((TextBoxBase)textEditor.UiScope).ExtentWidth;

                // Calculate the scroll to the origin position position when the horizontal scroll is available 
                if (viewportWidth != 0 && extentWidth != 0 && viewportWidth < extentWidth)
                { 
                    bool needScrollToOriginPosition = false; 

                    // Check whether we need to calculate the scroll origin position to scroll it with the caret 
                    // position. If the caret position is out of the current visual viewport area, the scroll
                    // to origin positioin will be calculated to scroll into the origin position first that
                    // ensure of displaying the wrapped word.
                    // 
                    // Note that horizontalCaretPosition is always relative to the viewport, not the document.
                    if (horizontalCaretPosition < 0 || horizontalCaretPosition >= viewportWidth) 
                    { 
                        needScrollToOriginPosition = true;
                    } 

                    if (needScrollToOriginPosition)
                    {
                        // Set the scroll original position as zero 
                        scrollToOriginPosition = 0;
 
                        // Get the flow direction of uiScope 
                        FlowDirection uiScopeflowDirection = (FlowDirection)textEditor.UiScope.GetValue(FrameworkElement.FlowDirectionProperty);
 
                        // Get the flow direction of the current paragraph and compare it with uiScope's flow direction.
                        Block paragraphOrBlockUIContainer = (caretPosition is TextPointer) ? ((TextPointer)caretPosition).ParagraphOrBlockUIContainer : null;
                        if (paragraphOrBlockUIContainer != null)
                        { 
                            FlowDirection pagraphFlowDirection = paragraphOrBlockUIContainer.FlowDirection;
 
                            // If the flow direction is different between uiScopoe and paragaph, 
                            // the original scroll position is the extent width value.
                            if (uiScopeflowDirection != pagraphFlowDirection) 
                            {
                                scrollToOriginPosition = extentWidth;
                            }
                        } 

                        // Adjust scroll position by current viewport offset 
                        scrollToOriginPosition -= ((TextBoxBase)textEditor.UiScope).HorizontalOffset; 
                    }
                } 
            }

            return scrollToOriginPosition;
        } 

        private CaretElement EnsureCaret(bool isBlinkEnabled, CaretScrollMethod scrollMethod) 
        { 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;
 
            if (_caretElement == null)
            {
                // Create new caret
                _caretElement = new CaretElement(_textEditor, isBlinkEnabled); 

                // Check the current input language to draw the BiDi caret in case of BiDi language 
                // like as Arabic or Hebrew input language. 
                //
                if (IsBidiInputLanguage(InputLanguageManager.Current.CurrentInputLanguage)) 
                {
                    TextEditor._ThreadLocalStore.Bidi = true;
                }
                else 
                {
                    TextEditor._ThreadLocalStore.Bidi = false; 
                } 
            }
            else 
            {
                _caretElement.SetBlinking(isBlinkEnabled);
            }
 
            UpdateCaretState(scrollMethod);
 
            return _caretElement; 
        }
 
        /// 
        /// Walk up the tree from the RenderScope to the UiScope until we find an
        /// AdornerDecorator or ScrollContentPresenter.
        ///  
        /// true if one is found, false otherwise
        private bool VerifyAdornerLayerExists() 
        { 
            DependencyObject element = TextView.RenderScope;
            while (element != _textEditor.UiScope && element != null) 
            {
                if (element is AdornerDecorator || element is System.Windows.Controls.ScrollContentPresenter)
                {
                    return true; 
                }
                element = VisualTreeHelper.GetParent(element); 
            } 
            return false;
        } 

        //......................................................
        //
        //  BIDI Support 
        //
        //...................................................... 
 
        /// 
        /// Check the input language of cultureInfo whether it is the bi-directional language or not. 
        /// 
        /// 
        /// 
        /// Return true if the passed cultureInfo is the bi-directional language like as Arabic or Hebrew. 
        /// Otherwise, return false.
        ///  
        ///  
        /// Critical - calls unmanaged code to check the font signature
        /// TreatAsSafe - data exposed (user using bidi) is safe to release 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private static bool IsBidiInputLanguage(CultureInfo cultureInfo)
        { 
            bool bidiInput;
            string fontSignature; 
 
            bidiInput = false;
 
            fontSignature = new String(new Char[FONTSIGNATURE_SIZE]);

            // Get the font signature to know the current LCID is BiDi(Arabic, Hebrew etc.) or not.
            if (UnsafeNativeMethods.GetLocaleInfoW(cultureInfo.LCID, NativeMethods.LOCALE_FONTSIGNATURE, fontSignature, FONTSIGNATURE_SIZE) != 0) 
            {
                // Compare fontSignature[7] with 0x0800 to detect BiDi language. 
                if ((fontSignature[FONTSIGNATURE_BIDI_INDEX] & FONTSIGNATURE_BIDI) != 0) 
                {
                    bidiInput = true; 
                }
            }

            return bidiInput; 
        }
 
        //...................................................... 
        //
        //  Table Selection 
        //
        //......................................................

        private static TableCell FindCellAtColumnIndex(TableCellCollection cells, int columnIndex) 
        {
            for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++) 
            { 
                TableCell cell;
                int startColumnIndex; 
                int endColumnIndex;

                cell = cells[cellIndex];
                startColumnIndex = cell.ColumnIndex; 
                endColumnIndex = startColumnIndex + cell.ColumnSpan - 1;
 
                if (startColumnIndex <= columnIndex && columnIndex <= endColumnIndex) 
                {
                    return cell; 
                }
            }

            return null; 
        }
 
        ///  
        /// Determines if the given element has any ancestor.
        ///  
        /// 
        /// 
        private static bool IsRootElement(DependencyObject element)
        { 
            return GetParentElement(element) == null;
        } 
 
        /// 
        /// Workaround to approximate whether or not our window is active. 
        /// 
        /// 
        private bool IsFocusWithinRoot()
        { 
            DependencyObject element = this.UiScope;
            DependencyObject parent = this.UiScope; 
 
            while (parent != null)
            { 
                element = parent;
                parent = GetParentElement(element);
            }
 
            if (element is UIElement && ((UIElement)element).IsKeyboardFocusWithin)
            { 
                return true; 
            }
 
            return false;
        }

        ///  
        /// Helper method to determine an element's parent, using the umpteen methods of
        /// parenting. 
        ///  
        /// 
        private static DependencyObject GetParentElement(DependencyObject element) 
        {
            DependencyObject parent;

            if (element is FrameworkElement || element is FrameworkContentElement) 
            {
                parent = LogicalTreeHelper.GetParent(element); 
                if (parent == null && element is FrameworkElement) 
                {
                    parent = ((FrameworkElement)element).TemplatedParent; 
                    if (parent == null && element is Visual)
                    {
                        parent = VisualTreeHelper.GetParent(element);
                    } 
                }
            } 
            else if (element is Visual) 
            {
                parent = VisualTreeHelper.GetParent(element); 
            }
            else
            {
                parent = null; 
            }
 
            return parent; 
        }
 
        // Removes the caret from the visual tree.
        private void DetachCaretFromVisualTree()
        {
            if (_caretElement != null) 
            {
                _caretElement.DetachFromView(); 
                _caretElement = null; 
            }
        } 

        #endregion Private methods

        //------------------------------------------------------ 
        //
        //  Private Properties 
        // 
        //-----------------------------------------------------
 
        #region Private Properties

        TextEditor ITextSelection.TextEditor
        { 
            get
            { 
                return _textEditor; 
            }
        } 

        ITextView ITextSelection.TextView
        {
            get 
            {
                return _textEditor.TextView; 
            } 
        }
 
        private ITextView TextView
        {
            get
            { 
                return ((ITextSelection)this).TextView;
            } 
        } 

        private TextStore TextStore 
        {
            get
            {
                return _textEditor.TextStore; 
            }
        } 
 
        private ImmComposition ImmComposition
        { 
            get
            {
                return _textEditor.ImmComposition;
            } 
        }
 
        // UiScope associated with this TextSelection's TextEditor. 
        private FrameworkElement UiScope
        { 
            get
            {
                return _textEditor.UiScope;
            } 
        }
 
        // Position from which to spring load property values. 
        private ITextPointer PropertyPosition
        { 
            get
            {
                ITextSelection This = this;
                ITextPointer position = null; 

                if (!This.IsEmpty) 
                { 
                    position = TextPointerBase.GetFollowingNonMergeableInlineContentStart(This.Start);
                } 

                if (position == null)
                {
                    position = This.Start; 
                }
 
                position.Freeze(); 
                return position;
            } 
        }

        #endregion Private Properties
 
        //-----------------------------------------------------
        // 
        //  Private Types 
        //
        //----------------------------------------------------- 

        #region Private Types

        // The four possible positions for the selection moving position. 
        private enum MovingEdge { Start, StartInner, EndInner, End, None };
 
        #endregion Private Types 

        //------------------------------------------------------ 
        //
        //  Private Fields
        //
        //----------------------------------------------------- 

        #region Private Fields 
 
        // Selected Content
        // ---------------- 

        // TextEditor that owns this selection.
        private TextEditor _textEditor;
 
        // Container for highlights on selected text.
        private TextSelectionHighlightLayer _highlightLayer; 
 
        // Springload Formatting
        // --------------------- 

        // Dependency object representing a set of springloaded formatting properties
        private DependencyObject _springloadFormatting;
 
        // Selection autoexpansion for unit boundaries
        // ------------------------------------------- 
 
        // A position where the last selection gesture has been initiated.
        // Selection gestures are: mouseDown-Move-...-Move-Up, Shift+ArrowDown-...-Down-Up. 
        // Note that Shift+MouseDown-Move-...-Move-Up is a gesture continuation,
        // it does not change _anchorPosition.
        // Actual selection always contains this position but may be extended
        // to a wider range - to encompass whole units such as words, 
        // hyperlinks, sentences, paragraphs, table cells etc.
        // 
 

 
        private ITextPointer _anchorPosition;

        // A position to which user input is applied.
        // It may coinside with Start or End, but it may be also in some other 
        // corner of rectangular table range.
        private MovingEdge _movingPositionEdge; 
 
        // LogicalDirection for the moving position.
        // If the selection is empty, this value is ignored and 
        // the direction matches this.Start.  Otherwise we respect
        // the value, which typically points inwards towards the
        // content but may point outward to include an empty line.
        private LogicalDirection _movingPositionDirection; 

        // Text position used on previous step of mouse dragging selection 
        // It is used in selection dragging heuristic to identify a situation when 
        // dragging end returned back to selected area which means that
        // autoword expansion must be temporary stopped - until a new word 
        // boundary is crossed. See also _reenterPosition.
        private ITextPointer _previousCursorPosition;

        // Text position where dragged mouse re-entered a selection. This word should not be autoexapnded 
        private ITextPointer _reenterPosition;
 
        // Flag indicating that initial word boundary has been crossed at least once doring selection expansion 
        private bool _anchorWordRangeHasBeenCrossedOnce;
 
        // Flag allows autoword expansion for anchor end of selection
        private bool _allowWordExpansionOnAnchorEnd;

        // Font signature size as 16 
        private const int FONTSIGNATURE_SIZE = 16;
 
        // BIDI font signature index from GetLocaleInfo. 
        private const int FONTSIGNATURE_BIDI_INDEX = 7;
 
        // BIDI font signature value
        private const int FONTSIGNATURE_BIDI = 0x0800;

        // Signals how the caret should be scrolled into view on the next 
        // caret update.
        private CaretScrollMethod _caretScrollMethod; 
 
        // If true, signals that the next caret
        // scroll-into-view should include hueristics to include following 
        // text.
        private bool _pendingCaretNavigation;

        // Caret associated with this selection. 
        private CaretElement _caretElement;
 
        // Flag set true after scheduling a callback to UpdateCaretStateWorker. 
        // Used to prevent unbounded callback allocations on the Dispatcher queue --
        // we fold redundant update requests into a single queue item. 
        bool _pendingUpdateCaretStateCallback;

        #endregion Private Fields
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// File: TextSelection.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: Holds and manipulates the text selection state for TextEditor. 
// 
//---------------------------------------------------------------------------
 
namespace System.Windows.Documents
{
    using MS.Internal;
    using System.Collections.Generic; 
    using System.Globalization;
    using System.Windows.Controls.Primitives;  // TextBoxBase 
    using System.Windows.Input; 
    using System.Windows.Media;
    using System.Windows.Threading; 
    using System.Threading;
    using System.Security;
    using System.Security.Permissions;
    using System.IO; 
    using System.Xml;
    using MS.Win32; 
    using System.Windows.Controls; 

    ///  
    /// The TextSelection class encapsulates selection state for the RichTextBox
    /// control.  It has no public constructor, but is exposed via a public
    /// property on RichTextBox.
    ///  
    public sealed class TextSelection : TextRange, ITextSelection
    { 
        #region Constructors 

        //----------------------------------------------------- 
        //
        //  Constructors
        //
        //----------------------------------------------------- 

        // Contstructor. 
        // TextSelection does not have a public constructor.  It is only accessible 
        // through TextEditor's Selection property.
        internal TextSelection(TextEditor textEditor) 
            : base(textEditor.TextContainer.Start, textEditor.TextContainer.Start)
        {
            ITextSelection thisSelection = (ITextSelection)this;
 
            Invariant.Assert(textEditor.UiScope != null);
 
            // Attach the selection to its editor 
            _textEditor = textEditor;
 
            // Initialize active pointers of the selection - anchor and moving pointers
            SetActivePositions(/*AnchorPosition:*/thisSelection.Start, thisSelection.End);

            // Activate selection in case if this control has keyboard focus already 
            thisSelection.UpdateCaretAndHighlight();
        } 
 
        #endregion Constructors
 
        // ******************************************************
        // *****************************************************
        // ******************************************************
        // 
        // Abstract TextSelection Implementation
        // 
        // ****************************************************** 
        // *****************************************************
        // ****************************************************** 

        //-----------------------------------------------------
        //
        // ITextRange implementation 
        //
        //----------------------------------------------------- 
 
        #region ITextRange Implementation
 
        //......................................................
        //
        // Selection Building
        // 
        //......................................................
 
        ///  
        /// 
        ///  
        void ITextRange.Select(ITextPointer anchorPosition, ITextPointer movingPosition)
        {
            TextRangeBase.BeginChange(this);
            try 
            {
                TextRangeBase.Select(this, anchorPosition, movingPosition); 
                SetActivePositions(anchorPosition, movingPosition); 
            }
            finally 
            {
                TextRangeBase.EndChange(this);
            }
        } 

        ///  
        ///  
        /// 
        void ITextRange.SelectWord(ITextPointer position) 
        {
            TextRangeBase.BeginChange(this);
            try
            { 
                TextRangeBase.SelectWord(this, position);
 
                ITextSelection thisSelection = this; 
                SetActivePositions(/*anchorPosition:*/thisSelection.Start, thisSelection.End);
            } 
            finally
            {
                TextRangeBase.EndChange(this);
            } 
        }
 
        ///  
        /// 
        ///  
        void ITextRange.SelectParagraph(ITextPointer position)
        {
            TextRangeBase.BeginChange(this);
            try 
            {
                TextRangeBase.SelectParagraph(this, position); 
 
                //
                ITextSelection thisSelection = this; 
                SetActivePositions(/*anchorPosition:*/position, thisSelection.End);
            }
            finally
            { 
                TextRangeBase.EndChange(this);
            } 
        } 

        ///  
        /// 
        /// 
        void ITextRange.ApplyTypingHeuristics(bool overType)
        { 
            TextRangeBase.BeginChange(this);
            try 
            { 
                TextRangeBase.ApplyInitialTypingHeuristics(this);
 
                // For non-empty selection start with saving current formatting
                if (!this.IsEmpty && _textEditor.AcceptsRichContent)
                {
                    SpringloadCurrentFormatting(); 
                    // Note: we springload formatting before overtype expansion
                } 
 
                TextRangeBase.ApplyFinalTypingHeuristics(this, overType);
            } 
            finally
            {
                TextRangeBase.EndChange(this);
            } 
        }
 
        ///  
        /// 
        ///  
        object ITextRange.GetPropertyValue(DependencyProperty formattingProperty)
        {
            object propertyValue;
 
            if (this.IsEmpty && TextSchema.IsCharacterProperty(formattingProperty))
            { 
                // For empty selection return springloaded formatting (only character formatting properties can be springloaded) 
                propertyValue = ((TextSelection)this).GetCurrentValue(formattingProperty);
            } 
            else
            {
                // Otherwise return base implementation from a TextRange.
                propertyValue = TextRangeBase.GetPropertyValue(this, formattingProperty); 
            }
 
            return propertyValue; 
        }
 
        //......................................................
        //
        // Plain Text Modification
        // 
        //......................................................
 
        //----------------------------------------------------- 
        //
        //  Overrides 
        //
        //------------------------------------------------------

        // Set true if a Changed event is pending. 
        bool ITextRange._IsChanged
        { 
            get 
            {
                return _IsChanged; 
            }

            set
            { 
                // TextStore needs to know about state changes
                // from false to true. 
                if (!_IsChanged && value) 
                {
                    if (this.TextStore != null) 
                    {
                        this.TextStore.OnSelectionChange();
                    }
                    if (this.ImmComposition != null) 
                    {
                        this.ImmComposition.OnSelectionChange(); 
                    } 
                }
 
                _IsChanged = value;
            }
        }
 
        /// 
        ///  
        void ITextRange.NotifyChanged(bool disableScroll, bool skipEvents) 
        {
            // Notify text store about selection movement. 
            if (this.TextStore != null)
            {
                this.TextStore.OnSelectionChanged();
            } 
            // Notify ImmComposition about selection movement.
            if (this.ImmComposition != null) 
            { 
                this.ImmComposition.OnSelectionChanged();
            } 

            if (!skipEvents)
            {
                TextRangeBase.NotifyChanged(this, disableScroll); 
            }
 
            if (!disableScroll) 
            {
                // Force a synchronous layout update.  If the update was big enough, background layout 
                // kicked in and the caret won't otherwise be updated.  Note this will block the thread
                // while layout runs.
                //
                // It's possible an application repositioned the caret 
                // while listening to a change event just raised, but in that case the following
                // code should be harmless. 
                ITextPointer movingPosition = ((ITextSelection)this).MovingPosition; 
                if (this.TextView != null && this.TextView.IsValid &&
                    !this.TextView.Contains(movingPosition)) 
                {
                    movingPosition.ValidateLayout();
                }
                // If layout wasn't valid, then there's a pending caret update 
                // that will proceed correctly now.  Otherwise the whole operation
                // is a nop. 
            } 

            // Fixup the caret. 
            UpdateCaretState(disableScroll ? CaretScrollMethod.None : CaretScrollMethod.Simple);
        }

        //----------------------------------------------------- 
        //
        //  ITextRange Properties 
        // 
        //------------------------------------------------------
 
        //......................................................
        //
        //  Content - rich and plain
        // 
        //......................................................
 
        ///  
        /// 
        ///  
        string ITextRange.Text
        {
            get
            { 
                return TextRangeBase.GetText(this);
            } 
 
            set
            { 
                TextRangeBase.BeginChange(this);
                try
                {
                    TextRangeBase.SetText(this, value); 

                    if (this.IsEmpty) 
                    { 
                        // We need to ensure appropriate caret visual position.
                        ((ITextSelection)this).SetCaretToPosition(((ITextRange)this).End, LogicalDirection.Forward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/false); 
                    }

                    Invariant.Assert(!this.IsTableCellRange);
                    SetActivePositions(((ITextRange)this).Start, ((ITextRange)this).End); 
                }
                finally 
                { 
                    TextRangeBase.EndChange(this);
                } 
            }
        }

        #endregion ITextRange Implementation 

        //------------------------------------------------------ 
        // 
        // ITextSelection implementation
        // 
        //-----------------------------------------------------

        #region ITextSelection Implementation
 
        void ITextSelection.UpdateCaretAndHighlight()
        { 
            if (this.UiScope.IsEnabled && this.TextView != null && this.UiScope.IsKeyboardFocused) 
            {
                // Update the TLS first, so that EnsureCaret is working in 
                // the correct context.
                SetThreadSelection();

                // Make caret visible and blinking 
                EnsureCaret(/*isBlinkEnabled:*/true, CaretScrollMethod.None);
                // Highlight selection 
                Highlight(); 
            }
            else if (this.UiScope.IsEnabled && this.TextView != null && 
             this.UiScope.IsFocused && IsRootElement(FocusManager.GetFocusScope(this.UiScope)) &&
             (IsFocusWithinRoot() ||                   // either UiScope root window has keyboard focus
             _textEditor.IsContextMenuOpen))          // or UiScope has a context menu open
            { 
                // Update the TLS first, so that EnsureCaret is working in
                // the correct context. 
                SetThreadSelection(); 

                // just stop the caret from blinking 
                EnsureCaret(/*isBlinkEnabled:*/false, CaretScrollMethod.None);
                // Highlight selection
                Highlight();
            } 
            else
            { 
                // Update the TLS first, so that the caret is working in 
                // the correct context.
                ClearThreadSelection(); 

                // delete the caret
                DetachCaretFromVisualTree();
                // Remove highlight 
                Unhighlight();
            } 
        } 

        ///  
        /// 
        ITextPointer ITextSelection.AnchorPosition
        {
            get 
            {
                Invariant.Assert(this.IsEmpty || _anchorPosition != null); 
                Invariant.Assert(_anchorPosition == null || _anchorPosition.IsFrozen); 
                return this.IsEmpty ? ((ITextSelection)this).Start : _anchorPosition;
            } 
        }

        /// 
        /// The position within this selection that responds to user input. 
        /// 
        ITextPointer ITextSelection.MovingPosition 
        { 
            get
            { 
                ITextSelection thisSelection = this;
                ITextPointer movingPosition;

                if (this.IsEmpty) 
                {
                    movingPosition = thisSelection.Start; 
                } 
                else
                { 
                    switch (_movingPositionEdge)
                    {
                        case MovingEdge.Start:
                            movingPosition = thisSelection.Start; 
                            break;
 
                        case MovingEdge.StartInner: 
                            movingPosition = thisSelection.TextSegments[0].End;
                            break; 

                        case MovingEdge.EndInner:
                            movingPosition = thisSelection.TextSegments[thisSelection.TextSegments.Count - 1].Start;
                            break; 

                        case MovingEdge.End: 
                            movingPosition = thisSelection.End; 
                            break;
 
                        case MovingEdge.None:
                        default:
                            Invariant.Assert(false, "MovingEdge should never be None with non-empty TextSelection!");
                            movingPosition = null; 
                            break;
                    } 
 
                    movingPosition = movingPosition.GetFrozenPointer(_movingPositionDirection);
                } 

                return movingPosition;
            }
        } 

        ///  
        ///  
        void ITextSelection.SetCaretToPosition(ITextPointer caretPosition, LogicalDirection direction, bool allowStopAtLineEnd, bool allowStopNearSpace)
        { 
            // We need a pointer with appropriate direction,
            // becasue it will be used in textRangeBase.Select method for
            // pointer normalization.
            caretPosition = caretPosition.CreatePointer(direction); 

            // Normalize the position in its logical direction - to get to text content over there. 
            caretPosition.MoveToInsertionPosition(direction); 

            // We need a pointer with the reverse direction to confirm 
            // the line wrapping position. So we can ensure Bidi caret navigation.
            // Bidi can have the different caret position by setting the
            // logical direction, so we have to only set the logical direction
            // as the forward for the real line wrapping position. 
            ITextPointer reversePosition = caretPosition.CreatePointer(direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward);
 
            // Check line wrapping condition 
            if (!allowStopAtLineEnd &&
                ((TextPointerBase.IsAtLineWrappingPosition(caretPosition, this.TextView) && 
                  TextPointerBase.IsAtLineWrappingPosition(reversePosition, this.TextView)) ||
                 TextPointerBase.IsNextToPlainLineBreak(caretPosition, LogicalDirection.Backward) ||
                 TextSchema.IsBreak(caretPosition.GetElementType(LogicalDirection.Backward))))
            { 
                // Caret is at wrapping position, and we are not allowed to stay at end of line,
                // so we choose forward direction to appear in the begiinning of a second line 
                caretPosition.SetLogicalDirection(LogicalDirection.Forward); 
            }
            else 
            {
                if (caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text &&
                    caretPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                { 
                    // This is statistically most typical case. No "smartness" needed
                    // to choose standard Forward orientation for the caret. 
                    // NOTE: By using caretPosition's direction we solve BiDi caret orientation case: 
                    // The orietnation reflects a direction from where caret has been moved
                    // or orientation where mouse clicked. So we will stick with appropriate 
                    // character.

                    // Nothing to do. The caretPosition is good to go.
                } 
                else if (!allowStopNearSpace)
                { 
                    // There are some tags around, and we are not allowed to choose a side near to space. 
                    // So we need to perform some content analysis.
 
                    char[] charBuffer = new char[1];

                    if (caretPosition.GetPointerContext(direction) == TextPointerContext.Text &&
                        caretPosition.GetTextInRun(direction, charBuffer, 0, 1) == 1 && 
                        Char.IsWhiteSpace(charBuffer[0]))
                    { 
                        LogicalDirection oppositeDirection = direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward; 

                        // Check formatting switch condition at this position 
                        FlowDirection initialFlowDirection = (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty);

                        bool moved = caretPosition.MoveToInsertionPosition(oppositeDirection);
 
                        if (moved &&
                            initialFlowDirection == (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty) && 
                            (caretPosition.GetPointerContext(oppositeDirection) != TextPointerContext.Text || 
                             caretPosition.GetTextInRun(oppositeDirection, charBuffer, 0, 1) != 1 ||
                             !Char.IsWhiteSpace(charBuffer[0]))) 
                        {
                            // In the opposite direction we have a non-space
                            // character. So we choose that direction
                            direction = oppositeDirection; 
                            caretPosition.SetLogicalDirection(direction);
                        } 
                    } 
                }
            } 

            // Now that orientation of a caretPosition is identified,
            // build an empty selection at this position
            TextRangeBase.BeginChange(this); 
            try
            { 
                TextRangeBase.Select(this, caretPosition, caretPosition); 

                // Note how Select method works for the case of empty range: 
                // It creates a single instance TextPointer normalized and oriented
                // in a direction taken from caretPosition:
                ITextSelection thisSelection = this;
                Invariant.Assert(thisSelection.Start.LogicalDirection == caretPosition.LogicalDirection); // orientation must be as passed 
                Invariant.Assert(this.IsEmpty);
                //Invariant.Assert((object)thisSelection.Start == (object)thisSelection.End); // it must be the same instance of TextPointer 
                //Invariant.Assert(TextPointerBase.IsAtInsertionPosition(thisSelection.Start, caretPosition.LogicalDirection)); // normalization must be done in the same diredction as orientation 

                // Clear active positions when selection is empty 
                SetActivePositions(null, null);
            }
            finally
            { 
                TextRangeBase.EndChange(this);
            } 
        } 

        //...................................................... 
        //
        //  Extending via movingEnd movements
        //
        //...................................................... 

        // Worker for ExtendToPosition, handles all ITextContainers. 
        void ITextSelection.ExtendToPosition(ITextPointer position) 
        {
            TextRangeBase.BeginChange(this); 
            try
            {
                ITextSelection thisSelection = (ITextSelection)this;
 
                // Store initial anchor position
                ITextPointer anchorPosition = thisSelection.AnchorPosition; 
 
                //Build new selection
                TextRangeBase.Select(thisSelection, anchorPosition, position); 

                // Store active positions.
                SetActivePositions(anchorPosition, position);
            } 
            finally
            { 
                TextRangeBase.EndChange(this); 
            }
        } 

        // Worker for ExtendToNextInsertionPosition, handles all ITextContainers.
        bool ITextSelection.ExtendToNextInsertionPosition(LogicalDirection direction)
        { 
            bool moved = false;
 
            TextRangeBase.BeginChange(this); 
            try
            { 
                ITextPointer anchorPosition = ((ITextSelection)this).AnchorPosition;
                ITextPointer movingPosition = ((ITextSelection)this).MovingPosition;
                ITextPointer newMovingPosition;
 
                if (this.IsTableCellRange)
                { 
                    // Both moving and anchor positions are within a single Table, in seperate 
                    // cells.  Select next cell.
                    newMovingPosition = TextRangeEditTables.GetNextTableCellRangeInsertionPosition(this, direction); 
                }
                else if (movingPosition is TextPointer && TextPointerBase.IsAtRowEnd(movingPosition))
                {
                    // Moving position at at a Table row end, anchor position is outside 
                    // the Table.  Select next row.
                    newMovingPosition = TextRangeEditTables.GetNextRowEndMovingPosition(this, direction); 
                } 
                else if (movingPosition is TextPointer && TextRangeEditTables.MovingPositionCrossesCellBoundary(this))
                { 
                    // Moving position at at a Table row start, anchor position is outside
                    // the Table.  Select next row.
                    newMovingPosition = TextRangeEditTables.GetNextRowStartMovingPosition(this, direction);
                } 
                else
                { 
                    // No Table logic. 
                    newMovingPosition = GetNextTextSegmentInsertionPosition(direction);
                } 

                if (newMovingPosition == null && direction == LogicalDirection.Forward)
                {
                    // When moving forward we cannot find next insertion position, set the end of selection after the last paragraph 
                    // (which is not an insertion position)
                    if (movingPosition.CompareTo(movingPosition.TextContainer.End) != 0) 
                    { 
                        newMovingPosition = movingPosition.TextContainer.End;
                    } 
                }

                // Now that new movingPosition is prepared, build the new selection
                if (newMovingPosition != null) 
                {
                    moved = true; 
 
                    // Re-build a range for the new pair of positions
                    TextRangeBase.Select(this, anchorPosition, newMovingPosition); 

                    // Make sure that active positions are inside of a selection
                    // Set the moving position direction to point toward the inner content.
                    LogicalDirection contentDirection = (anchorPosition.CompareTo(newMovingPosition) <= 0) ? 
                                                 LogicalDirection.Backward : LogicalDirection.Forward;
                    newMovingPosition = newMovingPosition.GetFrozenPointer(contentDirection); 
 
                    SetActivePositions(anchorPosition, newMovingPosition);
                } 
            }
            finally
            {
                TextRangeBase.EndChange(this); 
            }
 
            return moved; 
        }
 
        // Finds new movingPosition for the selection when it is in TextSegment state.
        // Returns null if there is no next insertion position in the requested direction.
        private ITextPointer GetNextTextSegmentInsertionPosition(LogicalDirection direction)
        { 
            ITextSelection thisSelection = (ITextSelection)this;
 
            // Move one over symbol in a given direction 
            return thisSelection.MovingPosition.GetNextInsertionPosition(direction);
        } 

        bool ITextSelection.Contains(Point point)
        {
            ITextSelection thisSelection = (ITextSelection)this; 

            if (thisSelection.IsEmpty) 
            { 
                return false;
            } 

            if (this.TextView == null || !this.TextView.IsValid)
            {
                return false; 
            }
 
            bool contains = false; 

            ITextPointer position = this.TextView.GetTextPositionFromPoint(point, /*snapToText:*/false); 

            // Did we hit any text?
            if (position != null && thisSelection.Contains(position))
            { 
                // If we did, make sure the range covers at least one full character.
                // Check both character edges. 
 
                position = position.GetNextInsertionPosition(position.LogicalDirection);
 
                if (position != null && thisSelection.Contains(position))
                {
                    contains = true;
                } 
            }
 
            // Point snapped to text did not hit anything, but we still have a chance 
            // to hit selection - in inter-paragraph or end-of-paragraph areas - highlighted by selection
            if (!contains) 
            {
                if (_caretElement != null && _caretElement.SelectionGeometry != null &&
                    _caretElement.SelectionGeometry.FillContains(point))
                { 
                    contains = true;
                } 
            } 

            return contains; 
        }

        #region ITextSelection Implementation
 
        //......................................................
        // 
        //  Interaction with Selection host 
        //
        //...................................................... 


        // Called by TextEditor.OnDetach, when the behavior is shut down.
        void ITextSelection.OnDetach() 
        {
            ITextSelection thisSelection = (ITextSelection)this; 
 
            // Check if we need to deactivate the selection
            thisSelection.UpdateCaretAndHighlight(); 

            // Delete highlight layer created for this selection (if any)
            if (_highlightLayer != null && thisSelection.Start.TextContainer.Highlights.GetLayer(typeof(TextSelection)) == _highlightLayer)
            { 
                thisSelection.Start.TextContainer.Highlights.RemoveLayer(_highlightLayer);
            } 
            _highlightLayer = null; 

            // Detach the selection from its editor 
            _textEditor = null;
        }

        // ITextView.Updated event listener. 
        // Called by the TextEditor.
        void ITextSelection.OnTextViewUpdated() 
        { 
            if ((this.UiScope.IsKeyboardFocused || this.UiScope.IsFocused))
            { 
                // Use the locally defined caretElement because _caretElement can be null by
                // detaching CaretElement object
                // Stress bug#1583327 indicate that _caretElement can be set to null by
                // detaching. So the below code is caching the caret element instance locally. 
                CaretElement caretElement = _caretElement;
                if (caretElement != null) 
                { 
                    caretElement.OnTextViewUpdated();
                } 
            }

            if (_pendingUpdateCaretStateCallback)
            { 
                // The TextView calls this method synchronously, before it finishes its Arrange
                // pass, so defer the remaining work until the TextView is valid. 
                Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(UpdateCaretStateWorker), null); 
            }
        } 

        // Perform any cleanup necessary when removing the current UiScope
        // from the visual tree (eg, during a template change).
        void ITextSelection.DetachFromVisualTree() 
        {
            DetachCaretFromVisualTree(); 
        } 

        // Italic command event handler. Called by TextEditor. 
        void ITextSelection.RefreshCaret()
        {
            // Update the caret to show it as italic or normal caret.
            RefreshCaret(_textEditor, _textEditor.Selection); 
        }
 
        // This is called from TextStore when the InterimSelection style of the current selection is changed. 
        void ITextSelection.OnInterimSelectionChanged(bool interimSelection)
        { 
            // Update the caret to show or remove the interim block caret.
            UpdateCaretState(CaretScrollMethod.None);
        }
 
        //......................................................
        // 
        //  Selection Heuristics 
        //
        //...................................................... 


        // Moves the selection to the mouse cursor position.
        // Extends the active end if extend == true, otherwise the selection 
        // is collapsed to a caret.
        void ITextSelection.SetSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint) 
        { 
            ITextSelection thisSelection = (ITextSelection)this;
 
            if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
            {
                // Shift modifier pressed - extending selection from existing one
                thisSelection.ExtendSelectionByMouse(cursorPosition, /*forceWordSelection:*/false, /*forceParagraphSelection*/false); 
            }
            else 
            { 
                // No shift modifier pressed - move selection to a cursor position
                MoveSelectionByMouse(cursorPosition, cursorMousePoint); 
            }
        }

        // Extends the selection to the mouse cursor position. 
        void ITextSelection.ExtendSelectionByMouse(ITextPointer cursorPosition, bool forceWordSelection, bool forceParagraphSelection)
        { 
            ITextSelection thisSelection = (ITextSelection)this; 

            // Check whether the cursor has been actually moved - compare with the previous position 
            if (forceParagraphSelection || _previousCursorPosition != null && cursorPosition.CompareTo(_previousCursorPosition) == 0)
            {
                // Mouse was not actually moved. Ignore the event.
                return; 
            }
 
            thisSelection.BeginChange(); 
            try
            { 
                if (!BeginMouseSelectionProcess(cursorPosition))
                {
                    return;
                } 

                // Get anchor position 
                ITextPointer anchorPosition = ((ITextSelection)this).AnchorPosition; 

                // Identify words on selection ends 
                TextSegment anchorWordRange;
                TextSegment cursorWordRange;
                IdentifyWordsOnSelectionEnds(anchorPosition, cursorPosition, forceWordSelection, out anchorWordRange, out cursorWordRange);
 
                // Calculate selection boundary positions
                ITextPointer startPosition; 
                ITextPointer movingPosition; 
                if (anchorWordRange.Start.CompareTo(cursorWordRange.Start) <= 0)
                { 
                    startPosition = anchorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward);
                    movingPosition = cursorWordRange.End.GetFrozenPointer(LogicalDirection.Backward); ;
                }
                else 
                {
                    startPosition = anchorWordRange.End.GetFrozenPointer(LogicalDirection.Backward); 
                    movingPosition = cursorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward); ; 
                }
 
                // Note that we use includeCellAtMovingPosition=true because we want that hit-tested table cell
                // be included into selection no matter whether it's empty or not.
                TextRangeBase.Select(this, startPosition, movingPosition, /*includeCellAtMovingPosition:*/true);
                SetActivePositions(anchorPosition, movingPosition); 

                // Store previous cursor position - for the next extension event 
                _previousCursorPosition = cursorPosition.CreatePointer(); 

                Invariant.Assert(thisSelection.Contains(thisSelection.AnchorPosition)); 
            }
            finally
            {
                thisSelection.EndChange(); 
            }
        } 
 
        // Part of ExtendSelectionByMouse method:
        // Checks whether selection has been started and initiates selection process 
        // Usually always returns true,
        // returns false only as a special value indicating that we need to return without executing selection expansion code.
        private bool BeginMouseSelectionProcess(ITextPointer cursorPosition)
        { 
            if (_previousCursorPosition == null)
            { 
                // This is a beginning of mouse selection guesture. 
                // Initialize the guesture state
                // initially autoword expansion of both ends is enabled 
                _anchorWordRangeHasBeenCrossedOnce = false;
                _allowWordExpansionOnAnchorEnd = true;
                _reenterPosition = null;
 
                if (this.GetUIElementSelected() != null)
                { 
                    // This means that we have just received mousedown event and selected embedded element in this event. 
                    // MoveMove event is sent immediately, but we don't want to loose UIElement selection,
                    // so we do not extend to the cursorPosition now. 
                    _previousCursorPosition = cursorPosition.CreatePointer();
                    return false;
                }
            } 

            return true; 
        } 

        // Part of ExtendSelectionByMouse method: 
        // Identifies words on selection ends.
        private void IdentifyWordsOnSelectionEnds(ITextPointer anchorPosition, ITextPointer cursorPosition, bool forceWordSelection, out TextSegment anchorWordRange, out TextSegment cursorWordRange)
        {
            if (forceWordSelection) 
            {
                anchorWordRange = TextPointerBase.GetWordRange(anchorPosition); 
                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection); 
            }
            else 
            {
                // Define whether word adjustment is allowed. Pressing Shift+Control prevents from auto-word expansion.
                bool disableWordExpansion = _textEditor.AutoWordSelection == false || ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 && (Keyboard.Modifiers & ModifierKeys.Control) != 0);
 
                if (disableWordExpansion)
                { 
                    anchorWordRange = new TextSegment(anchorPosition, anchorPosition); 
                    cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                } 
                else
                {
                    // Autoword expansion heuristics
                    // ----------------------------- 

                    // Word autoword heuristics: 
                    // a) After active end returned to selected area, autoword expansion on active end is disabled 
                    // b) After active end returned to the very first word, expansion on anchor word is disabled either
                    //    We do this though only if selection has crossed initial word boundary at least once. 
                    // c) After active end crosses new word, autoword expansion of active end is enabled again

                    // Calculate a word range for anchor position
                    anchorWordRange = TextPointerBase.GetWordRange(anchorPosition); 

                    // Check if we re-entering selection or moving outside 
                    // and set autoexpansion flags accordingly 
                    if (_previousCursorPosition != null &&
                        (anchorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(_previousCursorPosition) < 0 || 
                        _previousCursorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(anchorPosition) < 0))
                    {
                        // Re-entering selection.
 
                        // Store position of reentering
                        _reenterPosition = cursorPosition.CreatePointer(); 
 
                        // When re-entering reaches initial word, disable word expansion on anchor end either
                        if (_anchorWordRangeHasBeenCrossedOnce && anchorWordRange.Contains(cursorPosition)) 
                        {
                            _allowWordExpansionOnAnchorEnd = false;
                        }
                    } 
                    else
                    { 
                        // Extending the selection. 

                        // Check if we are crossing a boundary of last reentered word to re-enable word expansion on moving end 
                        if (_reenterPosition != null)
                        {
                            TextSegment lastReenteredWordRange = TextPointerBase.GetWordRange(_reenterPosition);
                            if (!lastReenteredWordRange.Contains(cursorPosition)) 
                            {
                                _reenterPosition = null; 
                            } 
                        }
                    } 

                    // Identify expanded range on both ends
                    //
 
                    if (anchorWordRange.Contains(cursorPosition) ||
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Forward)) || 
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Backward))) 
                    {
                        // Selection does not cross word boundary, so shrink selection to exact anchor/cursor positions 
                        anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                    }
                    else 
                    {
                        // Selection crosses word boundary. 
                        _anchorWordRangeHasBeenCrossedOnce = true; 

                        if (!_allowWordExpansionOnAnchorEnd || // 
                            TextPointerBase.IsAtWordBoundary(anchorPosition, /*insideWordDirection:*/LogicalDirection.Forward))
                        {
                            // We collapse anchorPosition in two cases:
                            // If we have been re-entering the initial word before - 
                            // then we treat it as an indicator that user wants exact position on anchor end
                            // or 
                            // if selection starts exactly on word boundary - 
                            // then we should not include the following word (when selection extends backward).
                            // 
                            // So in the both cases we collapse anchorWordRange to exact _anchorPosition
                            anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        }
 
                        if (TextPointerBase.IsAfterLastParagraph(cursorPosition) ||
                            TextPointerBase.IsAtWordBoundary(cursorPosition, /*insideWordDirection:*/LogicalDirection.Forward)) 
                        { 
                            cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                        } 
                        else
                        {
                            if (_reenterPosition == null)
                            { 
                                // We are not in re-entering mode; expand moving end to word boundary
                                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection); 
                            } 
                            else
                            { 
                                // We are in re-entering mode; use exact moving end position
                                cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                            }
                        } 
                    }
                } 
            } 
        }
 
        //......................................................
        //
        //  Table Selection
        // 
        //......................................................
 
        ///  
        /// Extends table selection by one row in a given direction
        ///  
        /// 
        /// LogicalDirection.Forward means moving active cell one row down,
        /// LogicalDirection.Backward - one row up.
        ///  
        bool ITextSelection.ExtendToNextTableRow(LogicalDirection direction)
        { 
            TableCell anchorCell; 
            TableCell movingCell;
            TableRowGroup rowGroup; 
            int nextRowIndex;
            TableCell nextCell;

            if (!this.IsTableCellRange) 
            {
                return false; 
            } 

            Invariant.Assert(!this.IsEmpty); 
            Invariant.Assert(_anchorPosition != null);
            Invariant.Assert(_movingPositionEdge != MovingEdge.None);

            if (!TextRangeEditTables.IsTableCellRange((TextPointer)_anchorPosition, (TextPointer)((ITextSelection)this).MovingPosition, /*includeCellAtMovingPosition:*/false, out anchorCell, out movingCell)) 
            {
                return false; 
            } 

            Invariant.Assert(anchorCell != null && movingCell != null); 

            rowGroup = movingCell.Row.RowGroup;

            nextCell = null; 

            if (direction == LogicalDirection.Forward) 
            { 
                // Move movingPosition to the following row.
                // Find a row in the forward direction 
                nextRowIndex = movingCell.Row.Index + movingCell.RowSpan;
                if (nextRowIndex < rowGroup.Rows.Count)
                {
                    nextCell = FindCellAtColumnIndex(rowGroup.Rows[nextRowIndex].Cells, movingCell.ColumnIndex); 
                }
            } 
            else 
            {
                // Find preceding row containing a cell in position of movingCell's first column 
                nextRowIndex = movingCell.Row.Index - 1;
                while (nextRowIndex >= 0)
                {
                    nextCell = FindCellAtColumnIndex(rowGroup.Rows[nextRowIndex].Cells, movingCell.ColumnIndex); 
                    if (nextCell != null)
                    { 
                        break; 
                    }
                    nextRowIndex--; 
                }
            }

            if (nextCell != null) 
            {
                // 
                ITextPointer movingPosition = nextCell.ContentEnd.CreatePointer(); 
                movingPosition.MoveToNextInsertionPosition(LogicalDirection.Forward);
 
                TextRangeBase.Select(this, _anchorPosition, movingPosition);

                // Make sure that active positions are inside of a selection
                SetActivePositions(_anchorPosition, movingPosition); 

                return true; 
            } 

            return false; 
        }

        //------------------------------------------------------
        // 
        //  ITextSelection Properties
        // 
        //----------------------------------------------------- 

        // True if the current seleciton is for interim character. 
        // Korean Interim character is now invisilbe selection (no highlight) and the controls needs to
        // have the block caret to indicate the interim character.
        // This should be updated by TextStore.
        internal bool IsInterimSelection 
        {
            get 
            { 
                if (this.TextStore != null)
                { 
                    return TextStore.IsInterimSelection;
                }

                return false; 
            }
        } 
 
        // IsInterimSelection wrapper for ITextSelection.
        bool ITextSelection.IsInterimSelection 
        {
            get
            {
                return this.IsInterimSelection; 
            }
        } 
 
        #endregion ITextSelection Implementation
 

        // *****************************************************
        // *****************************************************
        // ****************************************************** 
        //
        // Concrete TextSelection Implementation 
        // 
        // *****************************************************
        // ****************************************************** 
        // ******************************************************


        //----------------------------------------------------- 
        //
        //  Public Methods 
        // 
        //------------------------------------------------------
 
        //......................................................
        //
        //  Selection extension (moving active end)
        // 
        //......................................................
 
        ///  
        /// Potential public method - concrete equivalent of abstract method
        ///  
        internal TextPointer AnchorPosition
        {
            get
            { 
                // ATTENTION: This method is supposed to be a pure redirection
                // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent 
                return (TextPointer)((ITextSelection)this).AnchorPosition; 
            }
        } 

        /// 
        /// Potential public method - concrete equivalent of abstract method
        ///  
        internal TextPointer MovingPosition
        { 
            get 
            {
                // ATTENTION: This method is supposed to be a pure redirection 
                // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
                return (TextPointer)((ITextSelection)this).MovingPosition;
            }
        } 

        ///  
        /// Potential public method - concrete equivalent of abstract method 
        /// 
        internal void SetCaretToPosition(TextPointer caretPosition, LogicalDirection direction, bool allowStopAtLineEnd, bool allowStopNearSpace) 
        {
            // ATTENTION: This method is supposed to be a pure redirection
            // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
            ((ITextSelection)this).SetCaretToPosition(caretPosition, direction, allowStopAtLineEnd, allowStopNearSpace); 
        }
 
        // 
        internal bool ExtendToNextInsertionPosition(LogicalDirection direction)
        { 
            // ATTENTION: This method is supposed to be a pure redirection
            // to corresponding ITextSelection method - to keep abstract and concrete selection behavior consistent
            return ((ITextSelection)this).ExtendToNextInsertionPosition(direction);
        } 

        #endregion Public Methods 
 
        #region Internal Methods
 
        //-----------------------------------------------------
        //
        //  Internal Methods
        // 
        //-----------------------------------------------------
 
        // InputLanguageChanged event handler. Called by TextEditor. 
        internal static void OnInputLanguageChanged(CultureInfo cultureInfo)
        { 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;

            // Check the changed input language of the cultureInfo to draw the BiDi caret in case of BiDi language
            // like as Arabic or Hebrew input language. 
            if (IsBidiInputLanguage(cultureInfo))
            { 
                threadLocalStore.Bidi = true; 
            }
            else 
            {
                threadLocalStore.Bidi = false;
            }
 
            // Update caret on focused text editor
            if (threadLocalStore.FocusedTextSelection != null) 
            { 
                ((ITextSelection)threadLocalStore.FocusedTextSelection).RefreshCaret();
            } 
        }

        // Returns true if the text matching a pixel position falls within
        // the selection. 
        internal bool Contains(Point point)
        { 
            return ((ITextSelection)this).Contains(point); 
        }
 
        //-----------------------------------------------------
        //
        // Internal Virtual Methods - TextSelection Extensibility
        // 
        //------------------------------------------------------
 
        //...................................................... 
        //
        //  Formatting 
        //
        //......................................................

        ///  
        ///  Append an object at the end of the TextRange.
        ///  
        internal override void InsertEmbeddedUIElementVirtual(FrameworkElement embeddedElement) 
        {
            TextRangeBase.BeginChange(this); 
            try
            {
                base.InsertEmbeddedUIElementVirtual(embeddedElement);
 
                this.ClearSpringloadFormatting();
            } 
            finally 
            {
                TextRangeBase.EndChange(this); 
            }
        }

        ///  
        /// Applies a property value to a selection.
        /// In case of empty selection sets property to springloaded property set. 
        ///  
        internal override void ApplyPropertyToTextVirtual(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction)
        { 
            if (!TextSchema.IsParagraphProperty(formattingProperty) && !TextSchema.IsCharacterProperty(formattingProperty))
            {
                return; // Ignore any unknown property
            } 

            // Check whether we are in a situation when auto-word formatting must happen 
            if (this.IsEmpty && TextSchema.IsCharacterProperty(formattingProperty) && 
                !applyToParagraphs &&
                formattingProperty != FrameworkElement.FlowDirectionProperty) // We dont want to apply flowdirection property to inlines when selection is empty. 
            {
                TextSegment autoWordRange = TextRangeBase.GetAutoWord(this);
                if (autoWordRange.IsNull)
                { 
                    // This property goes to springload formatting. We should not create undo unit for it.
                    if (_springloadFormatting == null) 
                    { 
                        _springloadFormatting = new DependencyObject();
                    } 

                    _springloadFormatting.SetValue(formattingProperty, value);
                }
                else 
                {
                    // TextRange will create undo unit with proper name 
                    new TextRange(autoWordRange.Start, autoWordRange.End).ApplyPropertyValue(formattingProperty, value); 
                }
            } 
            else
            {
                // No word to auto-format. Apply property to a selection.
                // TextRange will create undo unit with proper name 
                base.ApplyPropertyToTextVirtual(formattingProperty, value, applyToParagraphs, propertyValueAction);
                this.ClearSpringloadFormatting(); 
            } 
        }
 
        internal override void ClearAllPropertiesVirtual()
        {
            // Character property - applies to text runs in selected range, or springloaded if selection is empty
            if (this.IsEmpty) 
            {
                this.ClearSpringloadFormatting(); 
            } 
            else
            { 
                TextRangeBase.BeginChange(this);
                try
                {
                    base.ClearAllPropertiesVirtual(); 

                    this.ClearSpringloadFormatting(); 
                } 
                finally
                { 
                    TextRangeBase.EndChange(this);
                }
            }
        } 

        //...................................................... 
        // 
        //  Range Serialization
        // 
        //......................................................

        // Worker for Xml property setter; enables extensibility for TextSelection
        internal override void SetXmlVirtual(TextElement fragment) 
        {
            TextRangeBase.BeginChange(this); 
            try 
            {
                base.SetXmlVirtual(fragment); 

                this.ClearSpringloadFormatting();
            }
            finally 
            {
                TextRangeBase.EndChange(this); 
            } 
        }
 
        // Worker for Load public method; enables extensibility for TextSelection
        internal override void LoadVirtual(Stream stream, string dataFormat)
        {
            TextRangeBase.BeginChange(this); 
            try
            { 
                base.LoadVirtual(stream, dataFormat); 

                this.ClearSpringloadFormatting(); 
            }
            finally
            {
                TextRangeBase.EndChange(this); 
            }
        } 
 
        //......................................................
        // 
        //  Table Editing
        //
        //......................................................
 
        // Worker for InsertTable; enables extensibility for TextSelection
        internal override Table InsertTableVirtual(int rowCount, int columnCount) 
        { 
            using (DeclareChangeBlock())
            { 
                Table table = base.InsertTableVirtual(rowCount, columnCount);

                if (table != null)
                { 
                    TextPointer cellStart = table.RowGroups[0].Rows[0].Cells[0].ContentStart;
 
                    this.SetCaretToPosition(cellStart, LogicalDirection.Backward, /*allowStopAtLineEnd:*/false, /*allowStopNearSpace:*/false); 
                }
 
                return table;
            }
        }
 
        // ..............................................................
        // 
        // Springload Formatting 
        //
        // .............................................................. 

        #region Springload Formatting

        ///  
        /// Function used in OnApplyProperty commands for character formatting properties.
        /// It takes care of springload formatting (applied to empty selection). 
        ///  
        /// 
        /// Property whose value is subject to be toggled. 
        /// 
        /// 
        /// The value of a property
        ///  
        internal object GetCurrentValue(DependencyProperty formattingProperty)
        { 
            ITextSelection thisSelection = this; 
            object propertyValue = DependencyProperty.UnsetValue;
 
            if (thisSelection.Start is TextPointer)
            {
                if (_springloadFormatting != null && this.IsEmpty)
                { 
                    // Get springload value
                    propertyValue = _springloadFormatting.ReadLocalValue(formattingProperty); 
                    if (propertyValue == DependencyProperty.UnsetValue) 
                    {
                        propertyValue = this.Start.Parent.GetValue(formattingProperty); 
                    }
                }
            }
 
            // If there's no spring loaded value, read the local value.
            if (propertyValue == DependencyProperty.UnsetValue) 
            { 
                propertyValue = this.PropertyPosition.GetValue(formattingProperty);
            } 

            return propertyValue;
        }
 
        /// 
        /// Reads a set of current formatting properties (from selection start) 
        /// into _springloadFormatting - to apply potentially for the following input. 
        /// 
        internal void SpringloadCurrentFormatting() 
        {
            if (((ITextSelection)this).Start is TextPointer)
            {
                TextPointer start = this.Start; 

                Inline ancestor = start.GetNonMergeableInlineAncestor(); 
                if (ancestor != null) 
                {
                    // Unless the selection is wholly contained within a Hyperlink, we don't 
                    // want to springload its character properties.
                    if (this.End.GetNonMergeableInlineAncestor() != ancestor)
                    {
                        start = ancestor.ElementEnd; 
                    }
                } 
 
                if (_springloadFormatting == null)
                { 
                    SpringloadCurrentFormatting(start.Parent);
                }
            }
        } 

        private void SpringloadCurrentFormatting(DependencyObject parent) 
        { 
            // Create new bag for formatting properties
            _springloadFormatting = new DependencyObject(); 

            // Check if we have an object to read from
            if (parent == null)
            { 
                return;
            } 
 
            DependencyProperty[] inheritableProperties = TextSchema.GetInheritableProperties(typeof(Inline));
            DependencyProperty[] noninheritableProperties = TextSchema.GetNoninheritableProperties(typeof(Span)); 

            // Walk up the tree.  At each step, if the element is typographical only,
            // grab all non-inherited values.  When we reach the top of the tree, grab all
            // values. 
            DependencyObject element = parent;
            while (element is Inline) 
            { 
                TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(element.GetType(), typeof(TextElementEditingBehaviorAttribute));
                if (att.IsTypographicOnly) 
                {
                    for (int i = 0; i < inheritableProperties.Length; i++)
                    {
                        if (_springloadFormatting.ReadLocalValue(inheritableProperties[i]) == DependencyProperty.UnsetValue && 
                            inheritableProperties[i] != FrameworkElement.LanguageProperty &&
                            inheritableProperties[i] != FrameworkElement.FlowDirectionProperty && 
                            System.Windows.DependencyPropertyHelper.GetValueSource(element, inheritableProperties[i]).BaseValueSource != BaseValueSource.Inherited) 
                        {
                            object value = parent.GetValue(inheritableProperties[i]); 
                            _springloadFormatting.SetValue(inheritableProperties[i], value);
                        }
                    }
                    for (int i = 0; i < noninheritableProperties.Length; i++) 
                    {
                        if (_springloadFormatting.ReadLocalValue(noninheritableProperties[i]) == DependencyProperty.UnsetValue && 
                            noninheritableProperties[i] != TextElement.TextEffectsProperty && 
                            System.Windows.DependencyPropertyHelper.GetValueSource(element, noninheritableProperties[i]).BaseValueSource != BaseValueSource.Inherited)
                        { 
                            object value = parent.GetValue(noninheritableProperties[i]);
                            _springloadFormatting.SetValue(noninheritableProperties[i], value);
                        }
                    } 
                }
                element = ((TextElement)element).Parent; 
            } 
        }
 
        /// 
        /// Clears springload formatting, so that the following text input
        /// will use formatting from a current position.
        ///  
        internal void ClearSpringloadFormatting()
        { 
            if (((ITextSelection)this).Start is TextPointer) 
            {
                // Delete all springloaded values 
                _springloadFormatting = null;

                // Update caret italic state
                ((ITextSelection)this).RefreshCaret(); 
            }
        } 
 
        /// 
        /// Applies springload formatting to a given content range. 
        /// Clears springloadFormatting after applying it.
        /// 
        internal void ApplySpringloadFormatting()
        { 
            if (!(((ITextSelection)this).Start is TextPointer))
            { 
                return; 
            }
 
            if (this.IsEmpty)
            {
                // We can't apply formatting to non-TextContainers or empty selection.
                return; 
            }
 
            if (_springloadFormatting != null) 
            {
                Invariant.Assert(this.Start.LogicalDirection == LogicalDirection.Backward); 
                Invariant.Assert(this.End.LogicalDirection == LogicalDirection.Forward);

                LocalValueEnumerator springloadFormattingValues = _springloadFormatting.GetLocalValueEnumerator();
 
                while (!this.IsEmpty && springloadFormattingValues.MoveNext())
                { 
                    // Note: we repeatedly check for IsEmpty because the selection 
                    // may become empty as a result of normalization after formatting
                    // (thai character sequence). 
                    LocalValueEntry propertyEntry = springloadFormattingValues.Current;
                    Invariant.Assert(TextSchema.IsCharacterProperty(propertyEntry.Property));
                    base.ApplyPropertyValue(propertyEntry.Property, propertyEntry.Value);
                } 

                ClearSpringloadFormatting(); 
            } 
        }
 
        #endregion Springload Formatting

        #region Caret Support
 
        // ..............................................................
        // 
        // Caret Support 
        //
        // .............................................................. 

        // Shows/hides the caret and scrolls it into view if requested.
        // Called when the range is moved or layout is updated.
        internal void UpdateCaretState(CaretScrollMethod caretScrollMethod) 
        {
            Invariant.Assert(caretScrollMethod != CaretScrollMethod.Unset); 
 
            if (_pendingCaretNavigation)
            { 
                caretScrollMethod = CaretScrollMethod.Navigation;
                _pendingCaretNavigation = false;
            }
 
            if (_caretScrollMethod == CaretScrollMethod.Unset)
            { 
                _caretScrollMethod = caretScrollMethod; 

                // Post a "Loaded" priority operation to the dispatcher queue. 

                // Operations at Loaded priority are processed when layout and render is
                // done but just before items at input priority are serviced.
                // We want the update caret worker to run after layout is clean. 
                if (_textEditor.TextView != null && _textEditor.TextView.IsValid)
                { 
                    UpdateCaretStateWorker(null); 
                }
                else 
                {
                    _pendingUpdateCaretStateCallback = true;
                }
            } 
            else if (caretScrollMethod != CaretScrollMethod.None)
            { 
                _caretScrollMethod = caretScrollMethod; 
            }
        } 

        // Get the caret brush that is the inverted color from the system window or background color.
        internal static Brush GetCaretBrush(TextEditor textEditor)
        { 
            Color backgroundColor;
            ITextSelection focusedTextSelection; 
            object backgroundPropertyValue; 

            // If TextBoxBase.CaretBrush has been set, use that instead of the default inverting behavior. 
            Brush caretBrush = (Brush)textEditor.UiScope.GetValue(TextBoxBase.CaretBrushProperty);
            if (caretBrush != null)
            {
                return caretBrush; 
            }
 
            // Get the default background from the system color or UiScope's background 
            backgroundPropertyValue = textEditor.UiScope.GetValue(System.Windows.Controls.Panel.BackgroundProperty);
            if (backgroundPropertyValue != null && backgroundPropertyValue != DependencyProperty.UnsetValue && 
                backgroundPropertyValue is SolidColorBrush)
            {
                backgroundColor = ((SolidColorBrush)backgroundPropertyValue).Color;
            } 
            else
            { 
                backgroundColor = SystemColors.WindowColor; 
            }
 
            // Get the background color from current selection
            focusedTextSelection = textEditor.Selection;
            if (focusedTextSelection is TextSelection)
            { 
                backgroundPropertyValue = ((TextSelection)focusedTextSelection).GetCurrentValue(TextElement.BackgroundProperty);
                if (backgroundPropertyValue != null && backgroundPropertyValue != DependencyProperty.UnsetValue) 
                { 
                    if (backgroundPropertyValue is SolidColorBrush)
                    { 
                        backgroundColor = ((SolidColorBrush)backgroundPropertyValue).Color;
                    }
                }
            } 

            // Invert the color to get the caret color from the system window or background color. 
            byte r = (byte)~(backgroundColor.R); 
            byte g = (byte)~(backgroundColor.G);
            byte b = (byte)~(backgroundColor.B); 

            caretBrush = new SolidColorBrush(Color.FromRgb(r, g, b));
            caretBrush.Freeze();
            return caretBrush; 
        }
 
        #endregion Caret Support 

        #region Bidi Support 

        //......................................................
        //
        //  BIDI Support 
        //
        //...................................................... 
 
        /// 
        /// Check the installed bidi input language from the current 
        /// input keyboard list.
        /// 
        /// 
        /// Critical - calls unmanaged code to get the current available keyboard list. 
        /// TreatAsSafe - data exposed (user using bidi) is safe to release
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static bool IsBidiInputLanguageInstalled()
        { 
            bool bidiInputLanguageInstalled;

            bidiInputLanguageInstalled = false;
 
            int keyboardListCount = (int)SafeNativeMethods.GetKeyboardLayoutList(0, null);
            if (keyboardListCount > 0) 
            { 
                int keyboardListIndex;
                IntPtr[] keyboardList; 

                keyboardList = new IntPtr[keyboardListCount];

                keyboardListCount = SafeNativeMethods.GetKeyboardLayoutList(keyboardListCount, keyboardList); 

                for (keyboardListIndex = 0; 
                     (keyboardListIndex < keyboardList.Length) && (keyboardListIndex < keyboardListCount); 
                     keyboardListIndex++)
                { 
                    CultureInfo cultureInfo = new CultureInfo((short)keyboardList[keyboardListIndex]);

                    if (IsBidiInputLanguage(cultureInfo))
                    { 
                        bidiInputLanguageInstalled = true;
                        break; 
                    } 
                }
            } 

            return bidiInputLanguageInstalled;
        }
 
        #endregion Bidi Support
 
        // Forces a synchronous layout validation, up to the selection moving position. 
        void ITextSelection.ValidateLayout()
        { 
            ((ITextSelection)this).MovingPosition.ValidateLayout();
        }

        #endregion Internal methods 

        //----------------------------------------------------- 
        // 
        //  Internal Properties
        // 
        //------------------------------------------------------

        #region Internal Properties
 
        // Caret associated with this TextSelection.
        internal CaretElement CaretElement 
        { 
            get
            { 
                return _caretElement;
            }
        }
 
        // Caret associated with this TextSelection.
        CaretElement ITextSelection.CaretElement 
        { 
            get
            { 
                return this.CaretElement;
            }
        }
 
        // Returns true iff there are no additional insertion positions are either
        // end of the selection. 
        bool ITextSelection.CoversEntireContent 
        {
            get 
            {
                ITextSelection This = this;

                return (This.Start.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text && 
                        This.End.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text &&
                        This.Start.GetNextInsertionPosition(LogicalDirection.Backward) == null && 
                        This.End.GetNextInsertionPosition(LogicalDirection.Forward) == null); 
            }
        } 

        #endregion Internal Properties

        //------------------------------------------------------ 
        //
        //  Private Methods 
        // 
        //-----------------------------------------------------
 
        #region Private Methods

        // Stores this TextSelection into our TLS slot.
        private void SetThreadSelection() 
        {
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; 
 
            // Store this selection as focused one
            threadLocalStore.FocusedTextSelection = this; 
        }

        // Removes this TextSelection from our TLS slot.
        private void ClearThreadSelection() 
        {
            // Clear currently focused selection, if it's us 
            if (TextEditor._ThreadLocalStore.FocusedTextSelection == this) 
            {
                TextEditor._ThreadLocalStore.FocusedTextSelection = null; 
            }
        }

        // GotKeyboardFocus event handler.  Called by UpdateCaretAndHighlight. 
        private void Highlight()
        { 
            ITextContainer textContainer = ((ITextSelection)this).Start.TextContainer; 

            // Only fixed documents use the highlight layer for selection. In all other cases, 
            // selection is rendered on the adorner layer. Since we split up individual runs
            // fed in to TextFormatter at highlight boundaries, using the highlight layer for
            // selection can affect measure.
            if (textContainer is TextContainer || textContainer is PasswordTextContainer) 
            {
                return; 
            } 

            // Make sure that a highlight layer exists for drawing this selection 
            if (_highlightLayer == null)
            {
                _highlightLayer = new TextSelectionHighlightLayer(this);
            } 

            // Make selection visible 
            if (textContainer.Highlights.GetLayer(typeof(TextSelection)) == null) 
            {
                textContainer.Highlights.AddLayer(_highlightLayer); 
            }
        }

        // LostKeyboardFocus event handler.  Called by UpdateCaretAndHighlight. 
        private void Unhighlight()
        { 
            ITextContainer textContainer = ((ITextSelection)this).Start.TextContainer; 
            TextSelectionHighlightLayer highlightLayer = textContainer.Highlights.GetLayer(typeof(TextSelection)) as TextSelectionHighlightLayer;
            if (highlightLayer != null) 
            {
                textContainer.Highlights.RemoveLayer(highlightLayer);
                Invariant.Assert(textContainer.Highlights.GetLayer(typeof(TextSelection)) == null);
            } 
        }
 
        //...................................................... 
        //
        //  Active Positions of Selection 
        //
        //......................................................

        ///  
        /// Stores normalized anchor and moving positions for the selection.
        /// Ensures that they are both inside of range Start/End. 
        ///  
        /// 
        /// A position which must be stored as initial position for the selection. 
        /// 
        /// 
        /// The "hot" or active selection edge which responds to user input.
        ///  
        private void SetActivePositions(ITextPointer anchorPosition, ITextPointer movingPosition)
        { 
            // The following settings are used in auto-word exapnsion. 
            // By setting a _previousPosition we are clearing them all -
            // they will be re-initialized in the beginning of a selection 
            // expansion guesture in ExtendSelectionByMouse method
            // Previous position is needed for selection gestures to remember
            // where mouse drag happed last time. Used for word autoexpansion.
            _previousCursorPosition = null; 

            if (this.IsEmpty) 
            { 
                _anchorPosition = null;
                _movingPositionEdge = MovingEdge.None; 
                return;
            }

            Invariant.Assert(anchorPosition != null); 

            ITextSelection thisSelection = (ITextSelection)this; 
 
            // Normalize and store new selection anchor position
            _anchorPosition = anchorPosition.GetInsertionPosition(anchorPosition.LogicalDirection); 

            // Ensure that anchor position is within one of text segments
            if (_anchorPosition.CompareTo(thisSelection.Start) < 0)
            { 
                _anchorPosition = thisSelection.Start.GetFrozenPointer(_anchorPosition.LogicalDirection);
            } 
            else if (_anchorPosition.CompareTo(thisSelection.End) > 0) 
            {
                _anchorPosition = thisSelection.End.GetFrozenPointer(_anchorPosition.LogicalDirection); 
            }

            _movingPositionEdge = ConvertToMovingEdge(anchorPosition, movingPosition);
            _movingPositionDirection = movingPosition.LogicalDirection; 
        }
 
        // Uses the current selection state to match an ITextPointer to one of the possible 
        // moving position edges.
        private MovingEdge ConvertToMovingEdge(ITextPointer anchorPosition, ITextPointer movingPosition) 
        {
            ITextSelection thisSelection = this;
            MovingEdge movingEdge;
 
            if (thisSelection.IsEmpty)
            { 
                // Empty selections have no moving edge. 
                movingEdge = MovingEdge.None;
            } 
            else if (thisSelection.TextSegments.Count < 2)
            {
                // Simple text selections move opposite their anchor positions.
                movingEdge = (anchorPosition.CompareTo(movingPosition) <= 0) ? MovingEdge.End : MovingEdge.Start; 
            }
            else 
            { 
                // Table selection.  Look for an exact match.
                if (movingPosition.CompareTo(thisSelection.Start) == 0) 
                {
                    movingEdge = MovingEdge.Start;
                }
                else if (movingPosition.CompareTo(thisSelection.End) == 0) 
                {
                    movingEdge = MovingEdge.End; 
                } 
                else if (movingPosition.CompareTo(thisSelection.TextSegments[0].End) == 0)
                { 
                    movingEdge = MovingEdge.StartInner;
                }
                else if (movingPosition.CompareTo(thisSelection.TextSegments[thisSelection.TextSegments.Count-1].Start) == 0)
                { 
                    movingEdge = MovingEdge.EndInner;
                } 
                else 
                {
                    movingEdge = (anchorPosition.CompareTo(movingPosition) <= 0) ? MovingEdge.End : MovingEdge.Start; 
                }
            }

            return movingEdge; 
        }
 
        //...................................................... 
        //
        //  Selection Building With Mouse 
        //
        //......................................................

        // Moves the selection to the mouse cursor position. 
        // If the cursor is facing a UIElement, select the UIElement.
        // Sets new selection anchor to a given cursorPosition. 
        private void MoveSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint) 
        {
            ITextSelection thisSelection = (ITextSelection)this; 

            if (this.TextView == null)
            {
                return; 
            }
            Invariant.Assert(this.TextView.IsValid); // We just checked RenderScope. We'll use TextView below 
 
            ITextPointer movingPosition = null;
 
            if (cursorPosition.GetPointerContext(cursorPosition.LogicalDirection) == TextPointerContext.EmbeddedElement)
            {
                Rect objectEdgeRect = this.TextView.GetRectangleFromTextPosition(cursorPosition);
 
                // Check for embedded object.
                // If the click happend inside of it we need to select it as a whole, when content is not read-only. 
                if (!_textEditor.IsReadOnly && ShouldSelectEmbeddedObject(cursorPosition, cursorMousePoint, objectEdgeRect)) 
                {
                    movingPosition = cursorPosition.GetNextContextPosition(cursorPosition.LogicalDirection); 
                }
            }

            // Move selection to this position 
            if (movingPosition == null)
            { 
                thisSelection.SetCaretToPosition(cursorPosition, cursorPosition.LogicalDirection, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/false); 
            }
            else 
            {
                thisSelection.Select(cursorPosition, movingPosition);
            }
        } 

        // Helper for MoveSelectionByMouse 
        private bool ShouldSelectEmbeddedObject(ITextPointer cursorPosition, Point cursorMousePoint, Rect objectEdgeRect) 
        {
            // Although we now know that cursorPosition is facing an embedded object, 
            // we still need an additional test to determine if the original mouse point
            // fell within the object or outside it's bouding box (which can happen when
            // a mouse click is snapped to the nearest content).
            // If the mouse point is outside the object, we don't want to select it. 
            if (!objectEdgeRect.IsEmpty &&
                cursorMousePoint.Y >= objectEdgeRect.Y && cursorMousePoint.Y < objectEdgeRect.Y + objectEdgeRect.Height) 
            { 
                // Compare X coordinates of mouse down point and object edge rect,
                // depending on the FlowDirection of the render scope and paragraph content. 

                FlowDirection renderScopeFlowDirection = (FlowDirection)this.TextView.RenderScope.GetValue(Block.FlowDirectionProperty);
                FlowDirection paragraphFlowDirection = (FlowDirection)cursorPosition.GetValue(Block.FlowDirectionProperty);
 
                if (renderScopeFlowDirection == FlowDirection.LeftToRight)
                { 
                    if (paragraphFlowDirection == FlowDirection.LeftToRight && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X < cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X < objectEdgeRect.X)) 
                    {
                        return true;
                    }
                    else if (paragraphFlowDirection == FlowDirection.RightToLeft && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X > cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X > objectEdgeRect.X)) 
                    { 
                        return true;
                    } 
                }
                else
                {
                    if (paragraphFlowDirection == FlowDirection.LeftToRight && 
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X > cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X > objectEdgeRect.X)) 
                    { 
                        return true;
                    } 
                    else if (paragraphFlowDirection == FlowDirection.RightToLeft &&
                        (cursorPosition.LogicalDirection == LogicalDirection.Forward && objectEdgeRect.X < cursorMousePoint.X ||
                        cursorPosition.LogicalDirection == LogicalDirection.Backward && cursorMousePoint.X < objectEdgeRect.X))
                    { 
                        return true;
                    } 
                } 
            }
 
            return false;
        }

        //...................................................... 
        //
        //  Caret Support 
        // 
        //......................................................
 
        // Redraws a caret using current setting for italic - taking springload formatting into account.
        private static void RefreshCaret(TextEditor textEditor, ITextSelection textSelection)
        {
            object fontStylePropertyValue; 
            bool italic;
 
            if (textSelection == null || textSelection.CaretElement == null) 
            {
                return; 
            }

            // NOTE: We are using GetCurrentValue to take springload formatting into account.
            fontStylePropertyValue = ((TextSelection)textSelection).GetCurrentValue(TextElement.FontStyleProperty); 
            italic = (textEditor.AcceptsRichContent && fontStylePropertyValue != DependencyProperty.UnsetValue && (FontStyle)fontStylePropertyValue == FontStyles.Italic);
 
            textSelection.CaretElement.RefreshCaret(italic); 
        }
 
        // Called after a caret navigation, to signal that the next caret
        // scroll-into-view should include hueristics to include following
        // text.
        internal void OnCaretNavigation() 
        {
            _pendingCaretNavigation = true; 
        } 

        // Called after a caret navigation, to signal that the next caret 
        // scroll-into-view should include hueristics to include following
        // text.
        void ITextSelection.OnCaretNavigation()
        { 
            OnCaretNavigation();
        } 
 
        // Callback for UpdateCaretState worker.
        private object UpdateCaretStateWorker(object o) 
        {
            _pendingUpdateCaretStateCallback = false;

            // This can happen if selection has been detached by TextEditor.OnDetach. 
            if (_textEditor == null)
            { 
                return null; 
            }
 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;

            CaretScrollMethod caretScrollMethod = _caretScrollMethod;
            _caretScrollMethod = CaretScrollMethod.Unset; 

            // Use the locally defined caretElement because _caretElement can be null by 
            // detaching CaretElement object 
            CaretElement caretElement = _caretElement;
 
            if (caretElement == null)
            {
                return null;
            } 

            if (threadLocalStore.FocusedTextSelection == null) 
            { 
                // If we have multiple windows open, a non-blinking caret might be showing
                // in the given TextEditor's UiScope.  If the selection for that Editor is 
                // not empty, we need to hide the caret.
                if (!this.IsEmpty)
                {
                    caretElement.Hide(); 
                }
 
                return null; 
            }
 
            // When the TextView is not valid, there is nothing to do
            if (_textEditor.TextView == null || !_textEditor.TextView.IsValid)
            {
                // 
                return null;
            } 
 
            if (!this.VerifyAdornerLayerExists())
            { 
                caretElement.Hide();
            }

            // Identify caret position 
            // Make sure that moving position is inside of selection
            ITextPointer caretPosition = IdentifyCaretPosition(this); 
 
            // If caret position is not valid in focusedTextSelection.TextView, we cannot update it.
            if (caretPosition.HasValidLayout) 
            {
                Rect caretRectangle;
                bool italic = false;
                bool caretVisible = this.IsEmpty && (!_textEditor.IsReadOnly || _textEditor.IsReadOnlyCaretVisible); 

                if (!this.IsInterimSelection) 
                { 
                    caretRectangle = CalculateCaretRectangle(this, caretPosition);
 
                    if (this.IsEmpty)
                    {
                        // Identify italic condition (including springload) - to use for caret shaping
                        object fontStylePropertyValue = GetPropertyValue(TextElement.FontStyleProperty); 
                        italic = (_textEditor.AcceptsRichContent && fontStylePropertyValue != DependencyProperty.UnsetValue && (FontStyle)fontStylePropertyValue == FontStyles.Italic);
                    } 
                } 
                else
                { 
                    caretRectangle = CalculateInterimCaretRectangle(this);

                    // Caret always visible on the interim input mode.
                    caretVisible = true; 
                }
 
                Brush caretBrush = GetCaretBrush(_textEditor); 

                // Calculate the scroll origin position to scroll it with the caret position. 
                double scrollToOriginPosition = CalculateScrollToOriginPosition(_textEditor, caretPosition, caretRectangle.X);

                // Re-render the caret.
                // Get a bounding rect from the active end of selection. 
                caretElement.Update(caretVisible, caretRectangle, caretBrush, 1.0, italic, caretScrollMethod, scrollToOriginPosition);
            } 
 
            //  CaretElement.Update(...) makes a conditional call to BringIntoView()
            //  on the text view's associated element, which makes the view invalid... 
            if (this.TextView.IsValid && !this.TextView.RendersOwnSelection)
            {
                // Re-render selection. Need to do this to invalidate and update adorner for this caret element.
                caretElement.UpdateSelection(); 
            }
 
            return null; 
        }
 
        // Helper for UpdateCaretState -- identifies caret position from text selection.
        private static ITextPointer IdentifyCaretPosition(ITextSelection currentTextSelection)
        {
            ITextPointer caretPosition = currentTextSelection.MovingPosition; 

            if (!currentTextSelection.IsEmpty) 
            { 
                // Even when we do not draw the blinking caret, we need this position
                // for scrolling caret position into view. 

                // Special case for nonempty selection extended beyond end of line
                if ((caretPosition.LogicalDirection == LogicalDirection.Backward && //
                     caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) || // 
                    TextPointerBase.IsAfterLastParagraph(caretPosition))
                { 
                    // This means that selection has been expanded by ExtendToLineEnd/ExtendToDocumentEnd command. 
                    // TextView in this case cannot give the rect from this position;
                    // we need to move backward to the end of content 
                    caretPosition = caretPosition.CreatePointer();
                    caretPosition.MoveToNextInsertionPosition(LogicalDirection.Backward);
                    caretPosition.SetLogicalDirection(LogicalDirection.Forward);
                } 
            }
 
            // TextView.GetRectangleFromTextPosition returns the end of character rect in case of Backward 
            // logical direction at the start caret position of the docuemtn or paragraph, so we reset the
            // logical direction with Forward to get the right rect of caret at the start position of 
            // document or paragraph.
            if (caretPosition.LogicalDirection == LogicalDirection.Backward && //
                caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart && //
                (caretPosition.GetNextInsertionPosition(LogicalDirection.Backward) == null || // 
                 TextPointerBase.IsNextToAnyBreak(caretPosition, LogicalDirection.Backward)))
            { 
                caretPosition = caretPosition.CreatePointer(); 
                caretPosition.SetLogicalDirection(LogicalDirection.Forward);
            } 

            return caretPosition;
        }
 
        // Helper for UpdateCaretState -- calculates caret rectangle from text selection.
        // regular (non-interim) case of caret positioning 
        private static Rect CalculateCaretRectangle(ITextSelection currentTextSelection, ITextPointer caretPosition) 
        {
            Transform caretTransform; 
            Rect caretRectangle = currentTextSelection.TextView.GetRawRectangleFromTextPosition(caretPosition, out caretTransform);

            if (caretRectangle.IsEmpty)
            { 
                // Caret is not at an insertion position, it has no geometry
                // and will not be displayed. 
                return Rect.Empty; 
            }
 
            // Convert to local coordiantes.
            caretRectangle = caretTransform.TransformBounds(caretRectangle);

            // We will use the system defined caret width later. 
            caretRectangle.Width = 0;
 
            if (currentTextSelection.IsEmpty) 
            {
                // Calculate caret height - from current font size (ignoring a rect returned by TextView, 
                // as it can be a rect of embedded object, which should not affect caret height)
                double fontSize = (double)currentTextSelection.GetPropertyValue(TextElement.FontSizeProperty);
                FontFamily fontFamily = (FontFamily)currentTextSelection.GetPropertyValue(TextElement.FontFamilyProperty);
                double caretHeight = fontFamily.LineSpacing * fontSize; 
                if (caretHeight < caretRectangle.Height)
                { 
                    // Decrease the height of caret to the font height and lower the caret to keep its bottom 
                    // staying on the baseline.
                    caretRectangle.Y += caretRectangle.Height - caretHeight; 
                    caretRectangle.Height = caretHeight;
                }

                if (!caretTransform.IsIdentity) 
                {
                    Point top = new Point(caretRectangle.X, caretRectangle.Y); 
                    Point bottom = new Point(caretRectangle.X, caretRectangle.Y + caretRectangle.Height); 
                    caretTransform.TryTransform(top, out top);
                    caretTransform.TryTransform(bottom, out bottom); 
                    caretRectangle.Y += caretRectangle.Height - Math.Abs(bottom.Y - top.Y);
                    caretRectangle.Height = Math.Abs(bottom.Y - top.Y);
                }
            } 

            return caretRectangle; 
        } 

        // Helper for UpdateCaretState -- handles the korean interim caret. 
        private static Rect CalculateInterimCaretRectangle(ITextSelection focusedTextSelection)
        {
            //
 
            // Get the current flow direction on the selection of interim.
            // This is for getting the right size of distance on the interim character 
            // whatever the current flow direction is. 
            FlowDirection flowDirection = (FlowDirection)focusedTextSelection.Start.GetValue(FrameworkElement.FlowDirectionProperty);
 
            ITextPointer nextCharacterPosition;
            Rect nextCharacterRectangle;
            Rect caretRectangle;
 
            if (flowDirection != FlowDirection.RightToLeft)
            { 
                // Flow direction is Left-to-Right 
                // Get the rectangle for both interim selection start position and the next character
                // position. 
                nextCharacterPosition = focusedTextSelection.Start.CreatePointer(LogicalDirection.Forward);
                caretRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition);

                // Get the next character position from the start position of the interim selection 
                // on the left to right flow direction.
                nextCharacterPosition.MoveToNextInsertionPosition(LogicalDirection.Forward); 
                nextCharacterPosition.SetLogicalDirection(LogicalDirection.Backward); 
                nextCharacterRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition);
            } 
            else
            {
                // Flow direction is Right-to-Left
                // Get the rectangle for both interim selection end position and the next character 
                // position.
                nextCharacterPosition = focusedTextSelection.End.CreatePointer(LogicalDirection.Backward); 
                caretRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition); 

                // Get the next character position from the end position of the interim selection 
                // on the right to left flow direction.
                nextCharacterPosition.MoveToNextInsertionPosition(LogicalDirection.Backward);
                nextCharacterPosition.SetLogicalDirection(LogicalDirection.Forward);
                nextCharacterRectangle = focusedTextSelection.TextView.GetRectangleFromTextPosition(nextCharacterPosition); 
            }
 
            // The interim next character position should be great than the current interim position. 
            // Otherwise, we show the caret as the normal state that use the system caret width.
            // In case of BiDi character, the next character position can be greater than the current position. 
            if (!caretRectangle.IsEmpty && !nextCharacterRectangle.IsEmpty && nextCharacterRectangle.Left > caretRectangle.Left)
            {
                // Get the interim caret width to show the interim block caret.
                caretRectangle.Width = nextCharacterRectangle.Left - caretRectangle.Left; 
            }
 
            return caretRectangle; 
        }
 
        // Helper for UpdateCaretStateWorker -- Calculate the scroll origin position to scroll caret
        // with the scroll origin position so that we can ensure of displaying caret with the wrapped word.
        //
        // There are four cases of different corrdinate by the flow direction on UiScope and Paragraph. 
        // UiScope has two flow direction which is LeftToRightflow directioin and another is RightToLeft.
        // Paragraph has also two flow direction which is LeftToRightflow directioin and another is RightToLeft. 
        // 
        // The below is the example of how horizontal corrdinate and scroll origin value base on the different
        // four cases. So we have to calculate the scroll to origin position base on the case. Simply we can 
        // get the scroll to origin value as zero if UiScope and Paragraph's flow direction is the same.
        // Otherwise, the scroll to origin value is the extent width value that is the max width.
        //
        // <> 
        //  Case 1.
        //      UiScope FlowDirection:              LTR(LeftToRight) 
        //      Paragraph FlowDirection:            LTR(LefTToRight) 
        //          Horizontal origin:              "Left"
        //          Scroll horizontal origin:       "0" 
        //          Wrapping to:                    "Left"
        //              ABC ......
        //              XYZ|
        // 
        //  Case 2.
        //      UiScope FlowDirection:              LTR(LeftToRight) 
        //      Paragraph FlowDirection:            RTL(RightToLeft) 
        //          Horizontal origin:              "Left"
        //          Scroll horizontal origin:       "Max:Extent Width" 
        //          Wrapping to:                    "Right"
        //              ......ABC
        //                    XYZ|
        // 
        //  Case 3.
        //      UiScope FlowDirection:              RTL(RightToLeft) 
        //      Paragraph FlowDirection:            RTL(RightToLeft) 
        //          horizontal origin:              "Right"
        //          Scroll horizontal origin:       "0" 
        //          Wrapping to:                    "Right"
        //              ......ABC
        //                    XYZ|
        // 
        //  Case 4.
        //      UiScope FlowDirection:              RTL(RightToLeft) 
        //      Paragraph FlowDirection:            LTR(LefTToRight) 
        //          horizontal origin:              "Right"
        //          Scroll horizontal origin:       "Max:Extent Width" 
        //          Wrapping to:                    "Left"
        //              ABC ......
        //              XYZ|
        private static double CalculateScrollToOriginPosition(TextEditor textEditor, ITextPointer caretPosition, double horizontalCaretPosition) 
        {
            double scrollToOriginPosition = double.NaN; 
 
            if (textEditor.UiScope is TextBoxBase)
            { 
                double viewportWidth = ((TextBoxBase)textEditor.UiScope).ViewportWidth;
                double extentWidth = ((TextBoxBase)textEditor.UiScope).ExtentWidth;

                // Calculate the scroll to the origin position position when the horizontal scroll is available 
                if (viewportWidth != 0 && extentWidth != 0 && viewportWidth < extentWidth)
                { 
                    bool needScrollToOriginPosition = false; 

                    // Check whether we need to calculate the scroll origin position to scroll it with the caret 
                    // position. If the caret position is out of the current visual viewport area, the scroll
                    // to origin positioin will be calculated to scroll into the origin position first that
                    // ensure of displaying the wrapped word.
                    // 
                    // Note that horizontalCaretPosition is always relative to the viewport, not the document.
                    if (horizontalCaretPosition < 0 || horizontalCaretPosition >= viewportWidth) 
                    { 
                        needScrollToOriginPosition = true;
                    } 

                    if (needScrollToOriginPosition)
                    {
                        // Set the scroll original position as zero 
                        scrollToOriginPosition = 0;
 
                        // Get the flow direction of uiScope 
                        FlowDirection uiScopeflowDirection = (FlowDirection)textEditor.UiScope.GetValue(FrameworkElement.FlowDirectionProperty);
 
                        // Get the flow direction of the current paragraph and compare it with uiScope's flow direction.
                        Block paragraphOrBlockUIContainer = (caretPosition is TextPointer) ? ((TextPointer)caretPosition).ParagraphOrBlockUIContainer : null;
                        if (paragraphOrBlockUIContainer != null)
                        { 
                            FlowDirection pagraphFlowDirection = paragraphOrBlockUIContainer.FlowDirection;
 
                            // If the flow direction is different between uiScopoe and paragaph, 
                            // the original scroll position is the extent width value.
                            if (uiScopeflowDirection != pagraphFlowDirection) 
                            {
                                scrollToOriginPosition = extentWidth;
                            }
                        } 

                        // Adjust scroll position by current viewport offset 
                        scrollToOriginPosition -= ((TextBoxBase)textEditor.UiScope).HorizontalOffset; 
                    }
                } 
            }

            return scrollToOriginPosition;
        } 

        private CaretElement EnsureCaret(bool isBlinkEnabled, CaretScrollMethod scrollMethod) 
        { 
            TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore;
 
            if (_caretElement == null)
            {
                // Create new caret
                _caretElement = new CaretElement(_textEditor, isBlinkEnabled); 

                // Check the current input language to draw the BiDi caret in case of BiDi language 
                // like as Arabic or Hebrew input language. 
                //
                if (IsBidiInputLanguage(InputLanguageManager.Current.CurrentInputLanguage)) 
                {
                    TextEditor._ThreadLocalStore.Bidi = true;
                }
                else 
                {
                    TextEditor._ThreadLocalStore.Bidi = false; 
                } 
            }
            else 
            {
                _caretElement.SetBlinking(isBlinkEnabled);
            }
 
            UpdateCaretState(scrollMethod);
 
            return _caretElement; 
        }
 
        /// 
        /// Walk up the tree from the RenderScope to the UiScope until we find an
        /// AdornerDecorator or ScrollContentPresenter.
        ///  
        /// true if one is found, false otherwise
        private bool VerifyAdornerLayerExists() 
        { 
            DependencyObject element = TextView.RenderScope;
            while (element != _textEditor.UiScope && element != null) 
            {
                if (element is AdornerDecorator || element is System.Windows.Controls.ScrollContentPresenter)
                {
                    return true; 
                }
                element = VisualTreeHelper.GetParent(element); 
            } 
            return false;
        } 

        //......................................................
        //
        //  BIDI Support 
        //
        //...................................................... 
 
        /// 
        /// Check the input language of cultureInfo whether it is the bi-directional language or not. 
        /// 
        /// 
        /// 
        /// Return true if the passed cultureInfo is the bi-directional language like as Arabic or Hebrew. 
        /// Otherwise, return false.
        ///  
        ///  
        /// Critical - calls unmanaged code to check the font signature
        /// TreatAsSafe - data exposed (user using bidi) is safe to release 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private static bool IsBidiInputLanguage(CultureInfo cultureInfo)
        { 
            bool bidiInput;
            string fontSignature; 
 
            bidiInput = false;
 
            fontSignature = new String(new Char[FONTSIGNATURE_SIZE]);

            // Get the font signature to know the current LCID is BiDi(Arabic, Hebrew etc.) or not.
            if (UnsafeNativeMethods.GetLocaleInfoW(cultureInfo.LCID, NativeMethods.LOCALE_FONTSIGNATURE, fontSignature, FONTSIGNATURE_SIZE) != 0) 
            {
                // Compare fontSignature[7] with 0x0800 to detect BiDi language. 
                if ((fontSignature[FONTSIGNATURE_BIDI_INDEX] & FONTSIGNATURE_BIDI) != 0) 
                {
                    bidiInput = true; 
                }
            }

            return bidiInput; 
        }
 
        //...................................................... 
        //
        //  Table Selection 
        //
        //......................................................

        private static TableCell FindCellAtColumnIndex(TableCellCollection cells, int columnIndex) 
        {
            for (int cellIndex = 0; cellIndex < cells.Count; cellIndex++) 
            { 
                TableCell cell;
                int startColumnIndex; 
                int endColumnIndex;

                cell = cells[cellIndex];
                startColumnIndex = cell.ColumnIndex; 
                endColumnIndex = startColumnIndex + cell.ColumnSpan - 1;
 
                if (startColumnIndex <= columnIndex && columnIndex <= endColumnIndex) 
                {
                    return cell; 
                }
            }

            return null; 
        }
 
        ///  
        /// Determines if the given element has any ancestor.
        ///  
        /// 
        /// 
        private static bool IsRootElement(DependencyObject element)
        { 
            return GetParentElement(element) == null;
        } 
 
        /// 
        /// Workaround to approximate whether or not our window is active. 
        /// 
        /// 
        private bool IsFocusWithinRoot()
        { 
            DependencyObject element = this.UiScope;
            DependencyObject parent = this.UiScope; 
 
            while (parent != null)
            { 
                element = parent;
                parent = GetParentElement(element);
            }
 
            if (element is UIElement && ((UIElement)element).IsKeyboardFocusWithin)
            { 
                return true; 
            }
 
            return false;
        }

        ///  
        /// Helper method to determine an element's parent, using the umpteen methods of
        /// parenting. 
        ///  
        /// 
        private static DependencyObject GetParentElement(DependencyObject element) 
        {
            DependencyObject parent;

            if (element is FrameworkElement || element is FrameworkContentElement) 
            {
                parent = LogicalTreeHelper.GetParent(element); 
                if (parent == null && element is FrameworkElement) 
                {
                    parent = ((FrameworkElement)element).TemplatedParent; 
                    if (parent == null && element is Visual)
                    {
                        parent = VisualTreeHelper.GetParent(element);
                    } 
                }
            } 
            else if (element is Visual) 
            {
                parent = VisualTreeHelper.GetParent(element); 
            }
            else
            {
                parent = null; 
            }
 
            return parent; 
        }
 
        // Removes the caret from the visual tree.
        private void DetachCaretFromVisualTree()
        {
            if (_caretElement != null) 
            {
                _caretElement.DetachFromView(); 
                _caretElement = null; 
            }
        } 

        #endregion Private methods

        //------------------------------------------------------ 
        //
        //  Private Properties 
        // 
        //-----------------------------------------------------
 
        #region Private Properties

        TextEditor ITextSelection.TextEditor
        { 
            get
            { 
                return _textEditor; 
            }
        } 

        ITextView ITextSelection.TextView
        {
            get 
            {
                return _textEditor.TextView; 
            } 
        }
 
        private ITextView TextView
        {
            get
            { 
                return ((ITextSelection)this).TextView;
            } 
        } 

        private TextStore TextStore 
        {
            get
            {
                return _textEditor.TextStore; 
            }
        } 
 
        private ImmComposition ImmComposition
        { 
            get
            {
                return _textEditor.ImmComposition;
            } 
        }
 
        // UiScope associated with this TextSelection's TextEditor. 
        private FrameworkElement UiScope
        { 
            get
            {
                return _textEditor.UiScope;
            } 
        }
 
        // Position from which to spring load property values. 
        private ITextPointer PropertyPosition
        { 
            get
            {
                ITextSelection This = this;
                ITextPointer position = null; 

                if (!This.IsEmpty) 
                { 
                    position = TextPointerBase.GetFollowingNonMergeableInlineContentStart(This.Start);
                } 

                if (position == null)
                {
                    position = This.Start; 
                }
 
                position.Freeze(); 
                return position;
            } 
        }

        #endregion Private Properties
 
        //-----------------------------------------------------
        // 
        //  Private Types 
        //
        //----------------------------------------------------- 

        #region Private Types

        // The four possible positions for the selection moving position. 
        private enum MovingEdge { Start, StartInner, EndInner, End, None };
 
        #endregion Private Types 

        //------------------------------------------------------ 
        //
        //  Private Fields
        //
        //----------------------------------------------------- 

        #region Private Fields 
 
        // Selected Content
        // ---------------- 

        // TextEditor that owns this selection.
        private TextEditor _textEditor;
 
        // Container for highlights on selected text.
        private TextSelectionHighlightLayer _highlightLayer; 
 
        // Springload Formatting
        // --------------------- 

        // Dependency object representing a set of springloaded formatting properties
        private DependencyObject _springloadFormatting;
 
        // Selection autoexpansion for unit boundaries
        // ------------------------------------------- 
 
        // A position where the last selection gesture has been initiated.
        // Selection gestures are: mouseDown-Move-...-Move-Up, Shift+ArrowDown-...-Down-Up. 
        // Note that Shift+MouseDown-Move-...-Move-Up is a gesture continuation,
        // it does not change _anchorPosition.
        // Actual selection always contains this position but may be extended
        // to a wider range - to encompass whole units such as words, 
        // hyperlinks, sentences, paragraphs, table cells etc.
        // 
 

 
        private ITextPointer _anchorPosition;

        // A position to which user input is applied.
        // It may coinside with Start or End, but it may be also in some other 
        // corner of rectangular table range.
        private MovingEdge _movingPositionEdge; 
 
        // LogicalDirection for the moving position.
        // If the selection is empty, this value is ignored and 
        // the direction matches this.Start.  Otherwise we respect
        // the value, which typically points inwards towards the
        // content but may point outward to include an empty line.
        private LogicalDirection _movingPositionDirection; 

        // Text position used on previous step of mouse dragging selection 
        // It is used in selection dragging heuristic to identify a situation when 
        // dragging end returned back to selected area which means that
        // autoword expansion must be temporary stopped - until a new word 
        // boundary is crossed. See also _reenterPosition.
        private ITextPointer _previousCursorPosition;

        // Text position where dragged mouse re-entered a selection. This word should not be autoexapnded 
        private ITextPointer _reenterPosition;
 
        // Flag indicating that initial word boundary has been crossed at least once doring selection expansion 
        private bool _anchorWordRangeHasBeenCrossedOnce;
 
        // Flag allows autoword expansion for anchor end of selection
        private bool _allowWordExpansionOnAnchorEnd;

        // Font signature size as 16 
        private const int FONTSIGNATURE_SIZE = 16;
 
        // BIDI font signature index from GetLocaleInfo. 
        private const int FONTSIGNATURE_BIDI_INDEX = 7;
 
        // BIDI font signature value
        private const int FONTSIGNATURE_BIDI = 0x0800;

        // Signals how the caret should be scrolled into view on the next 
        // caret update.
        private CaretScrollMethod _caretScrollMethod; 
 
        // If true, signals that the next caret
        // scroll-into-view should include hueristics to include following 
        // text.
        private bool _pendingCaretNavigation;

        // Caret associated with this selection. 
        private CaretElement _caretElement;
 
        // Flag set true after scheduling a callback to UpdateCaretStateWorker. 
        // Used to prevent unbounded callback allocations on the Dispatcher queue --
        // we fold redundant update requests into a single queue item. 
        bool _pendingUpdateCaretStateCallback;

        #endregion Private Fields
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK