@@ -312,64 +312,89 @@ static void OnCut(object target, ExecutedRoutedEventArgs args)
312312 if ( textArea != null && textArea . Document != null ) {
313313 if ( textArea . Selection . IsEmpty && textArea . Options . CutCopyWholeLine ) {
314314 DocumentLine currentLine = textArea . Document . GetLineByNumber ( textArea . Caret . Line ) ;
315- CopyWholeLine ( textArea , currentLine ) ;
316- ISegment [ ] segmentsToDelete = textArea . GetDeletableSegments ( new SimpleSegment ( currentLine . Offset , currentLine . TotalLength ) ) ;
317- for ( int i = segmentsToDelete . Length - 1 ; i >= 0 ; i -- ) {
318- textArea . Document . Remove ( segmentsToDelete [ i ] ) ;
315+ if ( CopyWholeLine ( textArea , currentLine ) ) {
316+ ISegment [ ] segmentsToDelete = textArea . GetDeletableSegments ( new SimpleSegment ( currentLine . Offset , currentLine . TotalLength ) ) ;
317+ for ( int i = segmentsToDelete . Length - 1 ; i >= 0 ; i -- ) {
318+ textArea . Document . Remove ( segmentsToDelete [ i ] ) ;
319+ }
319320 }
320321 } else {
321- CopySelectedText ( textArea ) ;
322- textArea . RemoveSelectedText ( ) ;
322+ if ( CopySelectedText ( textArea ) )
323+ textArea . RemoveSelectedText ( ) ;
323324 }
324325 textArea . Caret . BringCaretToView ( ) ;
325326 args . Handled = true ;
326327 }
327328 }
328329
329- static void CopySelectedText ( TextArea textArea )
330+ static bool CopySelectedText ( TextArea textArea )
330331 {
331332 var data = textArea . Selection . CreateDataObject ( textArea ) ;
333+ var copyingEventArgs = new DataObjectCopyingEventArgs ( data , false ) ;
334+ textArea . RaiseEvent ( copyingEventArgs ) ;
335+ if ( copyingEventArgs . CommandCancelled )
336+ return false ;
332337
333338 try {
334339 Clipboard . SetDataObject ( data , true ) ;
335340 } catch ( ExternalException ) {
336341 // Apparently this exception sometimes happens randomly.
337342 // The MS controls just ignore it, so we'll do the same.
338- return ;
343+ return false ;
339344 }
340345
341346 string text = textArea . Selection . GetText ( ) ;
342347 text = TextUtilities . NormalizeNewLines ( text , Environment . NewLine ) ;
343348 textArea . OnTextCopied ( new TextEventArgs ( text ) ) ;
349+ return true ;
344350 }
345351
346352 const string LineSelectedType = "MSDEVLineSelect" ; // This is the type VS 2003 and 2005 use for flagging a whole line copy
347353
348- static void CopyWholeLine ( TextArea textArea , DocumentLine line )
354+ public static bool ConfirmDataFormat ( TextArea textArea , DataObject dataObject , string format )
355+ {
356+ var e = new DataObjectSettingDataEventArgs ( dataObject , format ) ;
357+ textArea . RaiseEvent ( e ) ;
358+ return ! e . CommandCancelled ;
359+ }
360+
361+ static bool CopyWholeLine ( TextArea textArea , DocumentLine line )
349362 {
350363 ISegment wholeLine = new SimpleSegment ( line . Offset , line . TotalLength ) ;
351364 string text = textArea . Document . GetText ( wholeLine ) ;
352365 // Ensure we use the appropriate newline sequence for the OS
353366 text = TextUtilities . NormalizeNewLines ( text , Environment . NewLine ) ;
354- DataObject data = new DataObject ( text ) ;
367+ DataObject data = new DataObject ( ) ;
368+ if ( ConfirmDataFormat ( textArea , data , DataFormats . UnicodeText ) )
369+ data . SetText ( text ) ;
355370
356371 // Also copy text in HTML format to clipboard - good for pasting text into Word
357372 // or to the SharpDevelop forums.
358- IHighlighter highlighter = textArea . GetService ( typeof ( IHighlighter ) ) as IHighlighter ;
359- HtmlClipboard . SetHtml ( data , HtmlClipboard . CreateHtmlFragment ( textArea . Document , highlighter , wholeLine , new HtmlOptions ( textArea . Options ) ) ) ;
373+ if ( ConfirmDataFormat ( textArea , data , DataFormats . Html ) ) {
374+ IHighlighter highlighter = textArea . GetService ( typeof ( IHighlighter ) ) as IHighlighter ;
375+ HtmlClipboard . SetHtml ( data , HtmlClipboard . CreateHtmlFragment ( textArea . Document , highlighter , wholeLine , new HtmlOptions ( textArea . Options ) ) ) ;
376+ }
377+
378+ if ( ConfirmDataFormat ( textArea , data , LineSelectedType ) ) {
379+ MemoryStream lineSelected = new MemoryStream ( 1 ) ;
380+ lineSelected . WriteByte ( 1 ) ;
381+ data . SetData ( LineSelectedType , lineSelected , false ) ;
382+ }
360383
361- MemoryStream lineSelected = new MemoryStream ( 1 ) ;
362- lineSelected . WriteByte ( 1 ) ;
363- data . SetData ( LineSelectedType , lineSelected , false ) ;
384+ var copyingEventArgs = new DataObjectCopyingEventArgs ( data , false ) ;
385+ textArea . RaiseEvent ( copyingEventArgs ) ;
386+ if ( copyingEventArgs . CommandCancelled )
387+ return false ;
364388
365389 try {
366390 Clipboard . SetDataObject ( data , true ) ;
367391 } catch ( ExternalException ) {
368392 // Apparently this exception sometimes happens randomly.
369393 // The MS controls just ignore it, so we'll do the same.
370- return ;
394+ return false ;
371395 }
372396 textArea . OnTextCopied ( new TextEventArgs ( text ) ) ;
397+ return true ;
373398 }
374399
375400 static void CanPaste ( object target , CanExecuteRoutedEventArgs args )
@@ -396,7 +421,7 @@ static void OnPaste(object target, ExecutedRoutedEventArgs args)
396421 }
397422 if ( dataObject == null )
398423 return ;
399- Debug . WriteLine ( dataObject . GetData ( DataFormats . Html ) as string ) ;
424+ Debug . WriteLine ( dataObject . GetData ( DataFormats . Html ) as string ) ;
400425
401426 // convert text back to correct newlines for this document
402427 string newLine = TextUtilities . GetNewLineFromDocument ( textArea . Document , textArea . Caret . Line ) ;
@@ -411,6 +436,27 @@ static void OnPaste(object target, ExecutedRoutedEventArgs args)
411436 if ( ! string . IsNullOrEmpty ( text ) ) {
412437 bool fullLine = textArea . Options . CutCopyWholeLine && dataObject . GetDataPresent ( LineSelectedType ) ;
413438 bool rectangular = dataObject . GetDataPresent ( RectangleSelection . RectangularSelectionDataType ) ;
439+
440+ string pasteFormat ;
441+ // fill the suggested DataFormat used for the paste action:
442+ if ( fullLine )
443+ pasteFormat = LineSelectedType ;
444+ else if ( rectangular && textArea . Selection . IsEmpty && ! ( textArea . Selection is RectangleSelection ) )
445+ pasteFormat = RectangleSelection . RectangularSelectionDataType ;
446+ else
447+ pasteFormat = DataFormats . UnicodeText ;
448+
449+ var pastingEventArgs = new DataObjectPastingEventArgs ( dataObject , false , pasteFormat ) ;
450+ textArea . RaiseEvent ( pastingEventArgs ) ;
451+ if ( pastingEventArgs . CommandCancelled )
452+ return ;
453+
454+ // DataObject.PastingEvent handlers might have changed the format to apply.
455+ pasteFormat = pastingEventArgs . FormatToApply ;
456+
457+ fullLine = pasteFormat == LineSelectedType ;
458+ rectangular = pasteFormat == RectangleSelection . RectangularSelectionDataType ;
459+
414460 if ( fullLine ) {
415461 DocumentLine currentLine = textArea . Document . GetLineByNumber ( textArea . Caret . Line ) ;
416462 if ( textArea . ReadOnlySectionProvider . CanInsert ( currentLine . Offset ) ) {
0 commit comments