FixVirtualIndentation() public method

Removes the indent on the caret line, if the indent mode is set to virtual and the indent matches the current virtual indent in that line.
public FixVirtualIndentation ( ) : void
return void
Example #1
0
        public static void InsertNewLine(TextEditorData data)
        {
            if (!data.CanEditSelection)
            {
                return;
            }

            using (var undo = data.OpenUndoGroup())
            {
                if (data.IsSomethingSelected)
                {
                    data.DeleteSelectedText();
                }
                switch (data.Options.IndentStyle)
                {
                case IndentStyle.None:
                    data.InsertAtCaret(data.EolMarker);
                    break;

                case IndentStyle.Auto:
                    data.EnsureCaretIsNotVirtual();
                    var sb = new StringBuilder(data.EolMarker);
                    sb.Append(data.Document.GetLineIndent(data.Caret.Line));
                    data.InsertAtCaret(sb.ToString());
                    break;

                case IndentStyle.Smart:
                    if (!data.HasIndentationTracker)
                    {
                        goto case IndentStyle.Auto;
                    }
                    NewLineSmartIndent(data);
                    break;

                case IndentStyle.Virtual:
                    if (!data.HasIndentationTracker)
                    {
                        goto case IndentStyle.Auto;
                    }
                    var oldLine   = data.Caret.Line;
                    var curLine   = data.GetLine(oldLine);
                    var indentCol = data.GetVirtualIndentationColumn(data.Caret.Location);
                    if (curLine.Length >= data.Caret.Column)
                    {
                        NewLineSmartIndent(data);
                        data.FixVirtualIndentation();
                        data.FixVirtualIndentation(oldLine);
                        break;
                    }
                    data.Insert(data.Caret.Offset, data.EolMarker);
                    data.FixVirtualIndentation(oldLine);
                    data.Caret.Column = indentCol;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Example #2
0
        static void SmartBackspace(TextEditorData data, DocumentLine line)
        {
            var prevLine        = line.PreviousLine;
            var prevLineIsEmpty = prevLine != null && prevLine.Length == 0;

            var startOffset = prevLine != null ? prevLine.EndOffset : 0;
            var count       = data.Caret.Offset - startOffset;

            if (count < 0 || startOffset >= data.Length)
            {
                return;
            }
            data.Remove(startOffset, count);
            if (prevLine != null)
            {
                if (prevLineIsEmpty)
                {
                    if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker)
                    {
                        data.InsertAtCaret(data.IndentationTracker.GetIndentationString(data.Caret.Line));
                    }
                    else
                    {
                        data.Caret.Column = data.GetVirtualIndentationColumn(prevLine.Offset);
                    }
                }
                data.FixVirtualIndentation();
            }
        }
Example #3
0
        static int PastePlainText(TextEditorData data, int offset, string text, bool preserveSelection = false, byte[] copyData = null)
        {
            int inserted = 0;
            var undo     = data.OpenUndoGroup();

            try {
                var version = data.Document.Version;
                if (!preserveSelection)
                {
                    data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != MonoDevelop.Ide.Editor.SelectionMode.Block);
                }
                int startLine = data.Caret.Line;
                data.EnsureCaretIsNotVirtual();
                if (data.IsSomethingSelected && data.MainSelection.SelectionMode == MonoDevelop.Ide.Editor.SelectionMode.Block)
                {
                    var selection            = data.MainSelection;
                    var visualInsertLocation = data.LogicalToVisualLocation(selection.Anchor);
                    var changes = new List <Microsoft.CodeAnalysis.Text.TextChange> ();

                    for (int lineNumber = selection.MinLine; lineNumber <= selection.MaxLine; lineNumber++)
                    {
                        var    lineSegment  = data.GetLine(lineNumber);
                        int    insertOffset = lineSegment.GetLogicalColumn(data, visualInsertLocation.Column) - 1;
                        string textToInsert;
                        if (lineSegment.Length < insertOffset)
                        {
                            int visualLastColumn = lineSegment.GetVisualColumn(data, lineSegment.Length + 1);
                            int charsToInsert    = visualInsertLocation.Column - visualLastColumn;
                            int spaceCount       = charsToInsert % data.Options.TabSize;
                            textToInsert = new string ('\t', (charsToInsert - spaceCount) / data.Options.TabSize) + new string (' ', spaceCount) + text;
                            insertOffset = lineSegment.Length;
                        }
                        else
                        {
                            textToInsert = text;
                        }
                        changes.Add(new Microsoft.CodeAnalysis.Text.TextChange(new Microsoft.CodeAnalysis.Text.TextSpan(lineSegment.Offset + insertOffset, 0), textToInsert));
                        inserted = textToInsert.Length;
                    }
                    data.Document.ApplyTextChanges(changes);
                }
                else
                {
                    offset   = version.MoveOffsetTo(data.Document.Version, offset);
                    inserted = data.PasteText(offset, text, copyData, ref undo);
                }
                data.FixVirtualIndentation(startLine);
            } finally {
                undo.Dispose();
            }
            return(inserted);
        }
Example #4
0
        public static void RemoveTab(TextEditorData data)
        {
            if (data.IsSomethingSelected)
            {
                if (data.CanEditSelection)
                {
                    RemoveIndentSelection(data);
                }
                return;
            }
            var line = data.Document.GetLine(data.Caret.Line);

            if (line != null)
            {
                using (var undo = data.OpenUndoGroup()) {
                    data.EnsureCaretIsNotVirtual();
                    data.Document.ApplyTextChanges(new [] { RemoveTabInLine(data, line) });
                    data.FixVirtualIndentation();
                }
            }
        }
Example #5
0
        static int PasteFrom(Clipboard clipboard, TextEditorData data, bool preserveSelection, int insertionOffset, bool preserveState)
        {
            int result = -1;

            if (!data.CanEdit(data.Document.OffsetToLineNumber(insertionOffset)))
            {
                return(result);
            }
            if (clipboard.WaitIsTargetAvailable(CopyOperation.MD_ATOM))
            {
                clipboard.RequestContents(CopyOperation.MD_ATOM, (ClipboardReceivedFunc) delegate(Clipboard clp, SelectionData selectionData) {
                    if (selectionData.Length > 0)
                    {
                        byte[] selBytes = selectionData.Data;
                        var upperBound  = System.Math.Max(0, System.Math.Min(selBytes [1], selBytes.Length - 2));
                        byte[] copyData = new byte[upperBound];
                        Array.Copy(selBytes, 2, copyData, 0, copyData.Length);
                        var rawTextOffset = 1 + 1 + copyData.Length;
                        string text       = Encoding.UTF8.GetString(selBytes, rawTextOffset, selBytes.Length - rawTextOffset);
                        bool pasteBlock   = (selBytes [0] & 1) == 1;
                        bool pasteLine    = (selBytes [0] & 2) == 2;
                        if (pasteBlock)
                        {
                            using (var undo = data.OpenUndoGroup()) {
                                var version = data.Document.Version;
                                if (!preserveSelection)
                                {
                                    data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != MonoDevelop.Ide.Editor.SelectionMode.Block);
                                }
                                int startLine = data.Caret.Line;
                                data.EnsureCaretIsNotVirtual();
                                insertionOffset = version.MoveOffsetTo(data.Document.Version, insertionOffset);

                                data.Caret.PreserveSelection = true;
                                var lines  = new List <string> ();
                                int offset = 0;
                                while (true)
                                {
                                    var delimiter = LineSplitter.NextDelimiter(text, offset);
                                    if (delimiter.IsInvalid)
                                    {
                                        break;
                                    }

                                    int delimiterEndOffset = delimiter.EndOffset;
                                    lines.Add(text.Substring(offset, delimiter.Offset - offset));
                                    offset = delimiterEndOffset;
                                }
                                if (offset < text.Length)
                                {
                                    lines.Add(text.Substring(offset, text.Length - offset));
                                }

                                int lineNr = data.Document.OffsetToLineNumber(insertionOffset);
                                int col    = insertionOffset - data.Document.GetLine(lineNr).Offset;
                                int visCol = data.Document.GetLine(lineNr).GetVisualColumn(data, col);
                                DocumentLine curLine;
                                int lineCol = col;
                                result      = 0;
                                for (int i = 0; i < lines.Count; i++)
                                {
                                    while (data.Document.LineCount <= lineNr + i)
                                    {
                                        data.Insert((int)data.Document.Length, Environment.NewLine);
                                        result += Environment.NewLine.Length;
                                    }
                                    curLine = data.Document.GetLine(lineNr + i);
                                    if (lines [i].Length > 0)
                                    {
                                        lineCol = curLine.GetLogicalColumn(data, visCol);
                                        if (curLine.Length + 1 < lineCol)
                                        {
                                            result += lineCol - curLine.Length;
                                            data.Insert(curLine.Offset + curLine.Length, new string (' ', lineCol - curLine.Length));
                                        }
                                        data.Insert(curLine.Offset + lineCol, lines [i]);
                                        result += lines [i].Length;
                                    }
                                    if (!preserveState)
                                    {
                                        data.Caret.Offset = curLine.Offset + lineCol + lines [i].Length;
                                    }
                                }
                                if (!preserveState)
                                {
                                    data.ClearSelection();
                                }
                                data.FixVirtualIndentation(startLine);
                                data.Caret.PreserveSelection = false;
                            }
                        }
                        else if (pasteLine)
                        {
                            using (var undo = data.OpenUndoGroup()) {
                                if (!preserveSelection)
                                {
                                    data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != MonoDevelop.Ide.Editor.SelectionMode.Block);
                                }
                                data.EnsureCaretIsNotVirtual();

                                data.Caret.PreserveSelection = true;
                                result = text.Length;
                                DocumentLine curLine = data.Document.GetLine(data.Caret.Line);
                                result = PastePlainText(data, curLine.Offset, text + data.EolMarker, preserveSelection, copyData);
                                if (!preserveState)
                                {
                                    data.ClearSelection();
                                }
                                data.Caret.PreserveSelection = false;
                                data.FixVirtualIndentation(curLine.LineNumber);
                            }
                        }
                        else
                        {
                            result = PastePlainText(data, insertionOffset, text, preserveSelection, copyData);
                        }
                    }
                });
                // we got MD_ATOM text - no need to request text. (otherwise buffer may get copied twice).
                return(result);
            }

            if (result < 0 && clipboard.WaitIsTextAvailable())
            {
                clipboard.RequestText(delegate(Clipboard clp, string text) {
                    if (string.IsNullOrEmpty(text))
                    {
                        return;
                    }
                    result = PastePlainText(data, insertionOffset, text, preserveSelection);
                });
            }

            return(result);
        }
