Exemplo n.º 1
0
        /*
         * Code used to trim text segments for alternative display of sticky note anchors
         *
         * /// <summary>
         * /// ctor that initializes the TextSegments array by cloning and trimming the input segment Array
         * /// </summary>
         * /// <param name="segments">input segment</param>
         * /// <remarks>This is used to convert a TextRange into TextAnchor.
         * /// Input segments must be ordered and non overlapping</remarks>
         * internal TextAnchor(IList<TextSegment> segments)
         * {
         *  if (segments == null)
         *      return;
         *
         *  ITextPointer lastPointer = null;
         *  for (int i = 0; i < segments.Count; i++)
         *  {
         *      Invariant.Assert((lastPointer == null) || (lastPointer.CompareTo(segments[i].Start) <= 0), "overlapped segments found");
         *      TextSegment newSegment = TextAnchor.Trim(segments[i]);
         *      if (newSegment.IsNull)
         *          continue;
         *
         *      _segments.Add(newSegment);
         *      lastPointer = newSegment.End;
         *  }
         * }
         */

        #endregion Constructors

        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------

        #region Public Methods

        /// <summary>
        /// Determines if the text pointer is contained by one of the
        /// anchor's TextSegment.s
        /// </summary>
        /// <param name="textPointer">text pointer to test</param>
        internal bool Contains(ITextPointer textPointer)
        {
            if (textPointer == null)
            {
                throw new ArgumentNullException("textPointer");
            }

            if (textPointer.TextContainer != this.Start.TextContainer)
            {
                throw new ArgumentException(SR.Get(SRID.NotInAssociatedTree, "textPointer"));
            }

            // Correct position normalization on range boundary so that
            // our test would not depend on what side of formatting tags
            // pointer is located.
            if (textPointer.CompareTo(this.Start) < 0)
            {
                textPointer = textPointer.GetInsertionPosition(LogicalDirection.Forward);
            }
            else if (textPointer.CompareTo(this.End) > 0)
            {
                textPointer = textPointer.GetInsertionPosition(LogicalDirection.Backward);
            }

            // Check if at least one segment contains this position.
            for (int i = 0; i < _segments.Count; i++)
            {
                if (_segments[i].Contains(textPointer))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemplo n.º 2
0
 // Token: 0x0600625B RID: 25179 RVA: 0x001B9470 File Offset: 0x001B7670
 private static TextSegment CreateNormalizedSegment(ITextPointer start, ITextPointer end)
 {
     if (start.CompareTo(end) == 0)
     {
         if (!TextPointerBase.IsAtInsertionPosition(start, start.LogicalDirection))
         {
             start = start.GetInsertionPosition(start.LogicalDirection);
             end   = start;
         }
     }
     else
     {
         if (!TextPointerBase.IsAtInsertionPosition(start, start.LogicalDirection))
         {
             start = start.GetInsertionPosition(LogicalDirection.Forward);
         }
         if (!TextPointerBase.IsAtInsertionPosition(end, start.LogicalDirection))
         {
             end = end.GetInsertionPosition(LogicalDirection.Backward);
         }
         if (start.CompareTo(end) >= 0)
         {
             if (start.LogicalDirection == LogicalDirection.Backward)
             {
                 start = end.GetFrozenPointer(LogicalDirection.Backward);
             }
             end = start;
         }
     }
     return(new TextSegment(start, end));
 }
Exemplo n.º 3
0
 // Token: 0x0600624A RID: 25162 RVA: 0x001B8AC4 File Offset: 0x001B6CC4
 internal bool Contains(ITextPointer textPointer)
 {
     if (textPointer == null)
     {
         throw new ArgumentNullException("textPointer");
     }
     if (textPointer.TextContainer != this.Start.TextContainer)
     {
         throw new ArgumentException(SR.Get("NotInAssociatedTree", new object[]
         {
             "textPointer"
         }));
     }
     if (textPointer.CompareTo(this.Start) < 0)
     {
         textPointer = textPointer.GetInsertionPosition(LogicalDirection.Forward);
     }
     else if (textPointer.CompareTo(this.End) > 0)
     {
         textPointer = textPointer.GetInsertionPosition(LogicalDirection.Backward);
     }
     for (int i = 0; i < this._segments.Count; i++)
     {
         if (this._segments[i].Contains(textPointer))
         {
             return(true);
         }
     }
     return(false);
 }
Exemplo n.º 4
0
            // Token: 0x060085BD RID: 34237 RVA: 0x0024AA08 File Offset: 0x00248C08
            private ITextPointer GetDropPosition(Visual target, Point point)
            {
                Invariant.Assert(target != null);
                Invariant.Assert(this._textEditor.TextView.IsValid);
                if (target != this._textEditor.TextView.RenderScope && target != null && this._textEditor.TextView.RenderScope.IsAncestorOf(target))
                {
                    GeneralTransform generalTransform = target.TransformToAncestor(this._textEditor.TextView.RenderScope);
                    generalTransform.TryTransform(point, out point);
                }
                ITextPointer textPointer = this.TextView.GetTextPositionFromPoint(point, true);

                if (textPointer != null)
                {
                    textPointer = textPointer.GetInsertionPosition(textPointer.LogicalDirection);
                    if (this._textEditor.AcceptsRichContent)
                    {
                        TextSegment normalizedLineRange = TextEditorSelection.GetNormalizedLineRange(this.TextView, textPointer);
                        if (!normalizedLineRange.IsNull && textPointer.CompareTo(normalizedLineRange.End) < 0 && !TextPointerBase.IsAtWordBoundary(textPointer, LogicalDirection.Forward) && this._dragSourceTextRange != null && TextPointerBase.IsAtWordBoundary(this._dragSourceTextRange.Start, LogicalDirection.Forward) && TextPointerBase.IsAtWordBoundary(this._dragSourceTextRange.End, LogicalDirection.Forward))
                        {
                            TextSegment wordRange        = TextPointerBase.GetWordRange(textPointer);
                            string      textInternal     = TextRangeBase.GetTextInternal(wordRange.Start, wordRange.End);
                            int         offsetToPosition = wordRange.Start.GetOffsetToPosition(textPointer);
                            textPointer = ((offsetToPosition < textInternal.Length / 2) ? wordRange.Start : wordRange.End);
                        }
                    }
                }
                return(textPointer);
            }
 // Token: 0x06008E5C RID: 36444 RVA: 0x0025C04B File Offset: 0x0025A24B
 private void OpenSegment(ref ITextPointer segmentStart, ITextPointer cursor)
 {
     if (segmentStart == null)
     {
         segmentStart = cursor.GetInsertionPosition(LogicalDirection.Forward);
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Creates a new segment with the specified pointers, but first
        /// normalizes them to make sure they are on insertion positions.
        /// </summary>
        /// <param name="start">start of the new segment</param>
        /// <param name="end">end of the new segment</param>
        private static TextSegment CreateNormalizedSegment(ITextPointer start, ITextPointer end)
        {
            // Normalize the segment
            if (start.CompareTo(end) == 0)
            {
                // When the range is empty we must keep it that way during normalization
                if (!TextPointerBase.IsAtInsertionPosition(start, start.LogicalDirection))
                {
                    start = start.GetInsertionPosition(start.LogicalDirection);
                    end   = start;
                }
            }
            else
            {
                if (!TextPointerBase.IsAtInsertionPosition(start, start.LogicalDirection))
                {
                    start = start.GetInsertionPosition(LogicalDirection.Forward);
                }
                if (!TextPointerBase.IsAtInsertionPosition(end, start.LogicalDirection))
                {
                    end = end.GetInsertionPosition(LogicalDirection.Backward);
                }

                // Collapse range in case of overlapped normalization result
                if (start.CompareTo(end) >= 0)
                {
                    // The range is effectuvely empty, so collapse it to single pointer instance
                    if (start.LogicalDirection == LogicalDirection.Backward)
                    {
                        // Choose a position normalized backward,
                        start = end.GetFrozenPointer(LogicalDirection.Backward);

                        // NOTE that otherwise we will use start position,
                        // which is oriented and normalizd Forward
                    }
                    end = start;
                }
            }

            return(new TextSegment(start, end));
        }
            /// <summary>
            /// Calculates a TextPointer indended for dropping the text.
            /// </summary>
            /// <param name="target"></param>
            /// <param name="point"></param>
            /// <returns>
            /// ITextPointer intended for dropping the selected text.
            /// Adjusts the dropping point to a word boundary (beginning of word)
            /// in case if source range contains whole words.
            /// The position returned is oriented towards a character
            /// under the mouse pointer.
            /// </returns>
            private ITextPointer GetDropPosition(Visual target, Point point)
            {
                Invariant.Assert(target != null);
                Invariant.Assert(_textEditor.TextView.IsValid); // caller must guarantee this.

                // Convert point to RenderScope
                if (target != _textEditor.TextView.RenderScope && target != null && (_textEditor.TextView.RenderScope).IsAncestorOf(target))
                {
                    GeneralTransform transform = target.TransformToAncestor(_textEditor.TextView.RenderScope);
                    transform.TryTransform(point, out point);
                }

                ITextPointer dropPosition = this.TextView.GetTextPositionFromPoint(point, /*snapToText:*/ true);

                // For rich text content we adjust drop position to word boundary
                if (dropPosition != null)
                {
                    // Normalize drop position
                    dropPosition = dropPosition.GetInsertionPosition(dropPosition.LogicalDirection);

                    if (_textEditor.AcceptsRichContent)
                    {
                        TextSegment lineRange = TextEditorSelection.GetNormalizedLineRange(this.TextView, dropPosition);

                        if (!lineRange.IsNull &&
                            // The drop position must be before of end of line
                            dropPosition.CompareTo(lineRange.End) < 0 &&
                            // We check if we are not at word boundary already:
                            !TextPointerBase.IsAtWordBoundary(dropPosition, /*insideWordDirection:*/ LogicalDirection.Forward) &&
                            // We do not do it if the source range was not on word boundaries from both ends
                            _dragSourceTextRange != null &&                                                           //
                            TextPointerBase.IsAtWordBoundary(_dragSourceTextRange.Start, LogicalDirection.Forward) && //
                            TextPointerBase.IsAtWordBoundary(_dragSourceTextRange.End, LogicalDirection.Forward))
                        {
                            // Move to word boundary. Select closest one to a dropPosition.
                            TextSegment wordSegment = TextPointerBase.GetWordRange(dropPosition);
                            string      wordText    = TextRangeBase.GetTextInternal(wordSegment.Start, wordSegment.End);
                            int         indexInWord = wordSegment.Start.GetOffsetToPosition(dropPosition);
                            dropPosition = (indexInWord < (wordText.Length / 2)) ? wordSegment.Start : wordSegment.End;
                        }
                    }
                }

                return(dropPosition);
            }
Exemplo n.º 8
0
        // 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);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 9
0
        //......................................................
        //
        //  Active Positions of Selection
        //
        //......................................................

        /// <summary>
        /// Stores normalized anchor and moving positions for the selection.
        /// Ensures that they are both inside of range Start/End.
        /// </summary>
        /// <param name="anchorPosition">
        /// A position which must be stored as initial position for the selection.
        /// </param>
        /// <param name="movingPosition">
        /// The "hot" or active selection edge which responds to user input.
        /// </param>
        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;
        }
Exemplo n.º 10
0
        // <see cref="TextPointer.GetCharacterRect"/>
        internal static Rect GetCharacterRect(ITextPointer thisPointer, LogicalDirection direction, bool transformToUiScope)
        {
            ITextView textView = thisPointer.TextContainer.TextView;

            Invariant.Assert(textView != null, "Null TextView!"); // Did you check ITextPointer.HasValidLayout?
            Invariant.Assert(textView.RenderScope != null, "Null RenderScope");
            Invariant.Assert(thisPointer.TextContainer != null, "Null TextContainer");
            Invariant.Assert(thisPointer.TextContainer.Parent != null, "Null parent of TextContainer");

            // Try to ask for a Rect from an insertion position.
            if (!thisPointer.IsAtInsertionPosition)
            {
                ITextPointer insertionPosition = thisPointer.GetInsertionPosition(direction);

                if (insertionPosition != null)
                {
                    thisPointer = insertionPosition;
                }
            }

            Rect rect = textView.GetRectangleFromTextPosition(thisPointer.CreatePointer(direction));

            if (transformToUiScope)
            {
                Visual templatedParent;

                if (thisPointer.TextContainer.Parent is FlowDocument && textView.RenderScope is FlowDocumentView)
                {
                    // 
                    templatedParent = ((FlowDocumentView)textView.RenderScope).TemplatedParent as Visual;
                    if (templatedParent == null && ((FlowDocumentView)textView.RenderScope).Parent is FrameworkElement)
                    {
                        templatedParent = ((FrameworkElement)((FlowDocumentView)textView.RenderScope).Parent).TemplatedParent as Visual;
                    }
                }
                else if (thisPointer.TextContainer.Parent is Visual)
                {
                    Invariant.Assert(textView.RenderScope == thisPointer.TextContainer.Parent || ((Visual)thisPointer.TextContainer.Parent).IsAncestorOf( /*descendant:*/textView.RenderScope),
                        "Unexpected location of RenderScope within visual tree");
                    templatedParent = (Visual)thisPointer.TextContainer.Parent;
                }
                else
                {
                    templatedParent = null;
                }

                if (templatedParent != null && templatedParent.IsAncestorOf( /*descendant:*/textView.RenderScope))
                {
                    // translate the rect from renderscope to uiscope coordinate system (from FlowDocumentView to RichTextBox)
                    GeneralTransform transformFromRenderToUiScope = textView.RenderScope.TransformToAncestor(/*ancestor:*/templatedParent);

                    rect = transformFromRenderToUiScope.TransformBounds(rect);
                }
            }

            return rect;
        }
Exemplo n.º 11
0
        // <summary>
        // Checks if there is a "paragraph break" symbol immediately
        // before the position. Paragraph break is either plaintext
        // newline character or a combination equivalent to
        // [close-paragraph;open-paragraph] tag combination
        // </summary>
        internal static bool IsNextToAnyBreak(ITextPointer thisPosition, LogicalDirection direction)
        {
            if (!thisPosition.IsAtInsertionPosition)
            {
                thisPosition = thisPosition.GetInsertionPosition(direction);
            }

            return (IsNextToPlainLineBreak(thisPosition, direction) || IsNextToRichBreak(thisPosition, direction, null));
        }
Exemplo n.º 12
0
        /// <summary>
        /// Returns a TextSegment covering the word containing this TextPointer.
        /// </summary>
        /// <remarks>
        /// If this TextPointer is between two words, direction specifies whether
        /// the preceeding or following word is returned.
        /// 
        /// The return value includes trailing whitespace, if any.
        /// </remarks>
        internal static TextSegment GetWordRange(ITextPointer thisPosition, LogicalDirection direction)
        {
            if (!thisPosition.IsAtInsertionPosition)
            {
                // Normalize original text pointer so it is at an insertion position.
                thisPosition = thisPosition.GetInsertionPosition(direction);
            }

            if (!thisPosition.IsAtInsertionPosition)
            {
                // In case there is no insertion position in the entire document, return an empty segment.
                // GetInsertionPosition() guarantees that navigator is moved back to original position.
                return new TextSegment(thisPosition, thisPosition);
            }

            // Find the next word end edge.
            ITextPointer navigator = thisPosition.CreatePointer();
            bool moved = MoveToNextWordBoundary(navigator, direction);

            ITextPointer wordEnd = navigator;

            // Find the corresponding word start edge.
            ITextPointer wordStart;
            if (moved && IsAtWordBoundary(thisPosition, /*insideWordDirection:*/LogicalDirection.Forward))
            {
                wordStart = thisPosition;
            }
            else
            {
                navigator = thisPosition.CreatePointer();
                MoveToNextWordBoundary(navigator, direction == LogicalDirection.Backward ? LogicalDirection.Forward : LogicalDirection.Backward);
                wordStart = navigator;
            }

            if (direction == LogicalDirection.Backward)
            {
                // If this is a backward search, need to swap start/end pointers.
                navigator = wordStart;
                wordStart = wordEnd;
                wordEnd = navigator;
            }

            // Make sure that we are not crossing any block boundaries.
            wordStart = RestrictWithinBlock(thisPosition, wordStart, LogicalDirection.Backward);
            wordEnd = RestrictWithinBlock(thisPosition, wordEnd, LogicalDirection.Forward);

            // Make sure that positions do not cross - as in TextRangeBase.cs
            if (wordStart.CompareTo(wordEnd) < 0)
            {
                wordStart = wordStart.GetFrozenPointer(LogicalDirection.Backward);
                wordEnd = wordEnd.GetFrozenPointer(LogicalDirection.Forward);
            }
            else
            {
                wordStart = wordEnd.GetFrozenPointer(LogicalDirection.Backward);
                wordEnd = wordStart;
            }

            Invariant.Assert(wordStart.CompareTo(wordEnd) <= 0, "expecting wordStart <= wordEnd");
            return new TextSegment(wordStart, wordEnd);
        }
Exemplo n.º 13
0
 // Opens a segment for the following portion 
 private void OpenSegment(ref ITextPointer segmentStart, ITextPointer cursor)
 { 
     if (segmentStart == null) 
     {
         // Create normalized position for the segment start 
         segmentStart = cursor.GetInsertionPosition(LogicalDirection.Forward);
     }
 }
Exemplo n.º 14
0
        private static ITextPointer GetNormalizedPosition(ITextRange thisRange, ITextPointer position, LogicalDirection direction) 
        {
            ITextPointer normalizedPosition;

            if (thisRange.IgnoreTextUnitBoundaries) 
            {
                normalizedPosition = position.GetFormatNormalizedPosition(direction); 
            } 
            else
            { 
                normalizedPosition = position.GetInsertionPosition(direction);
            }

            return normalizedPosition; 
        }
        // Helper for OnSelectDownByLine.  Updates the selection moving position
        // during select down by line.
        private static void AdjustMovingPositionForSelectDownByLine(TextEditor This, ITextPointer newMovingPosition, ITextPointer originalMovingPosition, double suggestedX)
        {
            int newComparedToOld = newMovingPosition.CompareTo(originalMovingPosition);

            // Note: we compare orientations of equal positions to handle a case
            // when original position was at the end of line (after its linebreak with backward orientation)
            // as a result of Shift+End selection; and the new position is in the beginning of the next line,
            // which is essentially the same position but oriented differently.
            // In such a case the new position is good enough to go there.
            // We certainly don't want to go to the end of the document in this case.
            if (newComparedToOld > 0 || newComparedToOld == 0 && newMovingPosition.LogicalDirection != originalMovingPosition.LogicalDirection)
            {
                // We have another line in a given direction; move to it

                // If the destination exactly preceeds a line break, expand to include
                // the line break if we haven't reached our desired suggestedX.
                if (TextPointerBase.IsNextToAnyBreak(newMovingPosition, LogicalDirection.Forward) ||
                    newMovingPosition.GetNextInsertionPosition(LogicalDirection.Forward) == null)
                {
                    double newPositionX = GetAbsoluteXOffset(This.TextView, newMovingPosition);
                    FlowDirection paragraphFlowDirection = GetScopingParagraphFlowDirection(newMovingPosition);
                    FlowDirection controlFlowDirection = This.UiScope.FlowDirection;

                    if ((paragraphFlowDirection == controlFlowDirection && newPositionX < suggestedX) ||
                        (paragraphFlowDirection != controlFlowDirection && newPositionX > suggestedX))
                    {
                        newMovingPosition = newMovingPosition.GetInsertionPosition(LogicalDirection.Forward);
                        newMovingPosition = newMovingPosition.GetNextInsertionPosition(LogicalDirection.Forward);

                        // If we're at the last Paragraph, move to document end to include
                        // the final paragraph break.
                        if (newMovingPosition == null)
                        {
                            newMovingPosition = originalMovingPosition.TextContainer.End;
                        }

                        newMovingPosition = newMovingPosition.GetFrozenPointer(LogicalDirection.Backward);
                    }
                }

                ExtendSelectionAndBringIntoView(newMovingPosition, This);
            }
            else
            {
                // Remember where we were so that we can return if a line up follows.
                if (This._NextLineAdvanceMovingPosition == null)
                {
                    This._NextLineAdvanceMovingPosition = originalMovingPosition;
                    This._IsNextLineAdvanceMovingPositionAtDocumentHead = false;
                }

                // No more lines in this direction. Move to end of current line.
                newMovingPosition = GetPositionAtLineEnd(originalMovingPosition);

                if (newMovingPosition.GetNextInsertionPosition(LogicalDirection.Forward) == null)
                {
                    // Move to the final implicit line at end-of-doc.
                    newMovingPosition = newMovingPosition.TextContainer.End;
                }

                ExtendSelectionAndBringIntoView(newMovingPosition, This);
            }
        }