Exemple #1
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);
        }
Exemple #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);
            }
        }
Exemple #3
0
        static void MoveCaretLeft(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
        {
            int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode);

            if (pos >= 0)
            {
                SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
            }
            else
            {
                // move to end of previous line
                DocumentLine previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
                if (previousDocumentLine != null)
                {
                    VisualLine previousLine = textArea.TextView.GetOrConstructVisualLine(previousDocumentLine);
                    pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode);
                    if (pos < 0)
                    {
                        throw ThrowUtil.NoValidCaretPosition();
                    }
                    SetCaretPosition(textArea, pos, previousLine.GetRelativeOffset(pos) + previousLine.FirstDocumentLine.Offset);
                }
                else
                {
                    // at start of document
                    Debug.Assert(visualLine.FirstDocumentLine.Offset == 0);
                    SetCaretPosition(textArea, 0, 0);
                }
            }
        }
Exemple #4
0
        static void MoveCaretRight(TextArea textArea, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode)
        {
            int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Forward, mode);

            if (pos >= 0)
            {
                SetCaretPosition(textArea, pos, visualLine.GetRelativeOffset(pos) + visualLine.FirstDocumentLine.Offset);
            }
            else
            {
                // move to start of next line
                DocumentLine nextDocumentLine = visualLine.LastDocumentLine.NextLine;
                if (nextDocumentLine != null)
                {
                    VisualLine nextLine = textArea.TextView.GetOrConstructVisualLine(nextDocumentLine);
                    pos = nextLine.GetNextCaretPosition(-1, LogicalDirection.Forward, mode);
                    if (pos < 0)
                    {
                        throw ThrowUtil.NoValidCaretPosition();
                    }
                    SetCaretPosition(textArea, pos, nextLine.GetRelativeOffset(pos) + nextLine.FirstDocumentLine.Offset);
                }
                else
                {
                    // at end of document
                    Debug.Assert(visualLine.LastDocumentLine.Offset + visualLine.LastDocumentLine.TotalLength == textArea.Document.TextLength);
                    SetCaretPosition(textArea, -1, textArea.Document.TextLength);
                }
            }
        }
        static TextViewPosition GetPrevCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace)
        {
            int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode, enableVirtualSpace);

            if (pos >= 0)
            {
                return(visualLine.GetTextViewPosition(pos));
            }
            else
            {
                // move to end of previous line
                DocumentLine previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;
                if (previousDocumentLine != null)
                {
                    VisualLine previousLine = textView.GetOrConstructVisualLine(previousDocumentLine);
                    pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode, enableVirtualSpace);
                    if (pos < 0)
                    {
                        throw ThrowUtil.NoValidCaretPosition();
                    }
                    return(previousLine.GetTextViewPosition(pos));
                }
                else
                {
                    // at start of document
                    Debug.Assert(visualLine.FirstDocumentLine.Offset == 0);
                    return(new TextViewPosition(0, 0));
                }
            }
        }
        static TextViewPosition GetNextCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace)
        {
            int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Forward, mode, enableVirtualSpace);

            if (pos >= 0)
            {
                return(visualLine.GetTextViewPosition(pos));
            }
            else
            {
                // move to start of next line
                DocumentLine nextDocumentLine = visualLine.LastDocumentLine.NextLine;
                if (nextDocumentLine != null)
                {
                    VisualLine nextLine = textView.GetOrConstructVisualLine(nextDocumentLine);
                    pos = nextLine.GetNextCaretPosition(-1, LogicalDirection.Forward, mode, enableVirtualSpace);
                    if (pos < 0)
                    {
                        throw ThrowUtil.NoValidCaretPosition();
                    }
                    return(nextLine.GetTextViewPosition(pos));
                }
                else
                {
                    // at end of document
                    Debug.Assert(visualLine.LastDocumentLine.Offset + visualLine.LastDocumentLine.TotalLength == textView.Document.TextLength);
                    return(new TextViewPosition(textView.Document.GetLocation(textView.Document.TextLength)));
                }
            }
        }
Exemple #7
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);
            }
        }