Example #6
0
        public static void InsertNewLine(TextEditorData data)
        {
            if (!data.CanEditSelection)
            {
                return;
            }

            using (var undo = data.OpenUndoGroup()) {
                if (data.IsSomethingSelected)
                {
                    var end = data.MainSelection.End;
                    data.DeleteSelectedText();
                    if (end.Column == 1)
                    {
                        CaretMoveActions.InternalCaretMoveHome(data, true, false);
                        return;
                    }
                }
                switch (data.Options.IndentStyle)
                {
                case IndentStyle.None:
                    data.InsertAtCaret(data.EolMarker);
                    break;

                case IndentStyle.Auto:
                    data.EnsureCaretIsNotVirtual();
                    var indent = data.Document.GetLineIndent(data.Caret.Line);
                    data.InsertAtCaret(data.EolMarker);
                    data.EnsureCaretIsNotVirtual();
                    if (data.GetLine(data.Caret.Line).Length == 0)
                    {
                        data.InsertAtCaret(indent);
                    }
                    break;

                case IndentStyle.Smart:
                    if (!data.HasIndentationTracker)
                    {
                        goto case IndentStyle.Auto;
                    }
                    NewLineSmartIndent(data);
                    break;

                case IndentStyle.Virtual:
                    if (!data.HasIndentationTracker)
                    {
                        goto case IndentStyle.Auto;
                    }
                    var oldLine   = data.Caret.Line;
                    var curLine   = data.GetLine(oldLine);
                    var indentCol = data.GetVirtualIndentationColumn(data.Caret.Location);
                    if (curLine.Length >= data.Caret.Column)
                    {
                        NewLineSmartIndent(data);
                        data.FixVirtualIndentation();
                        data.FixVirtualIndentation(oldLine);
                        break;
                    }
                    data.Insert(data.Caret.Offset, data.EolMarker);
                    data.FixVirtualIndentation(oldLine);
                    data.Caret.Column = indentCol;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
Example #7
0
        public static void Delete(TextEditorData data)
        {
            if (!data.CanEditSelection)
            {
                return;
            }

            using (var undoGroup = data.OpenUndoGroup()) {
                if (data.IsSomethingSelected)
                {
                    // case: zero width block selection
                    if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column)
                    {
                        var col = data.MainSelection.Lead.Column;
                        if (col <= DocumentLocation.MinColumn)
                        {
                            data.ClearSelection();
                            return;
                        }
                        bool preserve = data.Caret.PreserveSelection;
                        data.Caret.PreserveSelection = true;
                        col--;
                        var changes = new List <Microsoft.CodeAnalysis.Text.TextChange> ();

                        for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++)
                        {
                            DocumentLine lineSegment = data.Document.GetLine(lineNumber);
                            if (col < lineSegment.Length)
                            {
                                changes.Add(new Microsoft.CodeAnalysis.Text.TextChange(new Microsoft.CodeAnalysis.Text.TextSpan(lineSegment.Offset + col, 1), ""));
                            }
                        }
                        data.Document.ApplyTextChanges(changes);

                        data.Caret.PreserveSelection = preserve;
                        data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                        return;
                    }
                    data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block);
                    return;
                }
                if (data.Caret.Offset >= data.Document.Length)
                {
                    return;
                }

                data.EnsureCaretIsNotVirtual();

                DocumentLine line = data.Document.GetLine(data.Caret.Line);
                if (data.Caret.Column == line.Length + 1)
                {
                    if (data.Caret.Line < data.Document.LineCount)
                    {
                        var deletionLength = line.DelimiterLength;
                        // smart backspace (delete indentation)
                        if (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual)
                        {
                            var next = line.NextLine;
                            if (next != null)
                            {
                                if (data.HasIndentationTracker)
                                {
                                    var lineIndentation = next.GetIndentation(data.Document);
                                    if (lineIndentation.StartsWith(data.IndentationTracker.GetIndentationString(next.LineNumber)))
                                    {
                                        deletionLength += lineIndentation.Length;
                                    }
                                }
                            }
                        }

                        data.Remove(line.EndOffsetIncludingDelimiter - line.DelimiterLength, deletionLength);
                        if (line.EndOffsetIncludingDelimiter == data.Document.Length)
                        {
                            line.UnicodeNewline = UnicodeNewline.Unknown;
                        }
                    }
                }
                else
                {
                    var o = data.Caret.Offset;
                    if (((ushort)data.GetCharAt(o) & CaretMoveActions.HighSurrogateMarker) == CaretMoveActions.HighSurrogateMarker)
                    {
                        data.Remove(o, 2);
                    }
                    else
                    {
                        data.Remove(o, 1);
                    }
                    data.Document.CommitLineUpdate(data.Caret.Line);
                }
                data.FixVirtualIndentation();
            }
        }
