Add support for cut, copy, paste API on Text widget

The implementation is based on Clipboard API. Only SWT_COMPATIBILITY
mode is supported. Exceptions during clipboard transfer are ignored.

Change-Id: I8e3166a4235d7df3381d79e237f7e037abd144d6
diff --git a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Text.java b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Text.java
index d1d60fc..bd30607 100644
--- a/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Text.java
+++ b/bundles/org.eclipse.rap.rwt/src/org/eclipse/swt/widgets/Text.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH.
+ * Copyright (c) 2002, 2021 Innoopract Informationssysteme GmbH.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -17,6 +17,9 @@
 import org.eclipse.rap.rwt.internal.theme.ThemeAdapter;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.SWTException;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
@@ -29,7 +32,6 @@
 import org.eclipse.swt.internal.widgets.textkit.TextLCA;
 import org.eclipse.swt.internal.widgets.textkit.TextThemeAdapter;
 
-
 /**
  * Instances of this class are selectable user interface
  * objects that allow the user to enter and modify text.
@@ -1024,6 +1026,101 @@
     removeListener( SWT.Verify, listener );
   }
 
+  /**
+   * Cuts the selected text.
+   * <p>
+   * The current selection is first copied to the
+   * clipboard and then deleted from the widget.
+   * </p>
+   *
+   * @exception UnsupportedOperationException when running the application in JEE_COMPATIBILITY mode
+   * @exception SWTException <ul>
+   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+   * </ul>
+   *
+   * @see org.eclipse.rap.rwt.application.Application.OperationMode
+   *
+   * @since 3.16
+   */
+  public void cut() {
+    checkWidget();
+    if( ( style & SWT.READ_ONLY ) == 0 ) {
+      try {
+        Clipboard clipboard = new Clipboard( display );
+        Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() };
+        Object[] data = new Object[] { getSelectionText() };
+        text = new StringBuffer( text ).replace( selection.x, selection.y, "" ).toString();
+        clipboard.setContents( data, transfers );
+        clipboard.dispose();
+      } catch ( @SuppressWarnings( "unused" ) Exception e ) {
+        // ignore unsupported browsers
+      }
+    }
+  }
+
+  /**
+   * Copies the selected text.
+   * <p>
+   * The current selection is copied to the clipboard.
+   * </p>
+   *
+   * @exception UnsupportedOperationException when running the application in JEE_COMPATIBILITY mode
+   * @exception SWTException <ul>
+   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+   * </ul>
+   *
+   * @see org.eclipse.rap.rwt.application.Application.OperationMode
+   *
+   * @since 3.16
+   */
+  public void copy() {
+    checkWidget();
+    try {
+      Clipboard clipboard = new Clipboard( display );
+      Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() };
+      Object[] data = new Object[] { getSelectionText() };
+      clipboard.setContents( data, transfers );
+      clipboard.dispose();
+    } catch ( @SuppressWarnings( "unused" ) Exception e ) {
+      // ignore unsupported browsers
+    }
+  }
+
+  /**
+   * Pastes text from clipboard.
+   * <p>
+   * The selected text is deleted from the widget
+   * and new text inserted from the clipboard.
+   * </p>
+   *
+   * @exception UnsupportedOperationException when running the application in JEE_COMPATIBILITY mode
+   * @exception SWTException <ul>
+   *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+   *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+   * </ul>
+   *
+   * @see org.eclipse.rap.rwt.application.Application.OperationMode
+   *
+   * @since 3.16
+   */
+  public void paste() {
+    checkWidget();
+    if( ( style & SWT.READ_ONLY ) == 0 ) {
+      try {
+        Clipboard clipboard = new Clipboard( display );
+        String content = ( String )clipboard.getContents( TextTransfer.getInstance() );
+        if( content != null ) {
+          text = new StringBuffer( text ).replace( selection.x, selection.y, content ).toString();
+        }
+        clipboard.dispose();
+      } catch ( @SuppressWarnings( "unused" ) Exception e ) {
+        // ignore unsupported browsers
+      }
+    }
+  }
+
   @Override
   @SuppressWarnings("unchecked")
   public <T> T getAdapter( Class<T> adapter ) {
diff --git a/examples/org.eclipse.rap.demo.controls/src/org/eclipse/rap/demo/controls/TextTab.java b/examples/org.eclipse.rap.demo.controls/src/org/eclipse/rap/demo/controls/TextTab.java
index 8f5f8ef..8e019cb 100644
--- a/examples/org.eclipse.rap.demo.controls/src/org/eclipse/rap/demo/controls/TextTab.java
+++ b/examples/org.eclipse.rap.demo.controls/src/org/eclipse/rap/demo/controls/TextTab.java
@@ -424,6 +424,33 @@
         text.insert( insertText.getText() );
       }
     } );
+    new Label( group, SWT.NONE );
+    Button cutButton = new Button( group, SWT.PUSH );
+    cutButton.setText( "Cut" );
+    cutButton.addSelectionListener( new SelectionAdapter() {
+      @Override
+      public void widgetSelected( SelectionEvent e ) {
+        text.cut();
+      }
+    } );
+    new Label( group, SWT.NONE );
+    Button copyButton = new Button( group, SWT.PUSH );
+    copyButton.setText( "Copy" );
+    copyButton.addSelectionListener( new SelectionAdapter() {
+      @Override
+      public void widgetSelected( SelectionEvent e ) {
+        text.copy();
+      }
+    } );
+    new Label( group, SWT.NONE );
+    Button pasteButton = new Button( group, SWT.PUSH );
+    pasteButton.setText( "Paste" );
+    pasteButton.addSelectionListener( new SelectionAdapter() {
+      @Override
+      public void widgetSelected( SelectionEvent e ) {
+        text.paste();
+      }
+    } );
   }
 
   private void createMessage( Composite parent ) {