Exemple #8
0
        static void MoveCaretToStartOfLine(TextArea textArea, VisualLine visualLine)
        {
            int newVC = visualLine.GetNextCaretPosition(-1, LogicalDirection.Forward, CaretPositioningMode.WordStart);

            if (newVC < 0)
            {
                throw ThrowUtil.NoValidCaretPosition();
            }
            // when the caret is already at the start of the text, jump to start before whitespace
            if (newVC == textArea.Caret.VisualColumn)
            {
                newVC = 0;
            }
            int offset = visualLine.FirstDocumentLine.Offset + visualLine.GetRelativeOffset(newVC);

            SetCaretPosition(textArea, newVC, offset);
        }
Exemple #9
0
        static TextViewPosition GetPrevCaretPosition(TextView textView, TextViewPosition caretPosition, VisualLine visualLine, CaretPositioningMode mode, bool enableVirtualSpace)
        {
            int pos = visualLine.GetNextCaretPosition(caretPosition.VisualColumn, LogicalDirection.Backward, mode, enableVirtualSpace);

            if (pos >= 0)
            {
                return(visualLine.GetTextViewPosition(pos));
            }
            var previousDocumentLine = visualLine.FirstDocumentLine.PreviousLine;

            if (previousDocumentLine != null)
            {
                var previousLine = textView.GetOrConstructVisualLine(previousDocumentLine);
                pos = previousLine.GetNextCaretPosition(previousLine.VisualLength + 1, LogicalDirection.Backward, mode, enableVirtualSpace);
                return(previousLine.GetTextViewPosition(pos));
            }
            return(new TextViewPosition(0, 0));
        }
        static TextViewPosition GetStartOfLineCaretPosition(int oldVC, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace)
        {
            int newVC = visualLine.GetTextLineVisualStartColumn(textLine);

            if (newVC == 0)
            {
                newVC = visualLine.GetNextCaretPosition(newVC - 1, LogicalDirection.Forward, CaretPositioningMode.WordStart, enableVirtualSpace);
            }
            if (newVC < 0)
            {
                throw ThrowUtil.NoValidCaretPosition();
            }
            // when the caret is already at the start of the text, jump to start before whitespace
            if (newVC == oldVC)
            {
                newVC = 0;
            }
            return(visualLine.GetTextViewPosition(newVC));
        }
Exemple #11
0
        Rect CalcCaretOverstrikeRectangle(VisualLine visualLine)
        {
            if (!visualColumnValid)
            {
                RevalidateVisualColumn(visualLine);
            }

            int currentPos = position.VisualColumn;
            // The text being overwritten in overstrike mode is everything up to the next normal caret stop
            int      nextPos  = visualLine.GetNextCaretPosition(currentPos, LogicalDirection.Forward, CaretPositioningMode.Normal, true);
            TextLine textLine = visualLine.GetTextLine(currentPos);

            Rect r;

            if (currentPos < visualLine.VisualLength)
            {
                // If the caret is within the text, use GetTextBounds() for the text being overwritten.
                // This is necessary to ensure the rectangle is calculated correctly in bidirectional text.
                var textBounds = textLine.GetTextBounds(currentPos, nextPos - currentPos)[0];
                r    = textBounds.Rectangle;
                r.Y += visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineTop);
            }
            else
            {
                // If the caret is at the end of the line (or in virtual space),
                // use the visual X position of currentPos and nextPos (one or more of which will be in virtual space)
                double xPos       = visualLine.GetTextLineVisualXPosition(textLine, currentPos);
                double xPos2      = visualLine.GetTextLineVisualXPosition(textLine, nextPos);
                double lineTop    = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop);
                double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom);
                r = new Rect(xPos, lineTop, xPos2 - xPos, lineBottom - lineTop);
            }
            // If the caret is too small (e.g. in front of zero-width character), ensure it's still visible
            if (r.Width < SystemParameters.CaretWidth)
            {
                r.Width = SystemParameters.CaretWidth;
            }
            return(r);
        }
Exemple #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.Location);
            int firstDocumentLineOffset = visualLine.FirstDocumentLine.Offset;

            position.VisualColumn = visualLine.ValidateVisualColumn(position, textArea.Selection.EnableVirtualSpace);

            // search possible caret positions
            int newVisualColumnForwards = visualLine.GetNextCaretPosition(position.VisualColumn - 1, LogicalDirection.Forward, CaretPositioningMode.Normal, textArea.Selection.EnableVirtualSpace);

            // 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, textArea.Selection.EnableVirtualSpace);

                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);
            }
            isInVirtualSpace = (position.VisualColumn > visualLine.VisualLength);
        }