Example #8
0
        public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret)
        {
            if (!data.CanEditSelection)
            {
                return;
            }
            DocumentLine line;
            bool         smartBackspace = false;

            using (var undo = data.OpenUndoGroup()) {
                if (data.IsSomethingSelected)
                {
                    var visualAnchorLocation = data.LogicalToVisualLocation(data.MainSelection.Anchor);
                    var visualLeadLocation   = data.LogicalToVisualLocation(data.MainSelection.Lead);
                    // case: zero width block selection
                    if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column)
                    {
                        var col = data.MainSelection.Lead.Column;
                        if (col <= DocumentLocation.MinColumn)
                        {
                            data.ClearSelection();
                            return;
                        }
                        bool preserve = data.Caret.PreserveSelection;
                        data.Caret.PreserveSelection = true;
                        var changes = new List <Microsoft.CodeAnalysis.Text.TextChange> ();

                        for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++)
                        {
                            var lineSegment  = data.Document.GetLine(lineNumber);
                            int insertOffset = lineSegment.GetLogicalColumn(data, visualAnchorLocation.Column - 1) - 1;
                            changes.Add(new Microsoft.CodeAnalysis.Text.TextChange(new Microsoft.CodeAnalysis.Text.TextSpan(lineSegment.Offset + insertOffset, 1), ""));
                        }
                        data.Document.ApplyTextChanges(changes);

                        var visualColumn = data.GetLine(data.Caret.Location.Line).GetVisualColumn(data, col - 1);
                        data.MainSelection = new MonoDevelop.Ide.Editor.Selection(
                            new DocumentLocation(data.MainSelection.Anchor.Line, data.GetLine(data.MainSelection.Anchor.Line).GetLogicalColumn(data, visualColumn)),
                            new DocumentLocation(data.MainSelection.Lead.Line, data.GetLine(data.MainSelection.Lead.Line).GetLogicalColumn(data, visualColumn)),
                            SelectionMode.Block
                            );

                        data.Caret.PreserveSelection = preserve;
                        data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                        return;
                    }
                    data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block);
                    return;
                }

                if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn)
                {
                    return;
                }

                // Virtual indentation needs to be fixed before to have the same behavior
                // if it's there or not (otherwise user has to press multiple backspaces in some cases)
                data.EnsureCaretIsNotVirtual();

                line = data.Document.GetLine(data.Caret.Line);
                // smart backspace (delete indentation)
                if (data.HasIndentationTracker && (data.IndentationTracker.SupportedFeatures & IndentationTrackerFeatures.SmartBackspace) != 0 && (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual) && data.Options.SmartBackspace)
                {
                    if (data.Caret.Column == data.GetVirtualIndentationColumn(data.Caret.Location))
                    {
                        bool isAllIndent = line.GetIndentation(data.Document).Length == data.Caret.Column - 1;
                        if (isAllIndent)
                        {
                            if (!data.Options.GenerateFormattingUndoStep)
                            {
                                SmartBackspace(data, line);
                                return;
                            }
                            smartBackspace = true;
                        }
                    }
                }

                // normal backspace.
                if (data.Caret.Column > line.Length + 1)
                {
                    data.Caret.Column = line.Length + 1;
                }
                else if (data.Caret.Offset == line.Offset)
                {
                    DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1);
                    if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual)
                    {
                        data.Caret.Location = new DocumentLocation(data.Caret.Line - 1, data.GetVirtualIndentationColumn(data.Caret.Line - 1, 1));
                        data.Replace(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.GetIndentationString(data.Caret.Line - 1, 1));
                    }
                    else
                    {
                        data.Remove(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength);
                    }
                }
                else
                {
                    removeCharBeforeCaret(data);
                }

                // Needs to be fixed after, the line may just contain the indentation
                data.FixVirtualIndentation();
            }

            if (data.Options.GenerateFormattingUndoStep && smartBackspace)
            {
                using (var undo = data.OpenUndoGroup()) {
                    data.EnsureCaretIsNotVirtual();
                    SmartBackspace(data, line);
                }
            }
        }
