blob: 4bf7a126ff99fba9bfce84624bf40b410eb359a6 [file] [log] [blame]
package org.eclipse.swt.dnd;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.motif.*;
import org.eclipse.swt.widgets.*;
/**
* 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();
/* Use the character encoding for the default locale */
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();
/* Use the character encoding for the default locale */
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;
}
}