Ejemplo n.º 1
0
        private bool ApplyOverlap(Token token, int start, int end, VisualLine visualLine)
        {
            if (token.Start >= end)
            {
                return(false);
            }

            if (token.End <= start)
            {
                return(true);
            }

            int overlapStart = Math.Max(start, token.Start);
            int overlapEnd   = Math.Min(end, token.End);

            int offset = visualLine.FirstDocumentLine.Offset;

            overlapStart = visualLine.GetVisualColumn(overlapStart - offset);
            overlapEnd   = visualLine.GetVisualColumn(overlapEnd - offset);

            void ApplyColorizerElements(VisualLineElement lineElement)
            {
                foreach (IColorizerElement <Token> colorizerElement in Elements)
                {
                    colorizerElement.Apply(lineElement, token);
                }
            }

            ChangeVisualElements(overlapStart, overlapEnd, ApplyColorizerElements);

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Validates the visual column of the caret using the specified visual line.
        /// The visual line must contain the caret offset.
        /// </summary>
        void RevalidateVisualColumn(VisualLine visualLine)
        {
            if (visualLine == null)
            {
                throw new ArgumentNullException("visualLine");
            }

            // mark column as validated
            visualColumnValid = true;

            int caretOffset             = textView.Document.GetOffset(position);
            int firstDocumentLineOffset = visualLine.FirstDocumentLine.Offset;

            if (position.VisualColumn < 0)
            {
                position.VisualColumn = visualLine.GetVisualColumn(caretOffset - firstDocumentLineOffset);
            }
            else
            {
                int offsetFromVisualColumn = visualLine.GetRelativeOffset(position.VisualColumn);
                offsetFromVisualColumn += firstDocumentLineOffset;
                if (offsetFromVisualColumn != caretOffset)
                {
                    position.VisualColumn = visualLine.GetVisualColumn(caretOffset - firstDocumentLineOffset);
                }
                else
                {
                    if (position.VisualColumn > visualLine.VisualLength)
                    {
                        position.VisualColumn = visualLine.VisualLength;
                    }
                }
            }
            // search possible caret position (first try forwards)
            int newVisualColumn = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal);

            if (newVisualColumn < 0)
            {
                // then try backwards
                newVisualColumn = visualLine.GetNextCaretPosition(position.VisualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.Normal);
            }
            if (newVisualColumn < 0)
            {
                throw ThrowUtil.NoValidCaretPosition();
            }
            if (newVisualColumn != position.VisualColumn)
            {
                int newOffset = visualLine.GetRelativeOffset(newVisualColumn) + firstDocumentLineOffset;
                this.Position = new TextViewPosition(textView.Document.GetLocation(newOffset), newVisualColumn);
            }
        }
Ejemplo n.º 3
0
        int GetOffsetFromMousePositionFirstTextLineOnly(Point positionRelativeToTextView, out int visualColumn)
        {
            visualColumn = 0;
            TextView textView = textArea.TextView;
            Point    pos      = positionRelativeToTextView;

            if (pos.Y < 0)
            {
                pos.Y = 0;
            }
            if (pos.Y > textView.ActualHeight)
            {
                pos.Y = textView.ActualHeight;
            }
            pos += textView.ScrollOffset;
            if (pos.Y > textView.DocumentHeight)
            {
                pos.Y = textView.DocumentHeight - ExtensionMethods.Epsilon;
            }
            VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y);

            if (line != null)
            {
                visualColumn = line.GetVisualColumn(line.TextLines.First(), pos.X, textArea.Selection.EnableVirtualSpace);
                return(line.GetRelativeOffset(visualColumn) + line.FirstDocumentLine.Offset);
            }
            return(-1);
        }