Example #9
0
        static int PasteFrom(TextEditorData data, bool preserveSelection, int insertionOffset, bool preserveState)
        {
            int result = -1;

            if (!data.CanEdit(data.Document.OffsetToLineNumber(insertionOffset)))
            {
                return(result);
            }
            if (Clipboard.ContainsData <byte[]>())
            {
                byte[] selBytes   = Clipboard.GetData <byte[]>();
                var    upperBound = System.Math.Max(0, System.Math.Min(selBytes[1], selBytes.Length - 2));
                byte[] copyData   = new byte[upperBound];
                Array.Copy(selBytes, 2, copyData, 0, copyData.Length);
                var    rawTextOffset = 1 + 1 + copyData.Length;
                string text          = Encoding.UTF8.GetString(selBytes, rawTextOffset, selBytes.Length - rawTextOffset);
                bool   pasteBlock    = (selBytes[0] & 1) == 1;
                bool   pasteLine     = (selBytes[0] & 2) == 2;
                if (pasteBlock)
                {
                    using (var undo = data.OpenUndoGroup())
                    {
                        var version = data.Document.Version;
                        if (!preserveSelection)
                        {
                            data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block);
                        }
                        int startLine = data.Caret.Line;
                        data.EnsureCaretIsNotVirtual();
                        insertionOffset = version.MoveOffsetTo(data.Document.Version, insertionOffset);

                        data.Caret.PreserveSelection = true;
                        var lines  = new List <string>();
                        int offset = 0;
                        while (true)
                        {
                            var delimiter = LineSplitter.NextDelimiter(text, offset);
                            if (delimiter.IsInvalid)
                            {
                                break;
                            }

                            int delimiterEndOffset = delimiter.EndOffset;
                            lines.Add(text.Substring(offset, delimiter.Offset - offset));
                            offset = delimiterEndOffset;
                        }
                        if (offset < text.Length)
                        {
                            lines.Add(text.Substring(offset, text.Length - offset));
                        }

                        int          lineNr = data.Document.OffsetToLineNumber(insertionOffset);
                        int          col    = insertionOffset - data.Document.GetLine(lineNr).Offset;
                        int          visCol = data.Document.GetLine(lineNr).GetVisualColumn(data, col);
                        DocumentLine curLine;
                        int          lineCol = col;
                        result = 0;
                        for (int i = 0; i < lines.Count; i++)
                        {
                            while (data.Document.LineCount <= lineNr + i)
                            {
                                data.Insert(data.Document.TextLength, Environment.NewLine);
                                result += Environment.NewLine.Length;
                            }
                            curLine = data.Document.GetLine(lineNr + i);
                            if (lines[i].Length > 0)
                            {
                                lineCol = curLine.GetLogicalColumn(data, visCol);
                                if (curLine.Length + 1 < lineCol)
                                {
                                    result += lineCol - curLine.Length;
                                    data.Insert(curLine.Offset + curLine.Length, new string(' ', lineCol - curLine.Length));
                                }
                                data.Insert(curLine.Offset + lineCol, lines[i]);
                                result += lines[i].Length;
                            }
                            if (!preserveState)
                            {
                                data.Caret.Offset = curLine.Offset + lineCol + lines[i].Length;
                            }
                        }
                        if (!preserveState)
                        {
                            data.ClearSelection();
                        }
                        data.FixVirtualIndentation(startLine);
                        data.Caret.PreserveSelection = false;
                    }
                }
                else if (pasteLine)
                {
                    using (var undo = data.OpenUndoGroup())
                    {
                        if (!preserveSelection)
                        {
                            data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block);
                        }
                        data.EnsureCaretIsNotVirtual();

                        data.Caret.PreserveSelection = true;
                        result = text.Length;
                        DocumentLine curLine = data.Document.GetLine(data.Caret.Line);

                        result = PastePlainText(data, curLine.Offset, text + data.EolMarker, preserveSelection, copyData);
                        if (!preserveState)
                        {
                            data.ClearSelection();
                        }
                        data.Caret.PreserveSelection = false;
                        data.FixVirtualIndentation(curLine.LineNumber);
                    }
                }
                else
                {
                    result = PastePlainText(data, insertionOffset, text, preserveSelection, copyData);
                }
            }
            else if (Clipboard.ContainsData(TransferDataType.Text))
            {
                var text = Clipboard.GetText();
                result = PastePlainText(data, insertionOffset, text, preserveState);
            }



            return(result);
        }
