summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org')
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/ByteArrayTransfer.java48
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Clipboard.java206
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DragSource.java460
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DropTarget.java540
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/FileTransfer.java66
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/RTFTransfer.java42
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TableDragUnderEffect.java63
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TextTransfer.java42
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Transfer.java26
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TransferData.java18
-rwxr-xr-xbundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TreeDragUnderEffect.java100
11 files changed, 1611 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/ByteArrayTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/ByteArrayTransfer.java
new file mode 100755
index 0000000000..df1a8dd4b9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/ByteArrayTransfer.java
@@ -0,0 +1,48 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.motif.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public abstract class ByteArrayTransfer extends Transfer {
+public TransferData[] getSupportedTypes(){
+ int[] types = getTypeIds();
+ TransferData[] data = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ data[i] = new TransferData();
+ data[i].type = types[i];
+ }
+ return data;
+}
+public boolean isSupportedType(TransferData transferData){
+ int[] types = getTypeIds();
+ for (int i = 0; i < types.length; i++) {
+ if (transferData.type == types[i]) return true;
+ }
+ return false;
+}
+protected void javaToNative (Object object, TransferData transferData){
+ if ((object == null) || !(object instanceof byte[]) || !(isSupportedType(transferData))) {
+ transferData.result = 0;
+ return;
+ }
+ byte[] buffer = (byte[])object;
+ transferData.pValue = OS.XtMalloc(buffer.length + 1);
+ OS.memmove(transferData.pValue, buffer, buffer.length);
+ transferData.length = buffer.length;
+ transferData.format = 8;
+ transferData.result = 1;
+}
+protected Object nativeToJava(TransferData transferData){
+
+ if (transferData.pValue == 0 || !(isSupportedType(transferData))) return null;
+
+ int size = transferData.format * transferData.length / 8;
+ byte[] buffer = new byte[size];
+ OS.memmove(buffer, transferData.pValue, size);
+ return buffer;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Clipboard.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Clipboard.java
new file mode 100755
index 0000000000..a7c099fe60
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Clipboard.java
@@ -0,0 +1,206 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.motif.*;
+import org.eclipse.swt.widgets.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+/*
+ *
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ *
+ */
+public class Clipboard {
+
+ private Display display;
+ private final int MAX_RETRIES = 10;
+ private int shellHandle;
+
+
+public Clipboard(Display display) {
+ checkSubclass ();
+ if (display == null) {
+ display = Display.getCurrent();
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ }
+ if (display.getThread() != Thread.currentThread()) {
+ SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.display = display;
+
+ int widgetClass = OS.TopLevelShellWidgetClass ();
+ shellHandle = OS.XtAppCreateShell (null, null, widgetClass, display.xDisplay, null, 0);
+ OS.XtSetMappedWhenManaged (shellHandle, false);
+ OS.XtRealizeWidget (shellHandle);
+}
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = Clipboard.class.getName();
+ if (!validName.equals(name)) {
+ DND.error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+public void dispose () {
+ if (shellHandle != 0) OS.XtDestroyWidget (shellHandle);
+ shellHandle = 0;
+ display = null;
+}
+public Object getContents(Transfer transfer) {
+ if (display.isDisposed() ) return null;
+ int xDisplay = OS.XtDisplay (shellHandle);
+ if (xDisplay == 0) return null;
+ int xWindow = OS.XtWindow (shellHandle);
+ if (xWindow == 0) return null;
+
+ // Open clipboard for retrieval
+ int retries = 0;
+ int status = OS.XmClipboardStartRetrieve(xDisplay, xWindow, OS.XtLastTimestampProcessed(xDisplay));
+ while ( status == OS.XmClipboardLocked && retries < MAX_RETRIES) {
+ retries ++;
+ status = OS.XmClipboardStartRetrieve(xDisplay, xWindow, OS.XtLastTimestampProcessed(xDisplay));
+ };
+ if (status != OS.XmClipboardSuccess) return null;
+
+ // Does Clipboard have data in required format?
+ String type = null;
+ int[] length = new int[1];
+ String[] supportedTypes = transfer.getTypeNames();
+ for (int i = 0; i < supportedTypes.length; i++) {
+ if (OS.XmClipboardInquireLength(xDisplay, xWindow, supportedTypes[i].getBytes(), length) == 1 /*OS.XmClipboardSuccess*/ ) {
+ type = supportedTypes[i];
+ break;
+ }
+ }
+
+ // Retrieve data from Clipboard
+ byte[] data = null;
+ if (type != null) {
+ data = new byte[length[0]];
+ status = OS.XmClipboardRetrieve(xDisplay, xWindow, type.getBytes(), data, length[0], new int[1], new int[1]);
+ if (status != OS.XmClipboardSuccess) {
+ data = null;
+ }
+ }
+
+ // Close Clipboard
+ status = OS.XmClipboardEndRetrieve(xDisplay, xWindow);
+
+ if (data == null) return null;
+
+ // Pass data to transfer agent for conversion to a Java Object
+ // Memory is allocated here to emulate the way Drag and Drop transfers data.
+ TransferData transferData = new TransferData();
+ byte[] bName = Converter.wcsToMbcs (null, type, false);
+ transferData.type = OS.XmInternAtom (xDisplay, bName, false);
+ transferData.pValue = OS.XtMalloc(data.length);
+ OS.memmove(transferData.pValue, data, data.length);
+ transferData.length = data.length;
+ transferData.format = 8;
+ transferData.result = 1;
+
+ Object result = transfer.nativeToJava(transferData);
+
+ // Clean up allocated memory
+ OS.XtFree(transferData.pValue);
+
+ return result;
+}
+public void setContents(Object[] data, Transfer[] transferAgents){
+
+ if (data == null) {
+ DND.error(SWT.ERROR_NOT_IMPLEMENTED);
+ }
+ if (transferAgents == null || data.length != transferAgents.length) {
+ DND.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ if (display.isDisposed() )
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+ int xDisplay = OS.XtDisplay (shellHandle);
+ if (xDisplay == 0)
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+ int xWindow = OS.XtWindow (shellHandle);
+ if (xWindow == 0)
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+
+ // Open clipboard for setting
+ int[] item_id = new int[1];
+ int retries = 0;
+ int status = OS.XmClipboardStartCopy(xDisplay, xWindow, 0, OS.XtLastTimestampProcessed(xDisplay), shellHandle, 0, item_id);
+ while ( status == OS.XmClipboardLocked && retries < MAX_RETRIES) {
+ retries ++;
+ status = OS.XmClipboardStartCopy(xDisplay, xWindow, 0, OS.XtLastTimestampProcessed(xDisplay), shellHandle, 0, item_id);
+ };
+ if (status != OS.XmClipboardSuccess)
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+
+ // copy data directly over to System clipboard (not deferred)
+ for (int i = 0; i < transferAgents.length; i++) {
+ String[] names = transferAgents[i].getTypeNames();
+ for (int j = 0; j < names.length; j++) {
+
+ TransferData transferData = new TransferData();
+ byte[] bName = Converter.wcsToMbcs (null, names[j], false);
+ transferData.type = OS.XmInternAtom (xDisplay, bName, false);
+ transferAgents[i].javaToNative(data[i], transferData);
+ status = OS.XmClipboardFail;
+ if (transferData.result == 1 && transferData.format == 8){
+ byte[] buffer = new byte[transferData.length];
+ OS.memmove(buffer, transferData.pValue, transferData.length);
+ status = OS.XmClipboardCopy(xDisplay, xWindow, item_id[0], bName, buffer, transferData.length, 0, null);
+ }
+ // Clean up allocated memory
+ if (transferData.pValue != 0) {
+ OS.XtFree(transferData.pValue);
+ }
+ }
+ }
+
+ // close clipboard for setting
+ OS.XmClipboardEndCopy(xDisplay, xWindow, item_id[0]);
+
+ if (status != OS.XmClipboardSuccess)
+ DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD);
+
+}
+/*
+ * Note: getAvailableTypeNames is a tool for writing a Transfer sub-class only. It should
+ * NOT be used within an application because it provides platform specfic
+ * information.
+ */
+public String[] getAvailableTypeNames() {
+ int[] count = new int[1];
+ int[] max_length = new int[1];
+ int xDisplay = OS.XtDisplay (shellHandle);
+ if (xDisplay == 0)
+ DND.error(SWT.ERROR_UNSPECIFIED);
+ int xWindow = OS.XtWindow (shellHandle);
+ if (xWindow == 0)
+ DND.error(SWT.ERROR_UNSPECIFIED);
+ if (OS.XmClipboardInquireCount(xDisplay, xWindow, count, max_length) != OS.XmClipboardSuccess)
+ DND.error(SWT.ERROR_UNSPECIFIED);
+ String[] types = new String[count[0]];
+ for (int i = 0; i < count[0]; i++) {
+ byte[] buffer = new byte[max_length[0]];
+ int[] copied_length = new int[1];
+ int rc = OS.XmClipboardInquireFormat(xDisplay, xWindow, i + 1, buffer, buffer.length, copied_length);
+ if (rc == OS.XmClipboardNoData){
+ types[i] = "";
+ continue;
+ }
+ if (rc != OS.XmClipboardSuccess)
+ DND.error(SWT.ERROR_UNSPECIFIED);
+ byte[] buffer2 = new byte[copied_length[0]];
+ System.arraycopy(buffer, 0, buffer2, 0, copied_length[0]);
+ types[i] = new String(buffer2);
+ }
+ return types;
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DragSource.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DragSource.java
new file mode 100755
index 0000000000..db1d34e248
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DragSource.java
@@ -0,0 +1,460 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.motif.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+/**
+ *
+ * Class <code>DragSource</code> defines the source object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ *
+ * <p>This class defines the following items:<ul>
+ * <li>the <code>Control</code> that the user clicks on to intiate a drag;
+ * <li>the data that will be transferred on a successful drop;
+ * <li>and the modes (move, copy, link) of transfer that are allowed.
+ * </ul></p>
+ *
+ * <p>You may have several DragSources in an application but you can only have one DragSource
+ * per Control. Data dragged from this DragSource can be dropped on a site within this application
+ * but it can also be dropped on another application such as an external Text editor.</p>
+ *
+ * <p>The application supplies the content of the data being transferred by implementing the interface
+ * <code>DragSourceListener</code> which uses the class <code>DragSourceEvent</code>.
+ * The application is required to take the appropriate action to remove the data from the drag source
+ * when a successful move operation occurs.</p>
+ *
+ * <code><pre>
+ * // Enable a label as a Drag Source
+ * Label label = new Label(shell, SWT.NONE);
+ * // This example will allow text to be dragged
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * // This example will allow the text to be copied or moved to the drop target
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY;
+ *
+ * DragSource source = new DragSource (label, operations);
+ * source.setTransfer(types);
+ * source.addDragListener (new DragSourceListener() {
+ * public void dragStart(DragSourceEvent e) {
+ * // Only start the drag if there is actually text in the
+ * // label - this text will be what is dropped on the target.
+ * if (label.getText().length() == 0) {
+ * event.doit = false;
+ * }
+ * };
+ * public void dragSetData (DragSourceEvent event) {
+ * // A drop has been performed, so provide the data of the
+ * // requested type.
+ * // (Checking the type of the requested data is only
+ * // necessary if the drag source supports more than
+ * // one data type but is shown here as an example).
+ * if (TextTransfer.getInstance().isSupportedType(event.dataType)){
+ * event.data = label.getText();
+ * }
+ * }
+ * public void dragFinished(DragSourceEvent event) {
+ * // A Move operation has been performed so remove the data
+ * // from the source
+ * if (event.detail == DND.DROP_MOVE)
+ * label.setText("");
+ * }
+ * });
+ * </pre></code>
+ *
+ *
+ * <dl>
+ * <dt><b>Styles</b> <dd>DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ * <dt><b>Events</b> <dd>DND.DragEnd, DND.DragSetData
+ * </dl>
+ */
+public class DragSource extends Widget {
+
+ private Callback convertProc;
+ private Callback dragDropFinish;
+ private Callback dropFinish;
+
+ // info for registering as a drag source
+ private Control control;
+ private Listener controlListener;
+ private Transfer[] transferAgents = new Transfer[0];
+
+ private boolean myDrag;
+
+ int dragContext;
+
+public DragSource(Control control, int style) {
+ super (control, checkStyle(style));
+
+ this.control = control;
+
+ controlListener = new Listener () {
+ public void handleEvent (Event event) {
+ if (event.type == SWT.Dispose) {
+ if (!DragSource.this.isDisposed()){
+ DragSource.this.dispose();
+ }
+ }
+ if (event.type == SWT.DragDetect){
+ DragSource.this.drag();
+ }
+
+ }
+ };
+ this.control.addListener (SWT.Dispose, controlListener);
+ this.control.addListener (SWT.DragDetect, controlListener);
+
+ this.addListener (SWT.Dispose, new Listener () {
+ public void handleEvent (Event event) {
+ onDispose();
+ }
+ });
+}
+/**
+* Adds the listener to receive events.
+* <p>
+*
+* @param listener the listener
+*
+* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
+* when called from the wrong thread
+* @exception SWTError(ERROR_WIDGET_DISPOSED)
+* when the widget has been disposed
+* @exception SWTError(ERROR_NULL_ARGUMENT)
+* when listener is null
+*/
+public void addDragListener(DragSourceListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener (listener);
+ addListener (DND.DragStart, typedListener);
+ addListener (DND.DragSetData, typedListener);
+ addListener (DND.DragEnd, typedListener);
+}
+static int checkStyle (int style) {
+ if (style == SWT.NONE) return DND.DROP_MOVE;
+ return style;
+}
+private int convertProcCallback(int widget, int pSelection, int pTarget, int pType_return, int ppValue_return, int pLength_return, int pFormat_return, int max_length, int client_data, int request_id) {
+ /*
+ pSelection - atom specifying which property is being used to transfer the selection (only support _MOTIF_DROP)
+ pTarget - atom specifying the type in which the requestor wants the information
+ pType_return - [out] type atom that data has been converted to (usually the same as pTarget)
+ ppValue_return - [out] set to a pointer to a block of memory
+ pLength_return - [out] number of elements in the array
+ pFormat_return - [out] size in bits of each element in the array
+
+ */
+
+ if (pSelection == 0 )
+ return 0;
+
+ // is this a drop?
+ int[] selection = new int[1];
+ OS.memmove(selection, pSelection, 4);
+ int motifDropAtom = Transfer.registerType("_MOTIF_DROP\0");
+ if (selection[0] != motifDropAtom) return 0;
+
+ // get the target value from pTarget
+ int[] target = new int[1];
+ OS.memmove(target, pTarget, 4);
+
+ // handle the "Move" case
+ if (target[0] == Transfer.registerType("DELETE\0")) { // DELETE corresponds to a Move request
+ OS.memmove(pType_return,new int[]{Transfer.registerType("NULL\0")}, 4);
+ OS.memmove(ppValue_return, new int[]{0}, 4);
+ OS.memmove(pLength_return, new int[]{0}, 4);
+ OS.memmove(pFormat_return, new int[]{8}, 4);
+ return 1;
+ }
+
+ // do we support the requested data type?
+ boolean dataMatch = true;
+ TransferData transferData = new TransferData();
+ transferData.type = target[0];
+ for (int i = 0; i < transferAgents.length; i++){
+ if (transferAgents[i].isSupportedType(transferData)){
+ dataMatch = true;
+ break;
+ }
+ }
+ if (!dataMatch) return 0;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = control;
+ //event.time = ??;
+ event.dataType = transferData;
+ try {
+ notifyListeners(DND.DragSetData,event);
+ } catch (Throwable err) {
+ return 0;
+ }
+
+ if (event.data == null) return 0;
+
+ Transfer transferAgent = null;
+ for (int i = 0; i < transferAgents.length; i++){
+ if (transferAgents[i].isSupportedType(transferData)){
+ transferAgent = transferAgents[i];
+ break;
+ }
+ }
+ if (transferAgent == null) return 0;
+
+ transferAgent.javaToNative(event.data, transferData);
+ if (transferData.result == 1){
+ OS.memmove(ppValue_return, new int[]{transferData.pValue}, 4);
+ OS.memmove(pType_return, new int[]{transferData.type}, 4);
+ OS.memmove(pLength_return, new int[]{transferData.length}, 4);
+ OS.memmove(pFormat_return, new int[]{transferData.format}, 4);
+ return 1;
+ } else {
+ OS.memmove(ppValue_return, new int[]{0}, 4);
+ OS.memmove(pLength_return, new int[]{0}, 4);
+ OS.memmove(pFormat_return, new int[]{8}, 4);
+ return 0;
+ }
+}
+private void drag() {
+ if (transferAgents == null)
+ return;
+
+ // Current event must be a Button Press event
+ Display display = control.getDisplay ();
+ if (display.xEvent.type != OS.ButtonPress) return;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this;
+ event.time = display.xEvent.pad2;
+ event.doit = true;
+
+ try {
+ notifyListeners(DND.DragStart, event);
+ } catch (Throwable e) {
+ event.doit = false;
+ }
+
+ if (!event.doit) {
+ int time = display.xEvent.pad2; // corresponds to time field in XButtonEvent
+ int[] args = new int[]{ OS.XmNdragOperations, OS.XmDROP_NOOP};
+ int dc = OS.XmGetDragContext(control.handle, time);
+ if (dc != 0){
+ OS.XtSetValues(dc, args, args.length /2);
+ } else {
+ dc = OS.XmDragStart(this.control.handle, display.xEvent, args, args.length/2);
+ }
+ return;
+ }
+
+ // set the protocol (optional)
+ // not implemented
+
+ // create pixmaps for icons (optional)
+ // not implemented
+
+ // Copy targets to global memory
+ TransferData[] transferData = new TransferData[0];
+ for (int i = 0; i < transferAgents.length; i++){
+ TransferData[] data = transferAgents[i].getSupportedTypes();
+ TransferData[] newTransferData = new TransferData[transferData.length + data.length];
+ System.arraycopy(transferData, 0, newTransferData, 0, transferData.length);
+ System.arraycopy(data, 0, newTransferData, transferData.length, data.length);
+ transferData = newTransferData;
+ }
+ int[] dataTypes = new int[transferData.length];
+ for (int i = 0; i < transferData.length; i++){
+ dataTypes[i] = transferData[i].type;
+ }
+ int pExportTargets = OS.XtMalloc(dataTypes.length * 4);
+ OS.memmove(pExportTargets, dataTypes, dataTypes.length * 4);
+
+ if (convertProc == null)
+ convertProc = new Callback(this, "convertProcCallback", 10);
+ if (convertProc == null) return;
+
+ int[] args = new int[]{
+ OS.XmNexportTargets, pExportTargets,
+ OS.XmNnumExportTargets, dataTypes.length,
+ OS.XmNdragOperations, opToOsOp(getStyle()),
+ OS.XmNconvertProc, convertProc.getAddress(),
+ OS.XmNoperationCursorIcon, 0,
+ OS.XmNsourceCursorIcon, 0,
+ OS.XmNstateCursorIcon, 0,
+ OS.XmNclientData, 0,
+ OS.XmNblendModel, OS.XmBLEND_ALL
+ };
+
+ // look for existing drag contexts
+ int time = display.xEvent.pad2; // corresponds to time field in XButtonEvent
+ dragContext = OS.XmGetDragContext(control.handle, time);
+ if (dragContext != 0){
+ OS.XtSetValues(dragContext, args, args.length /2);
+ } else {
+ dragContext = OS.XmDragStart(this.control.handle, display.xEvent, args, args.length / 2);
+ myDrag = true;
+ }
+ OS.XtFree(pExportTargets);
+ if (dragContext == 0) return;
+
+ // register a call back to clean up when drop is done (optional)
+ if (dragDropFinish == null)
+ dragDropFinish = new Callback(this, "dragDropFinishCallback", 3);
+ OS.XtAddCallback(dragContext, OS.XmNdragDropFinishCallback, dragDropFinish.getAddress(), 0);
+
+ // register a call back to tell user what happened (optional)
+ if (dropFinish == null)
+ dropFinish = new Callback(this, "dropFinishCallback", 3);
+ OS.XtAddCallback(dragContext, OS.XmNdropFinishCallback, dropFinish.getAddress(), 0);
+ return;
+}
+
+private int dragDropFinishCallback(int widget, int client_data, int call_data) {
+
+ // uncomment the following code when we allow users to specify their own source icons
+ // release the pre set source icon
+ //int pSourceIcon = OS.XtMalloc(4);
+ //int[] args = new int[]{OS.XmNsourceCursorIcon, pSourceIcon};
+ //OS.XtGetValues(control.handle, args, args.length / 2);
+ //int[] sourceIcon = new int[1];
+ //OS.memmove(sourceIcon, pSourceIcon, 4);
+ //if (sourceIcon[0] != 0)
+ //OS.XtDestroyWidget(sourceIcon[0]);
+ //OS.XtFree(pSourceIcon);
+
+ dragContext = 0;
+
+ if (convertProc != null)
+ convertProc.dispose();
+ convertProc = null;
+
+ if (dragDropFinish != null)
+ dragDropFinish.dispose();
+ dragDropFinish = null;
+
+ if (dropFinish != null)
+ dropFinish.dispose();
+ dropFinish = null;
+
+ return 0;
+}
+private int dropFinishCallback(int widget, int client_data, int call_data) {
+
+ XmDropFinishCallback data = new XmDropFinishCallback();
+ OS.memmove(data, call_data, XmDropFinishCallback.sizeof);
+
+ if (data.dropAction != OS.XmDROP || data.dropSiteStatus != OS.XmDROP_SITE_VALID) return 0;
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this.control;
+ event.time = data.timeStamp;
+ event.detail = osOpToOp(data.operation);
+ event.doit = (data.completionStatus != 0);
+
+ try {
+ notifyListeners(DND.DragEnd,event);
+ } catch (Throwable err) {
+ }
+
+ return 0;
+}
+public Control getControl () {
+ return control;
+}
+/**
+* Gets the Display.
+*/
+public Display getDisplay () {
+
+ if (control == null) DND.error(SWT.ERROR_WIDGET_DISPOSED);
+ return control.getDisplay ();
+}
+public Transfer[] getTransfer(){
+ return transferAgents;
+}
+private void onDispose() {
+
+ // Check if there is a drag in progress and cancel it
+ //if (dragContext != 0 && myDrag)
+ // OS.XmDragCancel(dragContext);
+
+ if (convertProc != null)
+ convertProc.dispose();
+ convertProc = null;
+
+ if (dragDropFinish != null)
+ dragDropFinish.dispose();
+ dragDropFinish = null;
+
+ if (dropFinish != null)
+ dropFinish.dispose();
+ dropFinish = null;
+
+ if (control != null && controlListener != null) {
+ control.removeListener(SWT.Dispose, controlListener);
+ control.removeListener(SWT.DragDetect, controlListener);
+ }
+ control = null;
+ controlListener = null;
+ transferAgents = null;
+}
+private byte opToOsOp(int operation){
+ byte osOperation = OS.XmDROP_NOOP;
+
+ if ((operation & DND.DROP_COPY) == DND.DROP_COPY)
+ osOperation |= OS.XmDROP_COPY;
+ if ((operation & DND.DROP_MOVE) == DND.DROP_MOVE)
+ osOperation |= OS.XmDROP_MOVE;
+ if ((operation & DND.DROP_LINK) == DND.DROP_LINK)
+ osOperation |= OS.XmDROP_LINK;
+
+ return osOperation;
+}
+private int osOpToOp(byte osOperation){
+ int operation = DND.DROP_NONE;
+
+ if ((osOperation & OS.XmDROP_COPY) == OS.XmDROP_COPY)
+ operation |= DND.DROP_COPY;
+ if ((osOperation & OS.XmDROP_MOVE) == OS.XmDROP_MOVE)
+ operation |= DND.DROP_MOVE;
+ if ((osOperation & OS.XmDROP_LINK) == OS.XmDROP_LINK)
+ operation |= DND.DROP_LINK;
+
+ return operation;
+}
+/**
+* Removes the listener.
+* <p>
+*
+* @param listener the listener
+*
+* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
+* when called from the wrong thread
+* @exception SWTError(ERROR_WIDGET_DISPOSED)
+* when the widget has been disposed
+* @exception SWTError(ERROR_NULL_ARGUMENT)
+* when listener is null
+*/
+public void removeDragListener(DragSourceListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ removeListener (DND.DragStart, listener);
+ removeListener (DND.DragSetData, listener);
+ removeListener (DND.DragEnd, listener);
+}
+public void setTransfer(Transfer[] transferAgents){
+ this.transferAgents = transferAgents;
+}
+
+
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = DragSource.class.getName();
+ if (!validName.equals(name)) {
+ DND.error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DropTarget.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DropTarget.java
new file mode 100755
index 0000000000..cdef0449d4
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/DropTarget.java
@@ -0,0 +1,540 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.motif.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+/**
+ *
+ * Class <code>DropTarget</code> defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is <em>not</em> intended to be subclassed.
+ *
+ * <p>This class identifies the <code>Control</code> over which the user must position the cursor
+ * in order to drop the data being transferred. It also specifies what data types can be dropped on
+ * this control and what operations can be performed. You may have several DropTragets in an
+ * application but there can only be a one to one mapping between a <code>Control</code> and a <code>DropTarget</code>.
+ * The DropTarget can receive data from within the same application or from other applications
+ * (such as text dragged from a text editor like Word).</p>
+ *
+ * <code><pre>
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * DropTarget target = new DropTarget(label, operations);
+ * target.setTransfer(types);
+ * </code></pre>
+ *
+ * <p>The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface <code>DropTargetListener</code> which uses the class
+ * <code>DropTargetEvent</code>. The application can modify the type of drag being performed
+ * on this Control at any stage of the drag by modifying the <code>event.detail</code> field or the
+ * <code>event.currentDataType</code> field. When the data is dropped, it is the responsibility of
+ * the application to copy this data for its own purposes.
+ *
+ * <code><pre>
+ * target.addDropListener (new DropTargetListener() {
+ * public void dragEnter(DropTargetEvent event) {};
+ * public void dragOver(DropTargetEvent event) {};
+ * public void dragLeave(DropTargetEvent event) {};
+ * public void dragOperationChanged(DropTargetEvent event) {};
+ * public void dropAccept(DropTargetEvent event) {}
+ * public void drop(DropTargetEvent event) {
+ * // A drop has occurred, copy over the data
+ * if (event.data == null) { // no data to copy, indicate failure in event.detail
+ * event.detail = DND.DROP_NONE;
+ * return;
+ * }
+ * label.setText ((String) event.data); // data copied to label text
+ * }
+ * });
+ * </pre></code>
+ *
+ * <dl>
+ * <dt><b>Styles</b> <dd>DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ * <dt><b>Events</b> <dd>DND.DragEnter, DND.DragLeave, DND.DragOver, DND.DragOperationChanged,
+ * DND.Drop, DND.DropAccept
+ * </dl>
+ */
+public class DropTarget extends Widget {
+
+ private Callback dropProc;
+ private Callback transferProc;
+ private Callback dragProc;
+
+ // info for registering as a droptarget
+ private Control control;
+ private Listener controlListener;
+ private Transfer[] transferAgents = new Transfer[0];
+
+ // info about data being dragged over site
+ private TransferData selectedDataType;
+ private TransferData[] dataTypes;
+ private int dropTransferObject;
+ private XmDropProcCallback droppedEventData;
+
+ private DragUnderEffect effect;
+
+public DropTarget(Control control, int style) {
+
+ super (control, checkStyle(style));
+
+ this.control = control;
+
+ dropProc = new Callback(this, "dropProcCallback", 3);
+ if (dropProc == null)
+ DND.error(DND.ERROR_CANNOT_INIT_DROP);
+
+ dragProc = new Callback(this, "dragProcCallback", 3);
+ if (dragProc == null)
+ DND.error(DND.ERROR_CANNOT_INIT_DROP);
+
+ int[] args = new int[]{
+ OS.XmNdropSiteOperations, opToOsOp(style),
+ OS.XmNdropSiteActivity, OS.XmDROP_SITE_ACTIVE,
+ OS.XmNdropProc, dropProc.getAddress(),
+ OS.XmNdragProc, dragProc.getAddress()
+ };
+
+ // the OS may have registered this widget as a drop site on creation.
+ // Remove the registered drop site because it has preconfigured values which we do not want.
+ //OS.XmDropSiteUnregister(control.handle);
+ // Register drop site with our own values
+ OS.XmDropSiteRegister(control.handle, args, args.length / 2);
+
+ controlListener = new Listener () {
+ public void handleEvent (Event event) {
+ if (!DropTarget.this.isDisposed()){
+ DropTarget.this.dispose();
+ }
+ }
+ };
+ control.addListener (SWT.Dispose, controlListener);
+
+ this.addListener (SWT.Dispose, new Listener () {
+ public void handleEvent (Event event) {
+ onDispose();
+ }
+ });
+
+ if (control instanceof Tree) {
+ effect = new TreeDragUnderEffect((Tree)control);
+ } else if (control instanceof Table) {
+ effect = new TableDragUnderEffect((Table)control);
+ } else {
+ effect = new NoDragUnderEffect(control);
+ }
+}
+/**
+* Adds the listener to receive events.
+* <p>
+*
+* @param listener the listener
+*
+* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
+* when called from the wrong thread
+* @exception SWTError(ERROR_WIDGET_DISPOSED)
+* when the widget has been disposed
+* @exception SWTError(ERROR_NULL_ARGUMENT)
+* when listener is null
+*/
+public void addDropListener(DropTargetListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ DNDListener typedListener = new DNDListener (listener);
+ addListener (DND.DragEnter, typedListener);
+ addListener (DND.DragLeave, typedListener);
+ addListener (DND.DragOver, typedListener);
+ addListener (DND.DragOperationChanged, typedListener);
+ addListener (DND.Drop, typedListener);
+ addListener (DND.DropAccept, typedListener);
+
+}
+static int checkStyle (int style) {
+ if (style == SWT.NONE) return DND.DROP_MOVE;
+ return style;
+}
+private int dragProcCallback(int widget, int client_data, int call_data) {
+
+ XmDragProcCallback callbackData = new XmDragProcCallback();
+ OS.memmove(callbackData, call_data, XmDragProcCallback.sizeof);
+
+ if (callbackData.reason == OS.XmCR_DROP_SITE_ENTER_MESSAGE){
+ releaseDropInfo();
+
+ // get the export targets
+ int ppExportTargets = OS.XtMalloc(4);
+ int pNumExportTargets = OS.XtMalloc(4);
+ int[] args = new int[]{
+ OS.XmNexportTargets, ppExportTargets,
+ OS.XmNnumExportTargets, pNumExportTargets
+ };
+
+ OS.XtGetValues(callbackData.dragContext, args, args.length / 2);
+ int[] numExportTargets = new int[1];
+ OS.memmove(numExportTargets, pNumExportTargets, 4);
+ OS.XtFree(pNumExportTargets);
+ int[] pExportTargets = new int[1];
+ OS.memmove(pExportTargets, ppExportTargets, 4);
+ OS.XtFree(ppExportTargets);
+ int[] exportTargets = new int[numExportTargets[0]];
+ OS.memmove(exportTargets, pExportTargets[0], 4*numExportTargets[0]);
+ //?OS.XtFree(pExportTargets[0]);
+
+ for (int i = 0, length = exportTargets.length; i < length; i++){
+ for (int j = 0, length2 = transferAgents.length; j < length2; j++){
+ TransferData transferData = new TransferData();
+ transferData.type = exportTargets[i];
+ if (transferAgents[j].isSupportedType(transferData)) {
+ TransferData[] newDataTypes = new TransferData[dataTypes.length + 1];
+ System.arraycopy(dataTypes, 0, newDataTypes, 0, dataTypes.length);
+ newDataTypes[dataTypes.length] = transferData;
+ dataTypes = newDataTypes;
+ break;
+ }
+ }
+ }
+ }
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this.control;
+ event.time = callbackData.timeStamp;
+ short [] root_x = new short [1];
+ short [] root_y = new short [1];
+ OS.XtTranslateCoords (this.control.handle, (short) callbackData.x, (short) callbackData.y, root_x, root_y);
+ event.x = root_x[0];
+ event.y = root_y[0];
+ event.dataTypes = dataTypes;
+ event.feedback = DND.FEEDBACK_SELECT;
+ event.operations = osOpToOp(callbackData.operations);
+ event.dataType = selectedDataType;
+ event.detail = osOpToOp(callbackData.operation);
+
+ try {
+ switch (callbackData.reason) {
+ case OS.XmCR_DROP_SITE_ENTER_MESSAGE :
+ if (dataTypes.length > 0) {
+ event.dataType = dataTypes[0];
+ }
+ notifyListeners(DND.DragEnter, event);
+ effect.show(event.feedback, event.x, event.y);
+ break;
+
+ case OS.XmCR_DROP_SITE_MOTION_MESSAGE :
+ notifyListeners(DND.DragOver, event);
+ effect.show(event.feedback, event.x, event.y);
+ break;
+ case OS.XmCR_OPERATION_CHANGED :
+ notifyListeners(DND.DragOperationChanged, event);
+ effect.show(event.feedback, event.x, event.y);
+ break;
+ case OS.XmCR_DROP_SITE_LEAVE_MESSAGE :
+ event.detail = DND.DROP_NONE;
+ notifyListeners(DND.DragLeave, event);
+ effect.show(DND.FEEDBACK_NONE, 0, 0);
+ return 0;
+ }
+ } catch (Throwable err) {
+ callbackData.dropSiteStatus = OS.XmDROP_SITE_INVALID;
+ callbackData.operation = opToOsOp(DND.DROP_NONE);
+ OS.memmove(call_data, callbackData, XmDragProcCallback.sizeof);
+ return 0;
+ }
+
+ selectedDataType = null;
+ for (int i = 0; i < dataTypes.length; i++) {
+ if (dataTypes[i].equals(event.dataType)) {
+ selectedDataType = event.dataType;
+ break;
+ }
+ }
+ int lastOperation = DND.DROP_NONE;
+ if (selectedDataType != null && ((event.detail & osOpToOp(callbackData.operations)) == event.detail)) {
+ lastOperation = event.detail;
+ }
+
+ callbackData.dropSiteStatus = OS.XmDROP_SITE_VALID;
+ callbackData.operation = opToOsOp(lastOperation);
+ OS.memmove(call_data, callbackData, XmDragProcCallback.sizeof);
+
+ return 0;
+}
+private int dropProcCallback(int widget, int client_data, int call_data) {
+
+ effect.show(DND.FEEDBACK_NONE, 0, 0);
+
+ droppedEventData = new XmDropProcCallback();
+ OS.memmove(droppedEventData, call_data, XmDropProcCallback.sizeof);
+
+ DNDEvent event = new DNDEvent();
+ event.widget = this.control;
+ event.time = droppedEventData.timeStamp;
+ short [] root_x = new short [1];
+ short [] root_y = new short [1];
+ OS.XtTranslateCoords (this.control.handle, (short) droppedEventData.x, (short) droppedEventData.y, root_x, root_y);
+ event.x = root_x[0];
+ event.y = root_y[0];
+ event.dataTypes = dataTypes;
+ event.operations = osOpToOp(droppedEventData.operations);
+ event.dataType = selectedDataType;
+ event.detail = osOpToOp(droppedEventData.operation);
+
+ try {
+ notifyListeners(DND.DropAccept,event);
+ } catch (Throwable err) {
+ event.detail = DND.DROP_NONE;
+ event.dataType = null;
+ }
+
+ selectedDataType = null;
+ for (int i = 0; i < dataTypes.length; i++) {
+ if (dataTypes[i].equals(event.dataType)) {
+ selectedDataType = event.dataType;
+ break;
+ }
+ }
+ int lastOperation = DND.DROP_NONE;
+ if (selectedDataType != null && ((event.detail & osOpToOp(droppedEventData.operations)) == event.detail)) {
+ lastOperation = event.detail;
+ }
+
+ if (lastOperation == DND.DROP_NONE) {
+ // this was not a successful drop
+ int[] args = new int[] {OS.XmNtransferStatus, OS.XmTRANSFER_FAILURE,
+ OS.XmNnumDropTransfers, 0};
+ dropTransferObject = OS.XmDropTransferStart(droppedEventData.dragContext, args, args.length / 2);
+ return 0;
+ }
+
+ // ask drag source for dropped data
+ int[] transferEntries = new int[2];
+ transferEntries[0] = 0;
+ transferEntries[1] = selectedDataType.type;
+
+ int pTransferEntries = OS.XtMalloc(transferEntries.length * 4);
+ OS.memmove(pTransferEntries, transferEntries, transferEntries.length * 4);
+ if (transferProc == null)
+ transferProc = new Callback(this, "transferProcCallback", 7);
+
+ if (transferProc != null){
+ int[] args = new int[] {OS.XmNdropTransfers, pTransferEntries,
+ OS.XmNnumDropTransfers, transferEntries.length / 2,
+ OS.XmNtransferProc, transferProc.getAddress()};
+
+ dropTransferObject = OS.XmDropTransferStart(droppedEventData.dragContext, args, args.length / 2);
+ OS.XtFree(pTransferEntries);
+ }
+
+ return 0;
+}
+/**
+ * Returns the Control which is registered for this DropTarget. This is the control over which the
+ * user positions the cursor to drop the data.
+ *
+ * @return the Control which is registered for this DropTarget
+ *
+ */
+public Control getControl () {
+ return control;
+}
+public Display getDisplay () {
+
+ if (control == null) DND.error(SWT.ERROR_WIDGET_DISPOSED);
+ return control.getDisplay ();
+}
+/**
+ * Returns the list of data types that can be transferred to this DropTarget.
+ *
+ * @return the list of data types that can be transferred to this DropTarget
+ *
+ */
+public Transfer[] getTransfer(){
+ return transferAgents;
+}
+public void notifyListeners (int eventType, Event event) {
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = control.toControl(coordinates);
+ if (this.control instanceof Tree) {
+ event.item = ((Tree)control).getItem(coordinates);
+ }
+ if (this.control instanceof Table) {
+ event.item = ((Table)control).getItem(coordinates);
+ }
+ super.notifyListeners(eventType, event);
+}
+private void onDispose() {
+
+ if (dropProc != null)
+ dropProc.dispose();
+ dropProc = null;
+
+ if (transferProc != null)
+ transferProc.dispose();
+ transferProc = null;
+
+ if (dragProc != null)
+ dragProc.dispose();
+ dragProc = null;
+ //if (control != null && !control.isDisposed()){
+ // OS.XmDropSiteUnregister(control.handle);
+ //}
+ if (controlListener != null) {
+ control.removeListener(SWT.Dispose, controlListener);
+ }
+ controlListener = null;
+ control = null;
+ transferAgents = null;
+}
+private byte opToOsOp(int operation){
+ byte osOperation = OS.XmDROP_NOOP;
+
+ if ((operation & DND.DROP_COPY) == DND.DROP_COPY)
+ osOperation |= OS.XmDROP_COPY;
+ if ((operation & DND.DROP_MOVE) == DND.DROP_MOVE)
+ osOperation |= OS.XmDROP_MOVE;
+ if ((operation & DND.DROP_LINK) == DND.DROP_LINK)
+ osOperation |= OS.XmDROP_LINK;
+
+ return osOperation;
+}
+private int osOpToOp(byte osOperation){
+ int operation = DND.DROP_NONE;
+
+ if ((osOperation & OS.XmDROP_COPY) == OS.XmDROP_COPY)
+ operation |= DND.DROP_COPY;
+ if ((osOperation & OS.XmDROP_MOVE) == OS.XmDROP_MOVE)
+ operation |= DND.DROP_MOVE;
+ if ((osOperation & OS.XmDROP_LINK) == OS.XmDROP_LINK)
+ operation |= DND.DROP_LINK;
+
+ return operation;
+}
+private void releaseDropInfo(){
+ selectedDataType = null;
+ dataTypes = new TransferData[0];
+ droppedEventData = null;
+ dropTransferObject = 0;
+}
+/**
+* Adds the listener to receive events.
+* <p>
+*
+* @param listener the listener
+*
+* @exception SWTError(ERROR_THREAD_INVALID_ACCESS)
+* when called from the wrong thread
+* @exception SWTError(ERROR_WIDGET_DISPOSED)
+* when the widget has been disposed
+* @exception SWTError(ERROR_NULL_ARGUMENT)
+* when listener is null
+*/
+public void removeDropListener(DropTargetListener listener) {
+ if (listener == null) DND.error (SWT.ERROR_NULL_ARGUMENT);
+ removeListener (DND.DragEnter, listener);
+ removeListener (DND.DragLeave, listener);
+ removeListener (DND.DragOver, listener);
+ removeListener (DND.DragOperationChanged, listener);
+ removeListener (DND.Drop, listener);
+ removeListener (DND.DropAccept, listener);
+}
+public void setTransfer(Transfer[] transferAgents){
+ this.transferAgents = transferAgents;
+
+ // register data types
+ TransferData[] transferData = new TransferData[0];
+ for (int i = 0, length = transferAgents.length; i < length; i++){
+ TransferData[] data = transferAgents[i].getSupportedTypes();
+ TransferData[] newTransferData = new TransferData[transferData.length + data.length];
+ System.arraycopy(transferData, 0, newTransferData, 0, transferData.length);
+ System.arraycopy(data, 0, newTransferData, transferData.length, data.length);
+ transferData = newTransferData;
+ }
+
+ int[] atoms = new int[transferData.length];
+ for (int i = 0, length = transferData.length; i < length; i++){
+ atoms[i] = transferData[i].type;
+ }
+
+ // Copy import targets to global memory
+ int pImportTargets = OS.XtMalloc(atoms.length * 4);
+ OS.memmove(pImportTargets, atoms, atoms.length * 4);
+
+ int[] args = new int[]{
+ OS.XmNimportTargets, pImportTargets,
+ OS.XmNnumImportTargets, atoms.length
+ };
+
+ OS.XmDropSiteUpdate(control.handle, args, args.length / 2);
+
+ OS.XtFree(pImportTargets);
+
+}
+private int transferProcCallback(int widget, int client_data, int pSelection, int pType, int pValue, int pLength, int pFormat) {
+
+ int[] type = new int[1];
+ OS.memmove(type, pType, 4);
+
+ // get dropped data object
+ Transfer transferAgent = null;
+ TransferData transferData = new TransferData();
+ transferData.type = type[0];
+ for (int i = 0; i < transferAgents.length; i++){
+ if (transferAgents[i].isSupportedType(transferData)){
+ transferAgent = transferAgents[i];
+ break;
+ }
+ }
+ if (transferAgent != null) {
+ transferData.pValue = pValue;
+ int[] length = new int[1];
+ OS.memmove(length, pLength, 4);
+ transferData.length = length[0];
+ int[] format = new int[1];
+ OS.memmove(format, pFormat, 4);
+ transferData.format = format[0];
+ Object data = transferAgent.nativeToJava(transferData);
+
+ OS.XtFree(transferData.pValue); //?? Should we be freeing this, and what about the other memory?
+
+ // notify listeners of drop
+ DNDEvent event = new DNDEvent();
+ event.widget = this.control;
+ event.time = droppedEventData.timeStamp;
+ short [] root_x = new short [1];
+ short [] root_y = new short [1];
+ OS.XtTranslateCoords (this.control.handle, (short) droppedEventData.x, (short) droppedEventData.y, root_x, root_y);
+ event.x = root_x[0];
+ event.y = root_y[0];
+ event.dataTypes = dataTypes;
+ event.operations = osOpToOp(droppedEventData.operations);
+ event.dataType = transferData;
+ event.detail = osOpToOp(droppedEventData.operation);
+ event.data = data;
+
+ try {
+ notifyListeners(DND.Drop,event);
+ } catch (Throwable err) {
+ event.detail = DND.DROP_NONE;
+ }
+
+ if ((event.detail & DND.DROP_MOVE) == DND.DROP_MOVE) {
+ OS.XmDropTransferAdd(dropTransferObject, new int[]{0, Transfer.registerType("DELETE\0")}, 1);
+ }
+ }
+
+ return 0;
+}
+
+protected void checkSubclass () {
+ String name = getClass().getName ();
+ String validName = DropTarget.class.getName();
+ if (!validName.equals(name)) {
+ DND.error (SWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/FileTransfer.java
new file mode 100755
index 0000000000..8b70854312
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/FileTransfer.java
@@ -0,0 +1,66 @@
+package org.eclipse.swt.dnd;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class FileTransfer extends ByteArrayTransfer {
+
+ private static FileTransfer _instance = new FileTransfer();
+ private static final String TYPENAME = "text/uri-list\0";
+ private static final int TYPEID = registerType(TYPENAME);
+
+private FileTransfer() {}
+public static FileTransfer getInstance () {
+ return _instance;
+}
+public void javaToNative(Object object, TransferData transferData) {
+
+ if (object == null || !(object instanceof String[])) return;
+
+ // build a byte array from data
+ String[] files = (String[])object;
+
+ // create a string separated by "new lines" to represent list of files
+ String nativeFormat = "file:";
+ for (int i = 0, length = files.length; i < length; i++){
+ nativeFormat += files[i]+"\r";
+ }
+ nativeFormat += "\0";
+ // pass byte array on to super to convert to native
+ super.javaToNative(nativeFormat.getBytes(), transferData);
+}
+public Object nativeToJava(TransferData transferData) {
+
+ byte[] data = (byte[])super.nativeToJava(transferData);
+ if (data == null) return null;
+ String string = new String(data);
+ // parse data and convert string to array of files
+ int start = string.indexOf("file:");
+ if (start == -1) return null;
+ start += 5;
+ String[] fileNames = new String[0];
+ while (start < string.length()) {
+ int end = string.indexOf("\r", start);
+ if (end == -1) end = string.length() - 1;
+
+ String fileName = string.substring(start, end);
+ String[] newFileNames = new String[fileNames.length + 1];
+ System.arraycopy(fileNames, 0, newFileNames, 0, fileNames.length);
+ newFileNames[fileNames.length] = fileName;
+ fileNames = newFileNames;
+
+ start = string.indexOf("file:", end);
+ if (start == -1) break;
+ start += 5;
+ }
+ return fileNames;
+}
+protected String[] getTypeNames(){
+ return new String[]{TYPENAME};
+}
+protected int[] getTypeIds(){
+ return new int[]{TYPEID};
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/RTFTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/RTFTransfer.java
new file mode 100755
index 0000000000..af09aac900
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/RTFTransfer.java
@@ -0,0 +1,42 @@
+package org.eclipse.swt.dnd;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class RTFTransfer extends ByteArrayTransfer {
+
+ private static RTFTransfer _instance = new RTFTransfer();
+ private static final String TYPENAME1 = "text/rtf\0";
+ private static final int TYPEID1 = registerType(TYPENAME1);
+ private static final String TYPENAME2 = "TEXT/RTF\0";
+ private static final int TYPEID2 = registerType(TYPENAME2);
+ private static final String TYPENAME3 = "application/rtf\0";
+ private static final int TYPEID3 = registerType(TYPENAME3);
+
+private RTFTransfer() {
+}
+public static RTFTransfer getInstance () {
+ return _instance;
+}
+public void javaToNative (Object object, TransferData transferData){
+ if (object == null || !(object instanceof String)) return;
+
+ String text = (String)object;
+ super.javaToNative(text.getBytes(), transferData);
+}
+public Object nativeToJava(TransferData transferData){
+ // get byte array from super
+ byte[] buffer = (byte[])super.nativeToJava(transferData);
+ if (buffer == null) return null;
+ // convert byte array to a string
+ return new String(buffer);
+}
+protected String[] getTypeNames(){
+ return new String[]{TYPENAME1, TYPENAME2, TYPENAME3};
+}
+protected int[] getTypeIds(){
+ return new int[]{TYPEID1, TYPEID2, TYPEID3};
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TableDragUnderEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TableDragUnderEffect.java
new file mode 100755
index 0000000000..231db14dc3
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TableDragUnderEffect.java
@@ -0,0 +1,63 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class TableDragUnderEffect extends DragUnderEffect {
+ private Table table;
+ private TableItem currentItem;
+ private TableItem[] selection = new TableItem[0];
+ private int currentEffect = DND.FEEDBACK_NONE;
+
+TableDragUnderEffect(Table table) {
+ this.table = table;
+}
+void show(int effect, int x, int y) {
+ TableItem item = null;
+ if (effect != DND.FEEDBACK_NONE) item = findItem(x, y);
+ if (item == null) effect = DND.FEEDBACK_NONE;
+ if (currentEffect != effect && currentEffect == DND.FEEDBACK_NONE) {
+ selection = table.getSelection();
+ table.setSelection(new TableItem[0]);
+ }
+ boolean restoreSelection = currentEffect != effect && effect == DND.FEEDBACK_NONE;
+ setDragUnderEffect(effect, item);
+ if (restoreSelection) {
+ table.setSelection(selection);
+ selection = new TableItem[0];
+ }
+}
+private TableItem findItem(int x, int y){
+ if (table == null) return null;
+ Point coordinates = new Point(x, y);
+ coordinates = table.toControl(coordinates);
+ TableItem item = table.getItem(coordinates);
+ if (item != null) return item;
+
+ Rectangle area = table.getClientArea();
+ for (int x1 = area.x; x1 < area.x + area.width; x1++) {
+ coordinates = new Point(x1, y);
+ coordinates = table.toControl(coordinates);
+ item = table.getItem(coordinates);
+ if (item != null) return item;
+ }
+ return null;
+
+}
+private void setDragUnderEffect(int effect, TableItem item) {
+ if (currentItem != item) {
+ if (item == null) {
+ table.setSelection(new TableItem[0]);
+ } else {
+ table.setSelection(new TableItem[] {item});
+ }
+ currentItem = item;
+ }
+ currentEffect = effect;
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TextTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TextTransfer.java
new file mode 100755
index 0000000000..12afd23a9d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TextTransfer.java
@@ -0,0 +1,42 @@
+package org.eclipse.swt.dnd;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class TextTransfer extends ByteArrayTransfer {
+
+ private static TextTransfer _instance = new TextTransfer();
+ private static final String TYPENAME1 = "STRING\0";
+ private static final int TYPEID1 = registerType(TYPENAME1);
+ private static final String TYPENAME2 = "text/plain\0";
+ private static final int TYPEID2 = registerType(TYPENAME2);
+ private static final String TYPENAME3 = "text/text\0";
+ private static final int TYPEID3 = registerType(TYPENAME3);
+
+private TextTransfer() {
+}
+public static TextTransfer getInstance () {
+ return _instance;
+}
+public void javaToNative (Object object, TransferData transferData){
+ if (object == null || !(object instanceof String)) return;
+
+ String text = (String)object;
+ super.javaToNative(text.getBytes(), transferData);
+}
+public Object nativeToJava(TransferData transferData){
+ // get byte array from super
+ byte[] buffer = (byte[])super.nativeToJava(transferData);
+ if (buffer == null) return null;
+ // convert byte array to a string
+ return new String(buffer);
+}
+protected String[] getTypeNames(){
+ return new String[]{TYPENAME1, TYPENAME2, TYPENAME3};
+}
+protected int[] getTypeIds(){
+ return new int[]{TYPEID1, TYPEID2, TYPEID3};
+}
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Transfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Transfer.java
new file mode 100755
index 0000000000..98f63bd8bc
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/Transfer.java
@@ -0,0 +1,26 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.internal.Converter;
+import org.eclipse.swt.internal.motif.OS;
+import org.eclipse.swt.widgets.Display;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public abstract class Transfer {
+abstract public TransferData[] getSupportedTypes();
+abstract public boolean isSupportedType(TransferData transferData);
+abstract protected String[] getTypeNames();
+abstract protected int[] getTypeIds();
+abstract protected void javaToNative (Object object, TransferData transferData);
+abstract protected Object nativeToJava(TransferData transferData);
+public static int registerType(String formatName){
+
+ int xDisplay = Display.getDefault().xDisplay; // using default because we don't have a particular widget
+ byte[] bName = Converter.wcsToMbcs (null, formatName, false);
+ int atom = OS.XmInternAtom (xDisplay, bName, false);
+ return atom;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TransferData.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TransferData.java
new file mode 100755
index 0000000000..a73cc97090
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TransferData.java
@@ -0,0 +1,18 @@
+package org.eclipse.swt.dnd;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+public class TransferData {
+ public int type;
+
+ // attributes specific to set/get
+ int length;
+ int format;
+ int pValue;
+
+ int result;
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TreeDragUnderEffect.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TreeDragUnderEffect.java
new file mode 100755
index 0000000000..e0babbfe6f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/motif/org/eclipse/swt/dnd/TreeDragUnderEffect.java
@@ -0,0 +1,100 @@
+package org.eclipse.swt.dnd;
+
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * (c) Copyright IBM Corp. 1998, 2000 All Rights Reserved
+ */
+
+class TreeDragUnderEffect extends DragUnderEffect {
+
+ private Tree tree;
+ private TreeItem currentItem = null;
+ private int currentEffect = DND.FEEDBACK_NONE;
+ private TreeItem[] selection = new TreeItem[0];
+
+TreeDragUnderEffect(Tree tree) {
+ this.tree = tree;
+}
+void show(int effect, int x, int y) {
+ TreeItem item = null;
+ if (effect != DND.FEEDBACK_NONE) item = findItem(x, y);
+ if (item == null) effect = DND.FEEDBACK_NONE;
+ if (currentEffect != effect && currentEffect == DND.FEEDBACK_NONE) {
+ selection = tree.getSelection();
+ tree.setSelection(new TreeItem[0]);
+ }
+ boolean restoreSelection = currentEffect != effect && effect == DND.FEEDBACK_NONE;
+ setDragUnderEffect(effect, item);
+ if (restoreSelection) {
+ tree.setSelection(selection);
+ selection = new TreeItem[0];
+ }
+}
+private TreeItem findItem(int x , int y){
+ Point coordinates = new Point(x, y);
+ coordinates = tree.toControl(coordinates);
+ TreeItem item = tree.getItem(coordinates);
+ if (item != null) return item;
+
+ Rectangle area = tree.getClientArea();
+ for (int x1 = area.x; x1 < area.x + area.width; x1++) {
+ coordinates = new Point(x1, y);
+ coordinates = tree.toControl(coordinates);
+ item = tree.getItem(coordinates);
+ if (item != null) return item;
+ }
+ return null;
+}
+private void setDragUnderEffect(int effect, TreeItem item) {
+ switch (effect) {
+ case DND.FEEDBACK_SELECT:
+ if (currentEffect == DND.FEEDBACK_INSERT_AFTER ||
+ currentEffect == DND.FEEDBACK_INSERT_BEFORE) {
+ tree.setInsertMark(null, false);
+ currentEffect = DND.FEEDBACK_NONE;
+ currentItem = null;
+ }
+ if (currentEffect != effect || currentItem != item) {
+ setDropSelection(item);
+ currentEffect = DND.FEEDBACK_SELECT;
+ currentItem = item;
+ }
+ break;
+ case DND.FEEDBACK_INSERT_AFTER:
+ case DND.FEEDBACK_INSERT_BEFORE:
+ if (currentEffect == DND.FEEDBACK_SELECT) {
+ setDropSelection(null);
+ currentEffect = DND.FEEDBACK_NONE;
+ currentItem = null;
+ }
+ if (currentEffect != effect || currentItem != item) {
+ tree.setInsertMark(item, effect == DND.FEEDBACK_INSERT_BEFORE);
+ currentEffect = effect;
+ currentItem = item;
+ }
+ break;
+ default :
+ if (currentEffect == DND.FEEDBACK_INSERT_AFTER ||
+ currentEffect == DND.FEEDBACK_INSERT_BEFORE) {
+ tree.setInsertMark(null, false);
+ }
+ if (currentEffect == DND.FEEDBACK_SELECT) {
+ setDropSelection(null);
+ }
+ currentEffect = DND.FEEDBACK_NONE;
+ currentItem = null;
+ break;
+ }
+}
+private void setDropSelection (TreeItem item) {
+ if (item == null) {
+ tree.setSelection(new TreeItem[0]);
+ } else {
+ tree.setSelection(new TreeItem[]{item});
+ }
+}
+
+} \ No newline at end of file