const string LineSelectedType = "MSDEVLineSelect"; // This is the type VS 2003 and 2005 use for flagging a whole line copy static void CopyWholeLine(TextArea textArea, DocumentLine line) { ISegment wholeLine = new SimpleSegment(line.Offset, line.TotalLength); string text = textArea.Document.GetText(wholeLine); // Ensure we use the appropriate newline sequence for the OS text = NewLineFinder.NormalizeNewLines(text, Environment.NewLine); DataObject data = new DataObject(text); // Also copy text in HTML format to clipboard - good for pasting text into Word // or to the SharpDevelop forums. IHighlighter highlighter = textArea.GetService(typeof(IHighlighter)) as IHighlighter; HtmlClipboard.SetHtml(data, HtmlClipboard.CreateHtmlFragment(textArea.Document, highlighter, wholeLine, new HtmlOptions(textArea.Options))); MemoryStream lineSelected = new MemoryStream(1); lineSelected.WriteByte(1); data.SetData(LineSelectedType, lineSelected, false); try { Clipboard.SetDataObject(data, true); } catch (ExternalException) { // Apparently this exception sometimes happens randomly. // The MS controls just ignore it, so we'll do the same. return; } textArea.OnTextCopied(new TextEventArgs(text)); }
/// <summary> /// Inserts text at the insertion position and advances the insertion position. /// This method will add the current indentation to every line in <paramref name="text"/> and will /// replace newlines with the expected newline for the document. /// </summary> public void InsertText(string text) { if (text == null) { throw new ArgumentNullException("text"); } if (currentStatus != Status.Insertion) { throw new InvalidOperationException(); } text = text.Replace("\t", this.Tab); using (this.Document.RunUpdate()) { int textOffset = 0; SimpleSegment segment; while ((segment = NewLineFinder.NextNewLine(text, textOffset)) != SimpleSegment.Invalid) { string insertString = text.Substring(textOffset, segment.Offset - textOffset) + this.LineTerminator + this.Indentation; this.Document.Insert(InsertionPosition, insertString); this.InsertionPosition += insertString.Length; textOffset = segment.EndOffset; } string remainingInsertString = text.Substring(textOffset); this.Document.Insert(InsertionPosition, remainingInsertString); this.InsertionPosition += remainingInsertString.Length; } }
static void CopySelectedText(TextArea textArea) { Clipboard.SetDataObject(textArea.Selection.CreateDataObject(textArea), true); string text = textArea.Selection.GetText(textArea.Document); text = NewLineFinder.NormalizeNewLines(text, Environment.NewLine); textArea.OnTextCopied(new TextEventArgs(text)); }
static void CopySelectedText(TextArea textArea) { string text = textArea.Selection.GetText(textArea.Document); // Ensure we use the appropriate newline sequence for the OS DataObject data = new DataObject(NewLineFinder.NormalizeNewLines(text, Environment.NewLine)); // Also copy text in HTML format to clipboard - good for pasting text into Word // or to the SharpDevelop forums. HtmlClipboard.SetHtml(data, HtmlClipboard.CreateHtmlFragmentForSelection(textArea, new HtmlOptions(textArea.Options))); Clipboard.SetDataObject(data, true); }
void ReplaceSelectionWithNewLine() { string newLine = NewLineFinder.GetNewLineFromDocument(this.Document, this.Caret.Line); using (this.Document.RunUpdate()) { ReplaceSelectionWithText(newLine); if (this.IndentationStrategy != null) { DocumentLine line = this.Document.GetLineByNumber(this.Caret.Line); this.IndentationStrategy.IndentLine(this.Document, line); } } }
/// <summary> /// Creates a data object containing the selection's text. /// </summary> public virtual DataObject CreateDataObject(TextArea textArea) { string text = GetText(textArea.Document); // Ensure we use the appropriate newline sequence for the OS DataObject data = new DataObject(NewLineFinder.NormalizeNewLines(text, Environment.NewLine)); // we cannot use DataObject.SetText - then we cannot drag to SciTe // (but dragging to Word works in both cases) // Also copy text in HTML format to clipboard - good for pasting text into Word // or to the SharpDevelop forums. HtmlClipboard.SetHtml(data, CreateHtmlFragment(textArea, new HtmlOptions(textArea.Options))); return(data); }
void textArea_Drop(object sender, DragEventArgs e) { try { DragDropEffects effect = GetEffect(e); e.Effects = effect; if (effect != DragDropEffects.None) { string text = e.Data.GetData(DataFormats.UnicodeText, true) as string; if (text != null) { int start = textArea.Caret.Offset; if (mode == SelectionMode.Drag && textArea.Selection.Contains(start)) { Debug.WriteLine("Drop: did not drop: drop target is inside selection"); e.Effects = DragDropEffects.None; } else { Debug.WriteLine("Drop: insert at " + start); bool rectangular = e.Data.GetDataPresent(RectangleSelection.RectangularSelectionDataType); string newLine = NewLineFinder.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); text = NewLineFinder.NormalizeNewLines(text, newLine); // Mark the undo group with the currentDragDescriptor, if the drag // is originating from the same control. This allows combining // the undo groups when text is moved. textArea.Document.UndoStack.StartUndoGroup(this.currentDragDescriptor); try { if (rectangular && RectangleSelection.PerformRectangularPaste(textArea, start, text, true)) { } else { textArea.Document.Insert(start, text); textArea.Selection = new SimpleSelection(start, start + text.Length); } } finally { textArea.Document.UndoStack.EndUndoGroup(); } } } } } catch (Exception ex) { OnDragException(ex); } }
static void OnEnter(object target, ExecutedRoutedEventArgs args) { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { string newLine = NewLineFinder.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); using (textArea.Document.RunUpdate()) { textArea.ReplaceSelectionWithText(newLine); if (textArea.IndentationStrategy != null) { DocumentLine line = textArea.Document.GetLineByNumber(textArea.Caret.Line); textArea.IndentationStrategy.IndentLine(line); } } textArea.Caret.BringCaretToView(); args.Handled = true; } }
static void CopySelectedText(TextArea textArea) { var data = textArea.Selection.CreateDataObject(textArea); try { Clipboard.SetDataObject(data, true); } catch (ExternalException) { // Apparently this exception sometimes happens randomly. // The MS controls just ignore it, so we'll do the same. return; } string text = textArea.Selection.GetText(textArea.Document); text = NewLineFinder.NormalizeNewLines(text, Environment.NewLine); textArea.OnTextCopied(new TextEventArgs(text)); }
/// <inheritdoc/> public override void ReplaceSelectionWithText(string newText) { if (newText == null) { throw new ArgumentNullException(nameof(newText)); } using (textArea.Document.RunUpdate()) { TextViewPosition start = new TextViewPosition(document.GetLocation(topLeftOffset), GetVisualColumnFromXPos(startLine, startXPos)); TextViewPosition end = new TextViewPosition(document.GetLocation(bottomRightOffset), GetVisualColumnFromXPos(endLine, endXPos)); int insertionLength; int totalInsertionLength = 0; int firstInsertionLength = 0; int editOffset = Math.Min(topLeftOffset, bottomRightOffset); TextViewPosition pos; if (NewLineFinder.NextNewLine(newText, 0) == SimpleSegment.Invalid) { // insert same text into every line foreach (SelectionSegment lineSegment in Segments.Reverse()) { ReplaceSingleLineText(textArea, lineSegment, newText, out insertionLength); totalInsertionLength += insertionLength; firstInsertionLength = insertionLength; } int newEndOffset = editOffset + totalInsertionLength; pos = new TextViewPosition(document.GetLocation(editOffset + firstInsertionLength)); textArea.Selection = new RectangleSelection(textArea, pos, Math.Max(startLine, endLine), GetXPos(textArea, pos)); } else { string[] lines = newText.Split(NewLineFinder.NewlineStrings, segments.Count, StringSplitOptions.None); int line = Math.Min(startLine, endLine); for (int i = lines.Length - 1; i >= 0; i--) { ReplaceSingleLineText(textArea, segments[i], lines[i], out insertionLength); firstInsertionLength = insertionLength; } pos = new TextViewPosition(document.GetLocation(editOffset + firstInsertionLength)); textArea.ClearSelection(); } textArea.Caret.Position = textArea.TextView.GetPosition(new Point(GetXPos(textArea, pos), textArea.TextView.GetVisualTopByDocumentLine(Math.Max(startLine, endLine)))).GetValueOrDefault(); } }
const string LineSelectedType = "MSDEVLineSelect"; // This is the type VS 2003 and 2005 use for flagging a whole line copy static void CopyWholeLine(TextArea textArea, DocumentLine line) { ISegment wholeLine = new SimpleSegment(line.Offset, line.TotalLength); string text = textArea.Document.GetText(wholeLine); // Ensure we use the appropriate newline sequence for the OS DataObject data = new DataObject(NewLineFinder.NormalizeNewLines(text, Environment.NewLine)); // Also copy text in HTML format to clipboard - good for pasting text into Word // or to the SharpDevelop forums. DocumentHighlighter highlighter = textArea.GetService(typeof(DocumentHighlighter)) as DocumentHighlighter; HtmlClipboard.SetHtml(data, HtmlClipboard.CreateHtmlFragment(textArea.Document, highlighter, wholeLine, new HtmlOptions(textArea.Options))); MemoryStream lineSelected = new MemoryStream(1); lineSelected.WriteByte(1); data.SetData(LineSelectedType, lineSelected, false); Clipboard.SetDataObject(data, true); }
void ReplaceSelectionWithNewLine() { string newLine = NewLineFinder.GetNewLineFromDocument(this.Document, this.Caret.Line); using (this.Document.RunUpdate()) { ReplaceSelectionWithText(newLine); if (this.IndentationStrategy != null) { DocumentLine line = this.Document.GetLineByNumber(this.Caret.Line); ISegment[] deletable = GetDeletableSegments(line); if (deletable.Length == 1 && deletable[0].Offset == line.Offset && deletable[0].Length == line.Length) { // use indentation strategy only if the line is not read-only this.IndentationStrategy.IndentLine(this.Document, line); } } } }
/// <summary> /// Creates a new InsertionContext instance. /// </summary> public InsertionContext(TextArea textArea, int insertionPosition) { if (textArea == null) { throw new ArgumentNullException("textArea"); } this.TextArea = textArea; this.Document = textArea.Document; this.SelectedText = textArea.Selection.GetText(textArea.Document); this.InsertionPosition = insertionPosition; this.startPosition = insertionPosition; DocumentLine startLine = this.Document.GetLineByOffset(insertionPosition); ISegment indentation = TextUtilities.GetWhitespaceAfter(this.Document, startLine.Offset); this.Indentation = Document.GetText(indentation.Offset, Math.Min(indentation.EndOffset, insertionPosition) - indentation.Offset); this.Tab = textArea.Options.IndentationString; this.LineTerminator = NewLineFinder.GetNewLineFromDocument(this.Document, startLine.LineNumber); }
static void OnPaste(object target, ExecutedRoutedEventArgs args) { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { Debug.WriteLine( Clipboard.GetText(TextDataFormat.Html) ); // convert text back to correct newlines for this document string newLine = NewLineFinder.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); string text = NewLineFinder.NormalizeNewLines(Clipboard.GetText(), newLine); bool fullLine = textArea.Options.CutCopyWholeLine && Clipboard.ContainsData(LineSelectedType); if (fullLine) { DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); textArea.Document.Insert(currentLine.Offset, text); } else { textArea.ReplaceSelectionWithText(text); } textArea.Caret.BringCaretToView(); args.Handled = true; } }
static void OnPaste(object target, ExecutedRoutedEventArgs args) { TextArea textArea = GetTextArea(target); if (textArea != null && textArea.Document != null) { Debug.WriteLine(Clipboard.GetText(TextDataFormat.Html)); // convert text back to correct newlines for this document string newLine = NewLineFinder.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); string text = NewLineFinder.NormalizeNewLines(Clipboard.GetText(), newLine); if (!string.IsNullOrEmpty(text)) { bool fullLine = textArea.Options.CutCopyWholeLine && Clipboard.ContainsData(LineSelectedType); bool rectangular = Clipboard.ContainsData(RectangleSelection.RectangularSelectionDataType); if (fullLine) { DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); if (textArea.ReadOnlySectionProvider.CanInsert(currentLine.Offset)) { textArea.Document.Insert(currentLine.Offset, text); } } else if (rectangular && textArea.Selection.IsEmpty) { if (!RectangleSelection.PerformRectangularPaste(textArea, textArea.Caret.Offset, text, false)) { textArea.ReplaceSelectionWithText(text); } } else { textArea.ReplaceSelectionWithText(text); } } textArea.Caret.BringCaretToView(); args.Handled = true; } }
/// <inheritdoc/> public override void ReplaceSelectionWithText(string newText) { if (newText == null) { throw new ArgumentNullException(nameof(newText)); } using (TextArea.Document.RunUpdate()) { int insertionLength; var firstInsertionLength = 0; var editOffset = Math.Min(_topLeftOffset, _bottomRightOffset); TextViewPosition pos; if (NewLineFinder.NextNewLine(newText, 0) == SimpleSegment.Invalid) { // insert same text into every line foreach (var lineSegment in Segments.Reverse()) { ReplaceSingleLineText(TextArea, lineSegment, newText, out insertionLength); firstInsertionLength = insertionLength; } pos = new TextViewPosition(_document.GetLocation(editOffset + firstInsertionLength)); TextArea.Selection = new RectangleSelection(TextArea, pos, Math.Max(_startLine, _endLine), GetXPos(TextArea, pos)); } else { var lines = newText.Split(NewLineFinder.NewlineStrings, _segments.Count, StringSplitOptions.None); for (var i = lines.Length - 1; i >= 0; i--) { ReplaceSingleLineText(TextArea, _segments[i], lines[i], out insertionLength); firstInsertionLength = insertionLength; } pos = new TextViewPosition(_document.GetLocation(editOffset + firstInsertionLength)); TextArea.ClearSelection(); } TextArea.Caret.Position = new TextViewPosition(Math.Max(_startLine, _endLine), pos.Column); } }
/// <inheritdoc/> public override void ReplaceSelectionWithText(TextArea textArea, string newText) { if (textArea == null) { throw new ArgumentNullException("textArea"); } if (newText == null) { throw new ArgumentNullException("newText"); } using (textArea.Document.RunUpdate()) { TextLocation start = document.GetLocation(StartOffset); TextLocation end = document.GetLocation(EndOffset); int editColumn = Math.Min(start.Column, end.Column); if (NewLineFinder.NextNewLine(newText, 0) == SimpleSegment.Invalid) { // insert same text into every line foreach (ISegment lineSegment in this.Segments.Reverse()) { ReplaceSingleLineText(textArea, lineSegment, newText); } TextLocation newStart = new TextLocation(start.Line, editColumn + newText.Length); TextLocation newEnd = new TextLocation(end.Line, editColumn + newText.Length); textArea.Caret.Location = newEnd; textArea.Selection = new RectangleSelection(document, document.GetOffset(newStart), document.GetOffset(newEnd)); } else { // convert all segment start/ends to anchors var segments = this.Segments.Select(s => new AnchorSegment(this.document, s)).ToList(); SimpleSegment ds = NewLineFinder.NextNewLine(newText, 0); // we'll check whether all lines have the same length. If so, we can continue using a rectangular selection. int commonLength = -1; // now insert lines into rectangular selection int lastDelimiterEnd = 0; bool isAtEnd = false; int i; for (i = 0; i < segments.Count; i++) { string lineText; if (ds == SimpleSegment.Invalid || (i == segments.Count - 1)) { lineText = newText.Substring(lastDelimiterEnd); isAtEnd = true; // if we have more lines to insert than this selection is long, we cannot continue using a rectangular selection if (ds != SimpleSegment.Invalid) { commonLength = -1; } } else { lineText = newText.Substring(lastDelimiterEnd, ds.Offset - lastDelimiterEnd); } if (i == 0) { commonLength = lineText.Length; } else if (commonLength != lineText.Length) { commonLength = -1; } ReplaceSingleLineText(textArea, segments[i], lineText); if (isAtEnd) { break; } lastDelimiterEnd = ds.EndOffset; ds = NewLineFinder.NextNewLine(newText, lastDelimiterEnd); } if (commonLength >= 0) { TextLocation newStart = new TextLocation(start.Line, editColumn + commonLength); TextLocation newEnd = new TextLocation(start.Line + i, editColumn + commonLength); textArea.Selection = new RectangleSelection(document, document.GetOffset(newStart), document.GetOffset(newEnd)); } else { textArea.Selection = Selection.Empty; } } } }
void StartDrag() { // prevent nested StartDrag calls mode = SelectionMode.Drag; // mouse capture and Drag'n'Drop doesn't mix textArea.ReleaseMouseCapture(); string text = textArea.Selection.GetText(textArea.Document); text = NewLineFinder.NormalizeNewLines(text, Environment.NewLine); DataObject dataObject = new DataObject(text); // we cannot use DataObject.SetText - then we cannot drag to SciTe // (but dragging to Word works in both cases) // also copy as HTML - adds syntax highlighting when dragging to Word string htmlFragment = HtmlClipboard.CreateHtmlFragmentForSelection(textArea, new HtmlOptions(textArea.Options)); HtmlClipboard.SetHtml(dataObject, htmlFragment); DragDropEffects allowedEffects = DragDropEffects.All; var deleteOnMove = textArea.Selection.Segments.Select(s => new AnchorSegment(textArea.Document, s)).ToList(); object dragDescriptor = new object(); this.currentDragDescriptor = dragDescriptor; DragDropEffects resultEffect; using (textArea.AllowCaretOutsideSelection()) { var oldCaretPosition = textArea.Caret.Position; try { Debug.WriteLine("DoDragDrop with allowedEffects=" + allowedEffects); resultEffect = DragDrop.DoDragDrop(textArea, dataObject, allowedEffects); Debug.WriteLine("DoDragDrop done, resultEffect=" + resultEffect); } catch (COMException ex) { // ignore COM errors - don't crash on badly implemented drop targets Debug.WriteLine("DoDragDrop failed: " + ex.ToString()); return; } if (resultEffect == DragDropEffects.None) { // reset caret if drag was aborted textArea.Caret.Position = oldCaretPosition; } } this.currentDragDescriptor = null; if (deleteOnMove != null && resultEffect == DragDropEffects.Move) { bool draggedInsideSingleDocument = (dragDescriptor == textArea.Document.UndoStack.LastGroupDescriptor); if (draggedInsideSingleDocument) { textArea.Document.UndoStack.StartContinuedUndoGroup(null); } textArea.Document.BeginUpdate(); try { foreach (ISegment s in deleteOnMove) { textArea.Document.Remove(s.Offset, s.Length); } } finally { textArea.Document.EndUpdate(); if (draggedInsideSingleDocument) { textArea.Document.UndoStack.EndUndoGroup(); } } } }