Example #10
0
        public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret)
        {
            if (!data.CanEditSelection)
            {
                return;
            }
            using (var undo = data.OpenUndoGroup()) {
                if (data.IsSomethingSelected)
                {
                    var visualAnchorLocation = data.LogicalToVisualLocation(data.MainSelection.Anchor);
                    var visualLeadLocation   = data.LogicalToVisualLocation(data.MainSelection.Lead);
                    // case: zero width block selection
                    if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column)
                    {
                        var col = data.MainSelection.Lead.Column;
                        if (col <= DocumentLocation.MinColumn)
                        {
                            data.ClearSelection();
                            return;
                        }
                        bool preserve = data.Caret.PreserveSelection;
                        data.Caret.PreserveSelection = true;
                        for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++)
                        {
                            var lineSegment  = data.Document.GetLine(lineNumber);
                            int insertOffset = lineSegment.GetLogicalColumn(data, visualAnchorLocation.Column - 1) - 1;
                            data.Remove(lineSegment.Offset + insertOffset, 1);
                        }

                        var visualColumn = data.GetLine(data.Caret.Location.Line).GetVisualColumn(data, col - 1);
                        data.MainSelection = new Selection(
                            new DocumentLocation(data.MainSelection.Anchor.Line, data.GetLine(data.MainSelection.Anchor.Line).GetLogicalColumn(data, visualColumn)),
                            new DocumentLocation(data.MainSelection.Lead.Line, data.GetLine(data.MainSelection.Lead.Line).GetLogicalColumn(data, visualColumn)),
                            SelectionMode.Block
                            );

                        data.Caret.PreserveSelection = preserve;
                        data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                        return;
                    }
                    data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block);
                    return;
                }

                if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn)
                {
                    return;
                }

                // Virtual indentation needs to be fixed before to have the same behavior
                // if it's there or not (otherwise user has to press multiple backspaces in some cases)
                data.EnsureCaretIsNotVirtual();
                DocumentLine line = data.Document.GetLine(data.Caret.Line);
                if (data.Caret.Column > line.Length + 1)
                {
                    data.Caret.Column = line.Length + 1;
                }
                else if (data.Caret.Offset == line.Offset)
                {
                    DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1);
                    if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual)
                    {
                        data.Caret.Location = new DocumentLocation(data.Caret.Line - 1, data.IndentationTracker.GetVirtualIndentationColumn(data.Caret.Line - 1, 1));
                        data.Replace(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.IndentationTracker.GetIndentationString(data.Caret.Line - 1, 1));
                    }
                    else
                    {
                        data.Remove(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength);
                    }
                }
                else
                {
                    removeCharBeforeCaret(data);
                }

                // Needs to be fixed after, the line may just contain the indentation
                data.FixVirtualIndentation();
            }
        }
Example #11
0
		public static void Delete (TextEditorData data)
		{
			if (!data.CanEditSelection)
				return;

			using (var undoGroup = data.OpenUndoGroup ()) {
				if (data.IsSomethingSelected) {
					// case: zero width block selection
					if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) {
						var col = data.MainSelection.Lead.Column;
						if (col <= DocumentLocation.MinColumn) {
							data.ClearSelection ();
							return;
						}
						bool preserve = data.Caret.PreserveSelection;
						data.Caret.PreserveSelection = true;
						col--;
						for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) {
							DocumentLine lineSegment = data.Document.GetLine (lineNumber);
							if (col < lineSegment.Length)
								data.Remove (lineSegment.Offset + col, 1);
						}
						data.Caret.PreserveSelection = preserve;
						data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine);
						return;
					}
					data.DeleteSelectedText (data.MainSelection.SelectionMode != SelectionMode.Block);
					return;
				}
				if (data.Caret.Offset >= data.Document.TextLength)
					return;

				data.EnsureCaretIsNotVirtual ();

				DocumentLine line = data.Document.GetLine (data.Caret.Line);
				if (data.Caret.Column == line.Length + 1) {
					if (data.Caret.Line < data.Document.LineCount) { 
						data.Remove (line.EndOffsetIncludingDelimiter - line.DelimiterLength, line.DelimiterLength);
						if (line.EndOffsetIncludingDelimiter == data.Document.TextLength)
							line.UnicodeNewline = UnicodeNewline.Unknown;
					}
				} else {
					data.Remove (data.Caret.Offset, 1); 
					data.Document.CommitLineUpdate (data.Caret.Line);
				}
				data.FixVirtualIndentation ();
			}
		}