Ejemplo n.º 4
0
        int GetOffsetFromMousePosition(Point positionRelativeToTextView, out int visualColumn, out bool isAtEndOfLine)
        {
            visualColumn = 0;
            TextView textView = textArea.TextView;
            Point    pos      = positionRelativeToTextView;

            if (pos.Y < 0)
            {
                pos.Y = 0;
            }
            if (pos.Y > textView.ActualHeight)
            {
                pos.Y = textView.ActualHeight;
            }
            pos += textView.ScrollOffset;
            if (pos.Y >= textView.DocumentHeight)
            {
                pos.Y = textView.DocumentHeight - 0.01;
            }
            VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y);

            if (line != null)
            {
                var textLine = line.GetTextLineByVisualYPosition(pos.Y);
                visualColumn  = line.GetVisualColumn(textLine, pos.X, textArea.Selection.EnableVirtualSpace);
                isAtEndOfLine = (visualColumn >= line.GetTextLineVisualStartColumn(textLine) + textLine.Length);
                return(line.GetRelativeOffset(visualColumn) + line.FirstDocumentLine.Offset);
            }
            isAtEndOfLine = false;
            return(-1);
        }
Ejemplo n.º 5
0
        public static ISegment GetWholeWordSegment(TextDocument document, TextEditor textEditor, LogicalDirection direction = LogicalDirection.Forward)
        {
            TextArea textArea = textEditor.TextArea;
            TextView textView = textArea.TextView;

            if (textView == null)
            {
                return(null);
            }

            Point      pos  = textArea.TextView.GetVisualPosition(textArea.Caret.Position, VisualYPosition.LineMiddle) - textArea.TextView.ScrollOffset;
            VisualLine line = textView.GetVisualLine(textEditor.TextArea.Caret.Position.Line);

            if (line != null)
            {
                int visualColumn = line.GetVisualColumn(pos, textArea.Selection.EnableVirtualSpace);
                int wordStartVc;

                if (line.VisualLength == visualColumn)
                {
                    wordStartVc = line.GetNextCaretPosition(visualColumn, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol, textArea.Selection.EnableVirtualSpace);
                }
                else
                {
                    wordStartVc = line.GetNextCaretPosition(visualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol, textArea.Selection.EnableVirtualSpace);
                }

                if (wordStartVc == -1)
                {
                    wordStartVc = 0;
                }
                int wordEndVc = line.GetNextCaretPosition(wordStartVc, direction, CaretPositioningMode.WordBorderOrSymbol, textArea.Selection.EnableVirtualSpace);
                if (wordEndVc == -1)
                {
                    wordEndVc = line.VisualLength;
                }

                if (visualColumn < wordStartVc || (direction == LogicalDirection.Forward && visualColumn > wordEndVc))
                {
                    return(new SimpleSegment());
                }

                if (direction == LogicalDirection.Backward && wordStartVc > wordEndVc)
                {
                    int temp = wordEndVc;
                    wordEndVc   = wordStartVc;
                    wordStartVc = temp;
                }

                int relOffset       = line.FirstDocumentLine.Offset;
                int wordStartOffset = line.GetRelativeOffset(wordStartVc) + relOffset;
                int wordEndOffset   = line.GetRelativeOffset(wordEndVc) + relOffset;

                return(new SimpleSegment(wordStartOffset, wordEndOffset - wordStartOffset));
            }

            return(null);
        }
