static void NewLineSmartIndent(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); var oldCaretLine = data.Caret.Location.Line; var indentString = data.IndentationTracker.GetIndentationString(data.Caret.Line); data.InsertAtCaret(data.EolMarker); if (data.HasIndentationTracker) { // Don't insert the indent string if the EOL insertion modified the caret location in an unexpected fashion // (This likely means someone has custom logic regarding insertion of the EOL) if (data.Caret.Location.Line == oldCaretLine + 1 && data.Caret.Location.Column == 1) { var line = data.GetLine(data.Caret.Line); var currentIndent = line.GetIndentation(data.Document); var currentCalculatedIndent = data.IndentationTracker.GetIndentationString(data.Caret.Line); if (!string.IsNullOrEmpty(currentCalculatedIndent)) { indentString = currentCalculatedIndent; } if (indentString != currentIndent) { data.InsertAtCaret(indentString); } } } } }
public static void InsertNewLine(TextEditorData data) { if (!data.CanEditSelection) { return; } data.Document.BeginAtomicUndo(); if (data.IsSomethingSelected) { data.DeleteSelectedText(); } data.EnsureCaretIsNotVirtual(); StringBuilder sb = new StringBuilder(data.EolMarker); if (data.Options.AutoIndent) { sb.Append(data.Document.GetLineIndent(data.Caret.Line)); } int offset = data.Caret.Offset; data.Insert(offset, sb.ToString()); data.Caret.Offset = offset + sb.Length; data.Document.EndAtomicUndo(); }
public static void CaretLineToEnd(TextEditorData data) { if (!data.CanEdit(data.Caret.Line)) { return; } var line = data.Document.GetLine(data.Caret.Line); using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); int physColumn = data.Caret.Column - 1; if (physColumn == line.Length) { // Nothing after the cursor, delete the end-of-line sequence data.Remove(line.Offset + physColumn, line.LengthIncludingDelimiter - physColumn); } else { // Delete from cursor position to the end of the line var end = GetEndOfLineOffset(data, data.Caret.Location, false); data.Remove(line.Offset + physColumn, end - (line.Offset + physColumn)); } } data.Document.CommitLineUpdate(data.Caret.Line); }
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(); } } }
static void NewLineSmartIndent(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); data.InsertAtCaret(data.EolMarker); data.InsertAtCaret(data.GetIndentationString(data.Caret.Location)); } }
static void NewLineSmartIndent(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); data.InsertAtCaret(data.EolMarker); var line = data.Document.GetLine(data.Caret.Line); data.InsertAtCaret(data.GetIndentationString(line.EndOffset)); } }
public static void Paste(TextEditorData data) { if (!data.CanEditSelection) { return; } using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); PasteFrom(Clipboard.Get(CopyOperation.CLIPBOARD_ATOM), data, true, data.IsSomethingSelected ? data.SelectionRange.Offset : data.Caret.Offset); } }
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); }
static void NewLineSmartIndent(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); string indentString; if (data.HasIndentationTracker) { indentString = data.IndentationTracker.GetIndentationString(data.Caret.Location); } else { indentString = data.GetIndentationString(data.Caret.Location); } data.InsertAtCaret(data.EolMarker); data.InsertAtCaret(indentString); } }
static int PastePlainText(TextEditorData data, int offset, string text, bool preserveSelection = false) { int inserted; using (var undo = data.OpenUndoGroup()) { var version = data.Document.Version; if (!preserveSelection) { data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block); } data.EnsureCaretIsNotVirtual(); offset = version.MoveOffsetTo(data.Document.Version, offset); inserted = data.Insert(offset, text); } data.PasteText(offset, text, inserted); return(inserted); }
static void NewLineSmartIndent(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); var oldCaretLine = data.Caret.Location.Line; string indentString = data.GetIndentationString(data.Caret.Location); data.InsertAtCaret(data.EolMarker); // Don't insert the indent string if the EOL insertion modified the caret location in an unexpected fashion // (This likely means someone has custom logic regarding insertion of the EOL) if (data.Caret.Location.Line == oldCaretLine + 1 && data.Caret.Location.Column == 1) { data.InsertAtCaret(indentString); } } }
public static void CaretLineToStart(TextEditorData data) { if (!data.CanEdit(data.Caret.Line)) { return; } var line = data.Document.GetLine(data.Caret.Line); using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); int physColumn = data.Caret.Column - 1; var startLine = GetStartOfLineOffset(data, data.Caret.Location); data.Remove(startLine, (line.Offset + physColumn) - startLine); } data.Document.CommitLineUpdate(data.Caret.Line); }
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); } 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); } undo.Dispose(); return(inserted); }
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(); } } }
public static void CaretLineToEnd(TextEditorData data) { if (!data.CanEdit(data.Caret.Line)) { return; } LineSegment line = data.Document.GetLine(data.Caret.Line); data.EnsureCaretIsNotVirtual(); int physColumn = data.Caret.Column - 1; if (physColumn == line.EditableLength) { // Nothing after the cursor, delete the end-of-line sequence data.Remove(line.Offset + physColumn, line.Length - physColumn); } else { // Delete from cursor position to the end of the line data.Remove(line.Offset + physColumn, line.EditableLength - physColumn); } data.Document.CommitLineUpdate(data.Caret.Line); }
public static void CaretLineToStart (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; var line = data.Document.GetLine (data.Caret.Line); using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); int physColumn = data.Caret.Column - 1; var startLine = GetStartOfLineOffset (data, data.Caret.Location); data.Remove (startLine, (line.Offset + physColumn) - startLine); } data.Document.CommitLineUpdate (data.Caret.Line); }
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); }
public static void CaretLineToEnd (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; var line = data.Document.GetLine (data.Caret.Line); using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); int physColumn = data.Caret.Column - 1; if (physColumn == line.Length) { // Nothing after the cursor, delete the end-of-line sequence data.Remove (line.Offset + physColumn, line.LengthIncludingDelimiter - physColumn); } else { // Delete from cursor position to the end of the line var end = GetEndOfLineOffset (data, data.Caret.Location, false); data.Remove (line.Offset + physColumn, end - (line.Offset + physColumn)); } } data.Document.CommitLineUpdate (data.Caret.Line); }
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; string text = System.Text.Encoding.UTF8.GetString(selBytes, 1, selBytes.Length - 1); bool pasteBlock = (selBytes [0] & 1) == 1; bool pasteLine = (selBytes [0] & 2) == 2; // var clearSelection = data.IsSomethingSelected ? data.MainSelection.SelectionMode != SelectionMode.Block : true; if (pasteBlock) { using (var undo = data.OpenUndoGroup()) { var version = data.Document.Version; if (!preserveSelection) { data.DeleteSelectedText(!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block); } data.EnsureCaretIsNotVirtual(); insertionOffset = version.MoveOffsetTo(data.Document.Version, insertionOffset); data.Caret.PreserveSelection = true; string[] lines = text.Split('\r'); 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.Length; 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.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); data.Insert(curLine.Offset, text + data.EolMarker); if (!preserveState) { data.ClearSelection(); } data.Caret.PreserveSelection = false; } } else { result = PastePlainText(data, insertionOffset, text, preserveSelection); } } }); // 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; } using (var undo = data.OpenUndoGroup()) { result = PastePlainText(data, insertionOffset, text, preserveSelection); } }); } return(result); }
static int PastePlainText (TextEditorData data, int offset, string text, bool preserveSelection = false) { int inserted = 0; using (var undo = data.OpenUndoGroup ()) { var version = data.Document.Version; if (!preserveSelection) data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block); 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); } } return inserted; }
public static void CaretLineToEnd (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; LineSegment line = data.Document.GetLine (data.Caret.Line); data.EnsureCaretIsNotVirtual (); if (data.Caret.Column == line.EditableLength) { // Nothing after the cursor, delete the end-of-line sequence data.Remove (line.Offset + data.Caret.Column, line.Length - data.Caret.Column); } else { // Delete from cursor position to the end of the line data.Remove (line.Offset + data.Caret.Column, line.EditableLength - data.Caret.Column); } data.Document.CommitLineUpdate (data.Caret.Line); }
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); }
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 (); } } }
public static void Paste (TextEditorData data) { if (!data.CanEditSelection) return; using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); PasteFrom (Clipboard.Get (CopyOperation.CLIPBOARD_ATOM), data, true, data.IsSomethingSelected ? data.SelectionRange.Offset : data.Caret.Offset); } }
public static void InsertNewLine (TextEditorData data) { if (!data.CanEditSelection) return; data.Document.BeginAtomicUndo (); if (data.IsSomethingSelected) data.DeleteSelectedText (); data.EnsureCaretIsNotVirtual (); StringBuilder sb = new StringBuilder (data.EolMarker); if (data.Options.AutoIndent) sb.Append (data.Document.GetLineIndent (data.Caret.Line)); int offset = data.Caret.Offset; data.Insert (offset, sb.ToString ()); data.Caret.Offset = offset + sb.Length; data.Document.EndAtomicUndo (); }
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(); } }
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 (); } }
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 (); } }
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; }
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); } } }
static void NewLineSmartIndent (TextEditorData data) { using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); data.InsertAtCaret (data.EolMarker); data.InsertAtCaret (data.GetIndentationString (data.Caret.Location)); } }
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(); } }
public static void SetCompletionText (TextEditorData data, CodeCompletionContext ctx, string partialWord, string completeWord, int wordOffset) { if (data == null || data.Document == null) return; int triggerOffset = ctx.TriggerOffset; int length = String.IsNullOrEmpty (partialWord) ? 0 : partialWord.Length; // for named arguments invoke(arg:<Expr>); if (completeWord.EndsWith (":", StringComparison.Ordinal)) { if (data.GetCharAt (triggerOffset + length) == ':') length++; } bool blockMode = false; if (data.IsSomethingSelected) { blockMode = data.MainSelection.SelectionMode == Mono.TextEditor.SelectionMode.Block; if (blockMode) { data.Caret.PreserveSelection = true; triggerOffset = data.Caret.Offset - length; } else { if (data.SelectionRange.Offset < ctx.TriggerOffset) triggerOffset = ctx.TriggerOffset - data.SelectionRange.Length; data.DeleteSelectedText (); } length = 0; } // | in the completion text now marks the caret position int idx = completeWord.IndexOf ('|'); if (idx >= 0) { completeWord = completeWord.Remove (idx, 1); } triggerOffset += data.EnsureCaretIsNotVirtual (); if (blockMode) { using (var undo = data.OpenUndoGroup ()) { int minLine = data.MainSelection.MinLine; int maxLine = data.MainSelection.MaxLine; int column = triggerOffset - data.Document.GetLineByOffset (triggerOffset).Offset; for (int lineNumber = minLine; lineNumber <= maxLine; lineNumber++) { DocumentLine lineSegment = data.Document.GetLine (lineNumber); if (lineSegment == null) continue; int offset = lineSegment.Offset + column; data.Replace (offset, length, completeWord); } int minColumn = Math.Min (data.MainSelection.Anchor.Column, data.MainSelection.Lead.Column); data.MainSelection = data.MainSelection.WithRange ( new Mono.TextEditor.DocumentLocation (data.Caret.Line == minLine ? maxLine : minLine, minColumn), data.Caret.Location ); data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine); data.Caret.PreserveSelection = false; } } else { data.Replace (triggerOffset, length, completeWord); } data.Document.CommitLineUpdate (data.Caret.Line); if (idx >= 0) data.Caret.Offset = triggerOffset + idx; }
protected void InsertCharacter(uint unicodeKey) { if (!textEditorData.CanEdit(Data.Caret.Line)) { return; } HideMouseCursor(); using (var undo = Document.OpenUndoGroup()) { if (textEditorData.IsSomethingSelected && textEditorData.Options.EnableSelectionWrappingKeys && IsSpecialKeyForSelection(unicodeKey)) { textEditorData.SelectionSurroundingProvider.HandleSpecialSelectionKey(textEditorData, unicodeKey); return; } textEditorData.DeleteSelectedText( textEditorData.IsSomethingSelected ? textEditorData.MainSelection.SelectionMode != SelectionMode.Block : true); // Needs to be called after delete text, delete text handles virtual caret postitions itself, // but afterwards the virtual position may need to be restored. textEditorData.EnsureCaretIsNotVirtual(); char ch = (char)unicodeKey; if (!char.IsControl(ch) && textEditorData.CanEdit(Caret.Line)) { DocumentLine line = Document.GetLine(Caret.Line); if (Caret.IsInInsertMode || Caret.Column >= line.Length + 1) { string text = ch.ToString(); if (textEditorData.IsSomethingSelected && textEditorData.MainSelection.SelectionMode == SelectionMode.Block) { var visualInsertLocation = textEditorData.LogicalToVisualLocation(Caret.Location); var selection = textEditorData.MainSelection; Caret.PreserveSelection = true; for (int lineNumber = selection.MinLine; lineNumber <= selection.MaxLine; lineNumber++) { DocumentLine lineSegment = textEditorData.GetLine(lineNumber); int insertOffset = lineSegment.GetLogicalColumn(textEditorData, visualInsertLocation.Column) - 1; string textToInsert; if (lineSegment.Length < insertOffset) { int visualLastColumn = lineSegment.GetVisualColumn(textEditorData, lineSegment.Length + 1); int charsToInsert = visualInsertLocation.Column - visualLastColumn; int spaceCount = charsToInsert % editor.Options.TabSize; textToInsert = new string ('\t', (charsToInsert - spaceCount) / editor.Options.TabSize) + new string (' ', spaceCount) + text; insertOffset = lineSegment.Length; } else { textToInsert = text; } textEditorData.Insert(lineSegment.Offset + insertOffset, textToInsert); } var visualColumn = textEditorData.GetLine(Caret.Location.Line).GetVisualColumn(textEditorData, Caret.Column); textEditorData.MainSelection = new Selection( new DocumentLocation(selection.Anchor.Line, textEditorData.GetLine(selection.Anchor.Line).GetLogicalColumn(textEditorData, visualColumn)), new DocumentLocation(selection.Lead.Line, textEditorData.GetLine(selection.Lead.Line).GetLogicalColumn(textEditorData, visualColumn)), SelectionMode.Block ); Document.CommitMultipleLineUpdate(textEditorData.MainSelection.MinLine, textEditorData.MainSelection.MaxLine); } else { textEditorData.Insert(Caret.Offset, text); } } else { textEditorData.Replace(Caret.Offset, 1, ch.ToString()); } // That causes unnecessary redraws: // bool autoScroll = Caret.AutoScrollToCaret; // Caret.Column++; if (Caret.PreserveSelection) { Caret.PreserveSelection = false; } // Caret.AutoScrollToCaret = autoScroll; // if (autoScroll) // Editor.ScrollToCaret (); // Document.RequestUpdate (new LineUpdate (Caret.Line)); // Document.CommitDocumentUpdate (); } } Document.OptimizeTypedUndo(); }
static void NewLineSmartIndent (TextEditorData data) { using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); data.InsertAtCaret (data.EolMarker); var line = data.Document.GetLine (data.Caret.Line); data.InsertAtCaret (data.GetIndentationString (line.EndOffset)); } }
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(); } } }
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; string text = System.Text.Encoding.UTF8.GetString (selBytes, 1, selBytes.Length - 1); bool pasteBlock = (selBytes [0] & 1) == 1; bool pasteLine = (selBytes [0] & 2) == 2; // var clearSelection = data.IsSomethingSelected ? data.MainSelection.SelectionMode != SelectionMode.Block : true; if (pasteBlock) { using (var undo = data.OpenUndoGroup ()) { var version = data.Document.Version; data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block); data.EnsureCaretIsNotVirtual (); insertionOffset = version.MoveOffsetTo (data.Document.Version, insertionOffset); data.Caret.PreserveSelection = true; string[] lines = text.Split ('\r'); 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.Length; 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.Caret.PreserveSelection = false; } } else if (pasteLine) { using (var undo = data.OpenUndoGroup ()) { 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); data.Insert (curLine.Offset, text + data.EolMarker); if (!preserveState) data.ClearSelection (); data.Caret.PreserveSelection = false; } } else { result = PastePlainText (data, insertionOffset, text); } } }); // 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; using (var undo = data.OpenUndoGroup ()) { result = PastePlainText (data, insertionOffset, text); } }); } return result; }
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 (); }
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(); } }
static void NewLineSmartIndent (TextEditorData data) { using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); string indentString; if (data.HasIndentationTracker) { indentString = data.IndentationTracker.GetIndentationString (data.Caret.Location); } else { indentString = data.GetIndentationString (data.Caret.Location); } data.InsertAtCaret (data.EolMarker); data.InsertAtCaret (indentString); } }
public static bool FixLineStart (TextEditorData textEditorData, DocumentStateTracker<CSharpIndentEngine> stateTracker, int lineNumber) { if (lineNumber > DocumentLocation.MinLine) { DocumentLine line = textEditorData.Document.GetLine (lineNumber); if (line == null) return false; DocumentLine prevLine = textEditorData.Document.GetLine (lineNumber - 1); if (prevLine == null) return false; string trimmedPreviousLine = textEditorData.Document.GetTextAt (prevLine).TrimStart (); //xml doc comments //check previous line was a doc comment //check there's a following line? if (trimmedPreviousLine.StartsWith ("///", StringComparison.Ordinal)) { if (textEditorData.GetTextAt (line.Offset, line.Length).TrimStart ().StartsWith ("///", StringComparison.Ordinal)) return false; //check that the newline command actually inserted a newline textEditorData.EnsureCaretIsNotVirtual (); string nextLine = textEditorData.Document.GetTextAt (textEditorData.Document.GetLine (lineNumber + 1)).TrimStart (); if (trimmedPreviousLine.Length > "///".Length || nextLine.StartsWith ("///", StringComparison.Ordinal)) { var insertionPoint = line.Offset + line.GetIndentation (textEditorData.Document).Length; textEditorData.Insert (insertionPoint, "/// "); return true; } //multi-line comments } else if (stateTracker.Engine.IsInsideMultiLineComment) { if (textEditorData.GetTextAt (line.Offset, line.Length).TrimStart ().StartsWith ("*", StringComparison.Ordinal)) return false; textEditorData.EnsureCaretIsNotVirtual (); string commentPrefix = string.Empty; if (trimmedPreviousLine.StartsWith ("* ", StringComparison.Ordinal)) { commentPrefix = "* "; } else if (trimmedPreviousLine.StartsWith ("/**", StringComparison.Ordinal) || trimmedPreviousLine.StartsWith ("/*", StringComparison.Ordinal)) { commentPrefix = " * "; } else if (trimmedPreviousLine.StartsWith ("*", StringComparison.Ordinal)) { commentPrefix = "*"; } int indentSize = line.GetIndentation (textEditorData.Document).Length; var insertedText = prevLine.GetIndentation (textEditorData.Document) + commentPrefix; textEditorData.Replace (line.Offset, indentSize, insertedText); textEditorData.Caret.Offset = line.Offset + insertedText.Length; return true; } else if (stateTracker.Engine.IsInsideStringLiteral) { var lexer = new CSharpCompletionEngineBase.MiniLexer (textEditorData.Document.GetTextAt (0, prevLine.EndOffset)); lexer.Parse (); if (!lexer.IsInString) return false; textEditorData.EnsureCaretIsNotVirtual (); textEditorData.Insert (prevLine.Offset + prevLine.Length, "\" +"); int indentSize = line.GetIndentation (textEditorData.Document).Length; var insertedText = prevLine.GetIndentation (textEditorData.Document) + (trimmedPreviousLine.StartsWith ("\"", StringComparison.Ordinal) ? "" : "\t") + "\""; textEditorData.Replace (line.Offset, indentSize, insertedText); return true; } } return false; }
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 (); } } }
static int PastePlainText (TextEditorData data, int offset, string text) { int inserted; using (var undo = data.OpenUndoGroup ()) { var version = data.Document.Version; data.DeleteSelectedText (!data.IsSomethingSelected || data.MainSelection.SelectionMode != SelectionMode.Block); data.EnsureCaretIsNotVirtual (); offset = version.MoveOffsetTo (data.Document.Version, offset); inserted = data.Insert (offset, text); } data.PasteText (offset, text, inserted); return inserted; }
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(); }