Example #12
0
		public static void Backspace (TextEditorData data, Action<TextEditorData> removeCharBeforeCaret)
		{
			if (!data.CanEditSelection)
				return;
			using (var undo = data.OpenUndoGroup ()) {
				if (data.IsSomethingSelected) {
					var visualAnchorLocation = data.LogicalToVisualLocation (data.MainSelection.Anchor);
					var visualLeadLocation = data.LogicalToVisualLocation (data.MainSelection.Lead);
					// case: zero width block selection
					if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column) {
						var col = data.MainSelection.Lead.Column;
						if (col <= DocumentLocation.MinColumn) {
							data.ClearSelection ();
							return;
						}
						bool preserve = data.Caret.PreserveSelection;
						data.Caret.PreserveSelection = true;
						for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) {
							var lineSegment = data.Document.GetLine (lineNumber);
							int insertOffset = lineSegment.GetLogicalColumn (data, visualAnchorLocation.Column - 1) - 1;
							data.Remove (lineSegment.Offset + insertOffset, 1);
						}

						var visualColumn = data.GetLine (data.Caret.Location.Line).GetVisualColumn (data, col - 1);
						data.MainSelection = new Selection (
							new DocumentLocation (data.MainSelection.Anchor.Line, data.GetLine (data.MainSelection.Anchor.Line).GetLogicalColumn (data, visualColumn)),
							new DocumentLocation (data.MainSelection.Lead.Line, data.GetLine (data.MainSelection.Lead.Line).GetLogicalColumn (data, visualColumn)),
							SelectionMode.Block
						);

						data.Caret.PreserveSelection = preserve;
						data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine);
						return;
					}
					data.DeleteSelectedText (data.MainSelection.SelectionMode != SelectionMode.Block);
					return;
				}

				if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn)
					return;
			
				// Virtual indentation needs to be fixed before to have the same behavior
				// if it's there or not (otherwise user has to press multiple backspaces in some cases)
				data.EnsureCaretIsNotVirtual ();
				DocumentLine line = data.Document.GetLine (data.Caret.Line);
				if (data.Caret.Column > line.Length + 1) {
					data.Caret.Column = line.Length + 1;
				} else if (data.Caret.Offset == line.Offset) {
					DocumentLine lineAbove = data.Document.GetLine (data.Caret.Line - 1);
					if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) {
						data.Caret.Location = new DocumentLocation (data.Caret.Line - 1, data.IndentationTracker.GetVirtualIndentationColumn (data.Caret.Line - 1, 1));
						data.Replace (lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.IndentationTracker.GetIndentationString (data.Caret.Line - 1, 1));
					} else {
						data.Remove (lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength);
					}
				} else {
					removeCharBeforeCaret (data);
				}

				// Needs to be fixed after, the line may just contain the indentation
				data.FixVirtualIndentation ();
			}
		}
Example #13
0
		public static void Backspace (TextEditorData data, Action<TextEditorData> removeCharBeforeCaret)
		{
			if (!data.CanEditSelection)
				return;
			if (data.IsSomethingSelected) {
				// case: zero width block selection
				if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) {
					var col = data.MainSelection.Lead.Column;
					if (col <= DocumentLocation.MinColumn) {
						data.ClearSelection ();
						return;
					}
					bool preserve = data.Caret.PreserveSelection;
					data.Caret.PreserveSelection = true;
					col--;
					for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) {
						data.Remove (data.Document.GetLine (lineNumber).Offset + col - 1, 1);
					}
					data.MainSelection.Lead = new DocumentLocation (data.MainSelection.Lead.Line, col);
					data.MainSelection.Anchor = new DocumentLocation (data.MainSelection.Anchor.Line, col);
					data.Caret.PreserveSelection = preserve;
					data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine);
					return;
				}
				data.DeleteSelectedText (data.MainSelection.SelectionMode != SelectionMode.Block);
				return;
			}

			if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn)
				return;
			
			// Virtual indentation needs to be fixed before to have the same behavior
			// if it's there or not (otherwise user has to press multiple backspaces in some cases)
			data.EnsureCaretIsNotVirtual ();
			DocumentLine line = data.Document.GetLine (data.Caret.Line);
			if (data.Caret.Column > line.Length + 1) {
				data.Caret.Column = line.Length + 1;
			} else if (data.Caret.Offset == line.Offset) {
				DocumentLine lineAbove = data.Document.GetLine (data.Caret.Line - 1);
				data.Remove (lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength);
			} else {
				removeCharBeforeCaret (data);
			}

			// Needs to be fixed after, the line may just contain the indentation
			data.FixVirtualIndentation ();
		}
Example #14
0
		static int PastePlainText (TextEditorData data, int offset, string text, bool preserveSelection = false, byte[] copyData = null)
		{
			int inserted = 0;
			var undo = data.OpenUndoGroup ();
			var version = data.Document.Version;
			if (!preserveSelection)
				data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block);
			int startLine = data.Caret.Line;
			data.EnsureCaretIsNotVirtual ();
			if (data.IsSomethingSelected && data.MainSelection.SelectionMode == SelectionMode.Block) {
				var selection = data.MainSelection;
				var visualInsertLocation = data.LogicalToVisualLocation (selection.Anchor);
				for (int lineNumber = selection.MinLine; lineNumber <= selection.MaxLine; lineNumber++) {
					var lineSegment = data.GetLine (lineNumber);
					int insertOffset = lineSegment.GetLogicalColumn (data, visualInsertLocation.Column) - 1;
					string textToInsert;
					if (lineSegment.Length < insertOffset) {
						int visualLastColumn = lineSegment.GetVisualColumn (data, lineSegment.Length + 1);
						int charsToInsert = visualInsertLocation.Column - visualLastColumn;
						int spaceCount = charsToInsert % data.Options.TabSize;
						textToInsert = new string ('\t', (charsToInsert - spaceCount) / data.Options.TabSize) + new string (' ', spaceCount) + text;
						insertOffset = lineSegment.Length;
					} else {
						textToInsert = text;
					}
					inserted = data.Insert (lineSegment.Offset + insertOffset, textToInsert);
				}
			} else {
				offset = version.MoveOffsetTo (data.Document.Version, offset);
				inserted = data.PasteText (offset, text, copyData, ref undo);
			}
			data.FixVirtualIndentation (startLine); 

			undo.Dispose ();
			return inserted;
		}