Ejemplo n.º 6
0
        void CalculateSegments()
        {
            DocumentLine nextLine = document.GetLineByNumber(Math.Min(startLine, endLine));

            do
            {
                VisualLine vl      = textArea.TextView.GetOrConstructVisualLine(nextLine);
                int        startVC = vl.GetVisualColumn(new Point(startXPos, 0), true);
                int        endVC   = vl.GetVisualColumn(new Point(endXPos, 0), true);

                int baseOffset  = vl.FirstDocumentLine.Offset;
                int startOffset = baseOffset + vl.GetRelativeOffset(startVC);
                int endOffset   = baseOffset + vl.GetRelativeOffset(endVC);
                segments.Add(new SelectionSegment(startOffset, startVC, endOffset, endVC));

                nextLine = vl.LastDocumentLine.NextLine;
            } while (nextLine != null && nextLine.LineNumber <= Math.Max(startLine, endLine));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Changes a part of the current document line.
        /// </summary>
        /// <param name="startOffset">Start offset of the region to change</param>
        /// <param name="endOffset">End offset of the region to change</param>
        /// <param name="action">Action that changes an individual <see cref="VisualLineElement"/>.</param>
        protected void ChangeLinePart(int startOffset, int endOffset, Action <VisualLineElement> action)
        {
            if (startOffset < currentDocumentLineStartOffset || startOffset > currentDocumentLineEndOffset)
            {
                throw new ArgumentOutOfRangeException("startOffset", startOffset, String.Format("Value must be between {0} and {1}", currentDocumentLineStartOffset, currentDocumentLineEndOffset));
            }
            if (endOffset < startOffset || endOffset > currentDocumentLineEndOffset)
            {
                throw new ArgumentOutOfRangeException("endOffset", endOffset, String.Format("Value must be between {0} and {1}", startOffset, currentDocumentLineEndOffset));
            }
            VisualLine vl          = this.CurrentContext.VisualLine;
            int        visualStart = vl.GetVisualColumn(startOffset - firstLineStart);
            int        visualEnd   = vl.GetVisualColumn(endOffset - firstLineStart);

            if (visualStart < visualEnd)
            {
                ChangeVisualElements(visualStart, visualEnd, action);
            }
        }
Ejemplo n.º 8
0
        int GetTextLineIndexFromOffset(List <TextLine> textLines, int offset)
        {
            int        lineNumber = TextView.Document.GetLineByOffset(offset).LineNumber;
            VisualLine vl         = TextView.GetVisualLine(lineNumber);

            if (vl != null)
            {
                int      relOffset = offset - vl.FirstDocumentLine.Offset;
                TextLine line      = vl.GetTextLine(vl.GetVisualColumn(relOffset));
                return(textLines.IndexOf(line));
            }
            return(-1);
        }
Ejemplo n.º 9
0
        private bool ApplyOverlap(Expression expression, int start, int end, VisualLine visualLine)
        {
            if (expression.StartToken.Start >= end)
            {
                return(false);
            }

            if (expression.EndToken.End <= start)
            {
                return(true);
            }

            int overlapStart = Math.Max(start, expression.StartToken.Start);
            int overlapEnd   = Math.Min(end, expression.EndToken.End);

            int offset = visualLine.FirstDocumentLine.Offset;

            overlapStart = visualLine.GetVisualColumn(overlapStart - offset);
            overlapEnd   = visualLine.GetVisualColumn(overlapEnd - offset);

            IEnumerable <IColorizerElement <Expression> > elements = Elements
                                                                     .Where(x => x.CanApply(expression));

            void ApplyColorizerElements(VisualLineElement lineElement)
            {
                foreach (IColorizerElement <Expression> colorizerElement in elements)
                {
                    colorizerElement.Apply(lineElement, expression);
                }
            }

            if (elements.Count() > 0)
            {
                ChangeVisualElements(overlapStart, overlapEnd, ApplyColorizerElements);
            }

            return(true);
        }
Ejemplo n.º 10
0
        private void OnTextEditorMouseHover(object sender, MouseEventArgs eventArgs)
        {
            // Find offset under mouse cursor.
            var        mousePos       = eventArgs.GetPosition(_textEditor.TextArea.TextView);
            double     verticalOffset = _textEditor.VerticalOffset;
            VisualLine visualLine     = _textEditor.TextArea.TextView.GetVisualLineFromVisualTop(mousePos.Y + verticalOffset);

            if (visualLine == null)
            {
                return;
            }

            double horizontalOffset = _textEditor.HorizontalOffset;
            int    visualColumn     = visualLine.GetVisualColumn(mousePos + new Vector(horizontalOffset, verticalOffset));
            int    relativeOffset   = visualLine.GetRelativeOffset(visualColumn);
            int    offset           = visualLine.FirstDocumentLine.Offset + relativeOffset;

            // Get word at mouse cursor.
            var text = TextUtilities.GetIdentifierAt(_textEditor.Document, offset);

            // Get region at mouse cursor.
            ShaderRegion region = _parser.IdentifyRegion(_textEditor.Document, offset);

            NamedObjectCollection <NamedCompletionData>[] lookupTables = GetToolTipLookupTables(region);
            if (lookupTables != null)
            {
                // Look up symbol in lookup tables.
                NamedCompletionData info = null;
                foreach (NamedObjectCollection <NamedCompletionData> lookupTable in lookupTables)
                {
                    if (lookupTable.TryGet <NamedCompletionData>(text, out info))
                    {
                        break;
                    }
                }

                // Show tooltip if lookup was successful and description for the symbol is available.
                if (info != null && !string.IsNullOrEmpty(info.Description as string))
                {
                    // TODO: Use s better tooltip style.
                    _toolTip = new ToolTip
                    {
                        Content   = info.Description,
                        Placement = PlacementMode.Mouse,
                        IsOpen    = true,
                    };
                }
            }
        }
Ejemplo n.º 11
0
        SimpleSegment GetWordAtMousePosition(MouseEventArgs e)
        {
            TextView textView = textArea.TextView;

            if (textView == null)
            {
                return(SimpleSegment.Invalid);
            }
            Point pos = e.GetPosition(textView);

            if (pos.Y < 0)
            {
                pos.Y = 0;
            }
            if (pos.Y > textView.ActualHeight)
            {
                pos.Y = textView.ActualHeight;
            }
            pos += textView.ScrollOffset;
            VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y);

            if (line != null)
            {
                int visualColumn = line.GetVisualColumn(pos, textArea.Selection.EnableVirtualSpace);
                int wordStartVC  = line.GetNextCaretPosition(visualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol, textArea.Selection.EnableVirtualSpace);
                if (wordStartVC == -1)
                {
                    wordStartVC = 0;
                }
                int wordEndVC = line.GetNextCaretPosition(wordStartVC, LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol, textArea.Selection.EnableVirtualSpace);
                if (wordEndVC == -1)
                {
                    wordEndVC = line.VisualLength;
                }
                int relOffset       = line.FirstDocumentLine.Offset;
                int wordStartOffset = line.GetRelativeOffset(wordStartVC) + relOffset;
                int wordEndOffset   = line.GetRelativeOffset(wordEndVC) + relOffset;
                return(new SimpleSegment(wordStartOffset, wordEndOffset - wordStartOffset));
            }
            else
            {
                return(SimpleSegment.Invalid);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Validates the visual column of the caret using the specified visual line.
        /// The visual line must contain the caret offset.
        /// </summary>
        void RevalidateVisualColumn(VisualLine visualLine)
        {
            if (visualLine == null)
            {
                throw new ArgumentNullException("visualLine");
            }

            // mark column as validated
            visualColumnValid = true;

            int caretOffset             = textView.Document.GetOffset(position);
            int firstDocumentLineOffset = visualLine.FirstDocumentLine.Offset;

            if (position.VisualColumn < 0)
            {
                position.VisualColumn = visualLine.GetVisualColumn(caretOffset - firstDocumentLineOffset);
            }
            else
            {
                int offsetFromVisualColumn = visualLine.GetRelativeOffset(position.VisualColumn);
                offsetFromVisualColumn += firstDocumentLineOffset;
                if (offsetFromVisualColumn != caretOffset)
                {
                    position.VisualColumn = visualLine.GetVisualColumn(caretOffset - firstDocumentLineOffset);
                }
                else
                {
                    if (position.VisualColumn > visualLine.VisualLength)
                    {
                        position.VisualColumn = visualLine.VisualLength;
                    }
                }
            }
            // search possible caret positions
            int newVisualColumnForwards = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal);

            // If position.VisualColumn was valid, we're done with validation.
            if (newVisualColumnForwards != position.VisualColumn)
            {
                // also search backwards so that we can pick the better match
                int newVisualColumnBackwards = visualLine.GetNextCaretPosition(position.VisualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.Normal);

                if (newVisualColumnForwards < 0 && newVisualColumnBackwards < 0)
                {
                    throw ThrowUtil.NoValidCaretPosition();
                }

                // determine offsets for new visual column positions
                int newOffsetForwards;
                if (newVisualColumnForwards >= 0)
                {
                    newOffsetForwards = visualLine.GetRelativeOffset(newVisualColumnForwards) + firstDocumentLineOffset;
                }
                else
                {
                    newOffsetForwards = -1;
                }
                int newOffsetBackwards;
                if (newVisualColumnBackwards >= 0)
                {
                    newOffsetBackwards = visualLine.GetRelativeOffset(newVisualColumnBackwards) + firstDocumentLineOffset;
                }
                else
                {
                    newOffsetBackwards = -1;
                }

                int newVisualColumn, newOffset;
                // if there's only one valid position, use it
                if (newVisualColumnForwards < 0)
                {
                    newVisualColumn = newVisualColumnBackwards;
                    newOffset       = newOffsetBackwards;
                }
                else if (newVisualColumnBackwards < 0)
                {
                    newVisualColumn = newVisualColumnForwards;
                    newOffset       = newOffsetForwards;
                }
                else
                {
                    // two valid positions: find the better match
                    if (Math.Abs(newOffsetBackwards - caretOffset) < Math.Abs(newOffsetForwards - caretOffset))
                    {
                        // backwards is better
                        newVisualColumn = newVisualColumnBackwards;
                        newOffset       = newOffsetBackwards;
                    }
                    else
                    {
                        // forwards is better
                        newVisualColumn = newVisualColumnForwards;
                        newOffset       = newOffsetForwards;
                    }
                }
                this.Position = new TextViewPosition(textView.Document.GetLocation(newOffset), newVisualColumn);
            }
        }
        static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn)
        {
            // moving up/down happens using the desired visual X position
            double xPos = textArea.Caret.DesiredXPos;

            if (double.IsNaN(xPos))
            {
                xPos = visualLine.GetTextLineVisualXPosition(textLine, caretVisualColumn);
            }
            // now find the TextLine+VisualLine where the caret will end up in
            VisualLine targetVisualLine = visualLine;
            TextLine   targetLine;
            int        textLineIndex = visualLine.TextLines.IndexOf(textLine);

            switch (direction)
            {
            case CaretMovementType.LineUp:
            {
                // Move up: move to the previous TextLine in the same visual line
                // or move to the last TextLine of the previous visual line
                int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1;
                if (textLineIndex > 0)
                {
                    targetLine = visualLine.TextLines[textLineIndex - 1];
                }
                else if (prevLineNumber >= 1)
                {
                    DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber);
                    targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine);
                    targetLine       = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1];
                }
                else
                {
                    targetLine = null;
                }
                break;
            }

            case CaretMovementType.LineDown:
            {
                // Move down: move to the next TextLine in the same visual line
                // or move to the first TextLine of the next visual line
                int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1;
                if (textLineIndex < visualLine.TextLines.Count - 1)
                {
                    targetLine = visualLine.TextLines[textLineIndex + 1];
                }
                else if (nextLineNumber <= textArea.Document.LineCount)
                {
                    DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber);
                    targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine);
                    targetLine       = targetVisualLine.TextLines[0];
                }
                else
                {
                    targetLine = null;
                }
                break;
            }

            case CaretMovementType.PageUp:
            case CaretMovementType.PageDown:
            {
                // Page up/down: find the target line using its visual position
                double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle);
                if (direction == CaretMovementType.PageUp)
                {
                    yPos -= textArea.TextView.RenderSize.Height;
                }
                else
                {
                    yPos += textArea.TextView.RenderSize.Height;
                }
                DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos);
                targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine);
                targetLine       = targetVisualLine.GetTextLineByVisualYPosition(yPos);
                break;
            }

            default:
                throw new NotSupportedException(direction.ToString());
            }
            if (targetLine != null)
            {
                double yPos            = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle);
                int    newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), textArea.Selection.EnableVirtualSpace);
                SetCaretPosition(textArea, targetVisualLine, targetLine, newVisualColumn, false);
                textArea.Caret.DesiredXPos = xPos;
            }
        }
        static TextViewPosition GetUpDownCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace, ref double xPos)
        {
            // moving up/down happens using the desired visual X position
            if (double.IsNaN(xPos))
            {
                xPos = visualLine.GetTextLineVisualXPosition(textLine, caretPosition.VisualColumn);
            }
            // now find the TextLine+VisualLine where the caret will end up in
            VisualLine targetVisualLine = visualLine;
            TextLine   targetLine;
            int        textLineIndex = visualLine.TextLines.IndexOf(textLine);

            switch (direction)
            {
            case CaretMovementType.LineUp:
            {
                // Move up: move to the previous TextLine in the same visual line
                // or move to the last TextLine of the previous visual line
                int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1;
                if (textLineIndex > 0)
                {
                    targetLine = visualLine.TextLines[textLineIndex - 1];
                }
                else if (prevLineNumber >= 1)
                {
                    DocumentLine prevLine = textView.Document.GetLineByNumber(prevLineNumber);
                    targetVisualLine = textView.GetOrConstructVisualLine(prevLine);
                    targetLine       = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1];
                }
                else
                {
                    targetLine = null;
                }
                break;
            }

            case CaretMovementType.LineDown:
            {
                // Move down: move to the next TextLine in the same visual line
                // or move to the first TextLine of the next visual line
                int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1;
                if (textLineIndex < visualLine.TextLines.Count - 1)
                {
                    targetLine = visualLine.TextLines[textLineIndex + 1];
                }
                else if (nextLineNumber <= textView.Document.LineCount)
                {
                    DocumentLine nextLine = textView.Document.GetLineByNumber(nextLineNumber);
                    targetVisualLine = textView.GetOrConstructVisualLine(nextLine);
                    targetLine       = targetVisualLine.TextLines[0];
                }
                else
                {
                    targetLine = null;
                }
                break;
            }

            case CaretMovementType.PageUp:
            case CaretMovementType.PageDown:
            {
                // Page up/down: find the target line using its visual position
                double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle);
                if (direction == CaretMovementType.PageUp)
                {
                    yPos -= textView.RenderSize.Height;
                }
                else
                {
                    yPos += textView.RenderSize.Height;
                }
                DocumentLine newLine = textView.GetDocumentLineByVisualTop(yPos);
                targetVisualLine = textView.GetOrConstructVisualLine(newLine);
                targetLine       = targetVisualLine.GetTextLineByVisualYPosition(yPos);
                break;
            }

            default:
                throw new NotSupportedException(direction.ToString());
            }
            if (targetLine != null)
            {
                double yPos            = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle);
                int    newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), enableVirtualSpace);

                // prevent wrapping to the next line; TODO: could 'IsAtEnd' help here?
                int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine);
                if (newVisualColumn >= targetLineStartCol + targetLine.Length)
                {
                    if (newVisualColumn <= targetVisualLine.VisualLength)
                    {
                        newVisualColumn = targetLineStartCol + targetLine.Length - 1;
                    }
                }
                return(targetVisualLine.GetTextViewPosition(newVisualColumn));
            }
            else
            {
                return(caretPosition);
            }
        }