Example #15
0
		static int PasteFrom (Clipboard clipboard, TextEditorData data, bool preserveSelection, int insertionOffset, bool preserveState)
		{
			int result = -1;
			if (!data.CanEdit (data.Document.OffsetToLineNumber (insertionOffset)))
				return result;
			if (clipboard.WaitIsTargetAvailable (CopyOperation.MD_ATOM)) {
				clipboard.RequestContents (CopyOperation.MD_ATOM, delegate(Clipboard clp, SelectionData selectionData) {
					if (selectionData.Length > 0) {
						byte[] selBytes = selectionData.Data;
						var upperBound = System.Math.Max (0, System.Math.Min (selBytes [1], selBytes.Length - 2));
						byte[] copyData = new byte[upperBound];
						Array.Copy (selBytes, 2, copyData, 0, copyData.Length);
						var rawTextOffset = 1 + 1 + copyData.Length;
						string text = Encoding.UTF8.GetString (selBytes, rawTextOffset, selBytes.Length - rawTextOffset);
						bool pasteBlock = (selBytes [0] & 1) == 1;
						bool pasteLine = (selBytes [0] & 2) == 2;
						if (pasteBlock) {
							using (var undo = data.OpenUndoGroup ()) {
								var version = data.Document.Version;
								if (!preserveSelection)
									data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block);
								int startLine = data.Caret.Line;
								data.EnsureCaretIsNotVirtual ();
								insertionOffset = version.MoveOffsetTo (data.Document.Version, insertionOffset);

								data.Caret.PreserveSelection = true;
								var lines = new List<string> ();
								int offset = 0;
								while (true) {
									var delimiter = LineSplitter.NextDelimiter (text, offset);
									if (delimiter.IsInvalid)
										break;

									int delimiterEndOffset = delimiter.EndOffset;
									lines.Add (text.Substring (offset, delimiter.Offset - offset));
									offset = delimiterEndOffset;
								}
								if (offset < text.Length)
									lines.Add (text.Substring (offset, text.Length - offset));

								int lineNr = data.Document.OffsetToLineNumber (insertionOffset);
								int col = insertionOffset - data.Document.GetLine (lineNr).Offset;
								int visCol = data.Document.GetLine (lineNr).GetVisualColumn (data, col);
								DocumentLine curLine;
								int lineCol = col;
								result = 0;
								for (int i = 0; i < lines.Count; i++) {
									while (data.Document.LineCount <= lineNr + i) {
										data.Insert (data.Document.TextLength, Environment.NewLine);
										result += Environment.NewLine.Length;
									}
									curLine = data.Document.GetLine (lineNr + i);
									if (lines [i].Length > 0) {
										lineCol = curLine.GetLogicalColumn (data, visCol);
										if (curLine.Length + 1 < lineCol) {
											result += lineCol - curLine.Length;
											data.Insert (curLine.Offset + curLine.Length, new string (' ', lineCol - curLine.Length));
										}
										data.Insert (curLine.Offset + lineCol, lines [i]);
										result += lines [i].Length;
									}
									if (!preserveState)
										data.Caret.Offset = curLine.Offset + lineCol + lines [i].Length;
								}
								if (!preserveState)
									data.ClearSelection ();
								data.FixVirtualIndentation (startLine); 
								data.Caret.PreserveSelection = false;
							}
						} else if (pasteLine) {
							using (var undo = data.OpenUndoGroup ()) {
								if (!preserveSelection)
									data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block);
								data.EnsureCaretIsNotVirtual ();

								data.Caret.PreserveSelection = true;
								result = text.Length;
								DocumentLine curLine = data.Document.GetLine (data.Caret.Line);

								result = PastePlainText (data, curLine.Offset,  text + data.EolMarker, preserveSelection, copyData);
								if (!preserveState)
									data.ClearSelection ();
								data.Caret.PreserveSelection = false;
								data.FixVirtualIndentation (curLine.LineNumber); 
							}
						} else {
							result = PastePlainText (data, insertionOffset, text, preserveSelection, copyData);
						}
					}
				});
				// we got MD_ATOM text - no need to request text. (otherwise buffer may get copied twice).
				return result;
			}
			
			if (result < 0 && clipboard.WaitIsTextAvailable ()) {
				clipboard.RequestText (delegate(Clipboard clp, string text) {
					if (string.IsNullOrEmpty (text))
						return;
					result = PastePlainText (data, insertionOffset, text, preserveSelection);
				});
			}
			
			return result;
		}
		static void SmartBackspace (TextEditorData data, DocumentLine line)
		{
			var prevLine = line.PreviousLine;
			var prevLineIsEmpty = prevLine != null && prevLine.Length == 0;

			var startOffset = prevLine != null ? prevLine.EndOffset : 0;
			var count = data.Caret.Offset - startOffset;
			if (count < 0)
				return;
			data.Remove (startOffset, count);
			if (prevLine != null) {
				if (prevLineIsEmpty) {
					if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker) {
						data.InsertAtCaret (data.IndentationTracker.GetIndentationString (data.Caret.Offset));
					} else {
						data.Caret.Column = data.GetVirtualIndentationColumn (prevLine.Offset);
					}
				}
				data.FixVirtualIndentation ();
			}
		}
		public static void InsertNewLine (TextEditorData data)
		{
			if (!data.CanEditSelection)
				return;
			
			using (var undo = data.OpenUndoGroup ()) {
				if (data.IsSomethingSelected)
					data.DeleteSelectedText ();
				switch (data.Options.IndentStyle) {
				case IndentStyle.None:
					data.InsertAtCaret (data.EolMarker);
					break;
				case IndentStyle.Auto:
					data.EnsureCaretIsNotVirtual ();
					var sb = new StringBuilder (data.EolMarker);
					sb.Append (data.Document.GetLineIndent (data.Caret.Line));
					data.InsertAtCaret (sb.ToString ());
					break;
				case IndentStyle.Smart:
					if (!data.HasIndentationTracker)
						goto case IndentStyle.Auto;
					NewLineSmartIndent (data);
					break;
				case IndentStyle.Virtual:
					if (!data.HasIndentationTracker)
						goto case IndentStyle.Auto;
					var oldLine = data.Caret.Line;
					var curLine = data.GetLine (oldLine);
					var indentCol = data.GetVirtualIndentationColumn (data.Caret.Location);
					if (curLine.Length >= data.Caret.Column) {
						NewLineSmartIndent (data);
						data.FixVirtualIndentation ();
						data.FixVirtualIndentation (oldLine);
						break;
					}
					data.Insert (data.Caret.Offset, data.EolMarker);
					data.FixVirtualIndentation (oldLine);
					data.Caret.Column = indentCol;
					break;
				default:
					throw new ArgumentOutOfRangeException ();
				}
			}
		}
Example #18
0
		public static void InsertNewLine (TextEditorData data)
		{
			if (!data.CanEditSelection)
				return;
			
			using (var undo = data.OpenUndoGroup ()) {
				if (data.IsSomethingSelected) {
					var end = data.MainSelection.End;
					data.DeleteSelectedText ();
					if (end.Column == 1) {
						CaretMoveActions.InternalCaretMoveHome (data, true, false);
						return;
					}
				}
				switch (data.Options.IndentStyle) {
				case IndentStyle.None:
					data.InsertAtCaret (data.EolMarker);
					break;
				case IndentStyle.Auto:
					data.EnsureCaretIsNotVirtual ();
					var indent = data.Document.GetLineIndent (data.Caret.Line);
					data.InsertAtCaret (data.EolMarker);
					data.EnsureCaretIsNotVirtual ();
					if (data.GetLine (data.Caret.Line).Length == 0)
						data.InsertAtCaret (indent);
					break;
				case IndentStyle.Smart:
					if (!data.HasIndentationTracker)
						goto case IndentStyle.Auto;
					NewLineSmartIndent (data);
					break;
				case IndentStyle.Virtual:
					if (!data.HasIndentationTracker)
						goto case IndentStyle.Auto;
					var oldLine = data.Caret.Line;
					var curLine = data.GetLine (oldLine);
					var indentCol = data.GetVirtualIndentationColumn (data.Caret.Location);
					if (curLine.Length >= data.Caret.Column) {
						NewLineSmartIndent (data);
						data.FixVirtualIndentation ();
						data.FixVirtualIndentation (oldLine);
						break;
					}
					data.Insert (data.Caret.Offset, data.EolMarker);
					data.FixVirtualIndentation (oldLine);
					data.Caret.Column = indentCol;
					break;
				default:
					throw new ArgumentOutOfRangeException ();
				}
			}
		}
Example #19
0
        public static void Delete(TextEditorData data)
        {
            if (!data.CanEditSelection)
            {
                return;
            }

            using (var undoGroup = data.OpenUndoGroup()) {
                if (data.IsSomethingSelected)
                {
                    // case: zero width block selection
                    if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column)
                    {
                        var col = data.MainSelection.Lead.Column;
                        if (col <= DocumentLocation.MinColumn)
                        {
                            data.ClearSelection();
                            return;
                        }
                        bool preserve = data.Caret.PreserveSelection;
                        data.Caret.PreserveSelection = true;
                        col--;
                        for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++)
                        {
                            DocumentLine lineSegment = data.Document.GetLine(lineNumber);
                            if (col < lineSegment.Length)
                            {
                                data.Remove(lineSegment.Offset + col, 1);
                            }
                        }
                        data.Caret.PreserveSelection = preserve;
                        data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                        return;
                    }
                    data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block);
                    return;
                }
                if (data.Caret.Offset >= data.Document.TextLength)
                {
                    return;
                }

                data.EnsureCaretIsNotVirtual();

                DocumentLine line = data.Document.GetLine(data.Caret.Line);
                if (data.Caret.Column == line.Length + 1)
                {
                    if (data.Caret.Line < data.Document.LineCount)
                    {
                        data.Remove(line.EndOffsetIncludingDelimiter - line.DelimiterLength, line.DelimiterLength);
                        if (line.EndOffsetIncludingDelimiter == data.Document.TextLength)
                        {
                            line.UnicodeNewline = UnicodeNewline.Unknown;
                        }
                    }
                }
                else
                {
                    data.Remove(data.Caret.Offset, 1);
                    data.Document.CommitLineUpdate(data.Caret.Line);
                }
                data.FixVirtualIndentation();
            }
        }
Example #20
0
        public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret)
        {
            if (!data.CanEditSelection)
            {
                return;
            }
            if (data.IsSomethingSelected)
            {
                // case: zero width block selection
                if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column)
                {
                    var col = data.MainSelection.Lead.Column;
                    if (col <= DocumentLocation.MinColumn)
                    {
                        data.ClearSelection();
                        return;
                    }
                    bool preserve = data.Caret.PreserveSelection;
                    data.Caret.PreserveSelection = true;
                    col--;
                    for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++)
                    {
                        data.Remove(data.Document.GetLine(lineNumber).Offset + col - 1, 1);
                    }
                    data.MainSelection.Lead      = new DocumentLocation(data.MainSelection.Lead.Line, col);
                    data.MainSelection.Anchor    = new DocumentLocation(data.MainSelection.Anchor.Line, col);
                    data.Caret.PreserveSelection = preserve;
                    data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine);
                    return;
                }
                data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block);
                return;
            }

            if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn)
            {
                return;
            }

            // Virtual indentation needs to be fixed before to have the same behavior
            // if it's there or not (otherwise user has to press multiple backspaces in some cases)
            data.EnsureCaretIsNotVirtual();
            DocumentLine line = data.Document.GetLine(data.Caret.Line);

            if (data.Caret.Column > line.Length + 1)
            {
                data.Caret.Column = line.Length + 1;
            }
            else if (data.Caret.Offset == line.Offset)
            {
                DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1);
                data.Remove(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength);
            }
            else
            {
                removeCharBeforeCaret(data);
            }

            // Needs to be fixed after, the line may just contain the indentation
            data.FixVirtualIndentation();
        }