1 11 package org.eclipse.swt.dnd; 12 13 14 import org.eclipse.swt.*; 15 import org.eclipse.swt.widgets.*; 16 import org.eclipse.swt.internal.win32.*; 17 import org.eclipse.swt.internal.ole.win32.*; 18 19 25 public class Clipboard { 26 27 private Display display; 28 29 private COMObject iDataObject; 31 private int refCount; 32 private Transfer[] transferAgents = new Transfer[0]; 33 private Object [] data = new Object [0]; 34 private int CFSTR_PREFERREDDROPEFFECT; 35 36 51 public Clipboard(Display display) { 52 checkSubclass (); 53 if (display == null) { 54 display = Display.getCurrent(); 55 if (display == null) { 56 display = Display.getDefault(); 57 } 58 } 59 if (display.getThread() != Thread.currentThread()) { 60 DND.error(SWT.ERROR_THREAD_INVALID_ACCESS); 61 } 62 this.display = display; 63 TCHAR chFormatName = new TCHAR(0, "Preferred DropEffect", true); CFSTR_PREFERREDDROPEFFECT = OS.RegisterClipboardFormat(chFormatName); 65 createCOMInterfaces(); 66 this.AddRef(); 67 } 68 69 96 protected void checkSubclass () { 97 String name = getClass().getName (); 98 String validName = Clipboard.class.getName(); 99 if (!validName.equals(name)) { 100 DND.error (SWT.ERROR_INVALID_SUBCLASS); 101 } 102 } 103 104 126 protected void checkWidget () { 127 Display display = this.display; 128 if (display == null) DND.error (SWT.ERROR_WIDGET_DISPOSED); 129 if (display.getThread() != Thread.currentThread ()) DND.error (SWT.ERROR_THREAD_INVALID_ACCESS); 130 if (display.isDisposed()) DND.error(SWT.ERROR_WIDGET_DISPOSED); 131 } 132 133 147 public void clearContents() { 148 clearContents(DND.CLIPBOARD); 149 } 150 151 177 public void clearContents(int clipboards) { 178 checkWidget(); 179 if ((clipboards & DND.CLIPBOARD) != 0) { 180 184 if (COM.OleIsCurrentClipboard(this.iDataObject.getAddress()) == COM.S_OK) { 185 189 COM.OleSetClipboard(0); 190 } 191 } 192 } 193 194 206 public void dispose () { 207 if (isDisposed()) return; 208 if (display.getThread() != Thread.currentThread()) DND.error(SWT.ERROR_THREAD_INVALID_ACCESS); 209 213 if (COM.OleIsCurrentClipboard(this.iDataObject.getAddress()) == COM.S_OK) { 214 COM.OleFlushClipboard(); 215 } 216 this.Release(); 217 display = null; 218 } 219 220 252 public Object getContents(Transfer transfer) { 253 return getContents(transfer, DND.CLIPBOARD); 254 } 255 298 public Object getContents(Transfer transfer, int clipboards) { 299 checkWidget(); 300 if (transfer == null) DND.error(SWT.ERROR_NULL_ARGUMENT); 301 if ((clipboards & DND.CLIPBOARD) == 0) return null; 302 312 int[] ppv = new int[1]; 313 int retryCount = 0; 314 317 int result = COM.OleGetClipboard(ppv); 318 while (result != COM.S_OK && retryCount++ < 10) { 319 try {Thread.sleep(50);} catch (Throwable t) {} 320 MSG msg = new MSG(); 321 OS.PeekMessage(msg, 0, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD); 322 result = COM.OleGetClipboard(ppv); 323 } 324 if (result != COM.S_OK) return null; 325 IDataObject dataObject = new IDataObject(ppv[0]); 326 try { 327 TransferData[] allowed = transfer.getSupportedTypes(); 328 for (int i = 0; i < allowed.length; i++) { 329 if (dataObject.QueryGetData(allowed[i].formatetc) == COM.S_OK) { 330 TransferData data = allowed[i]; 331 data.pIDataObject = ppv[0]; 332 return transfer.nativeToJava(data); 333 } 334 } 335 } finally { 336 dataObject.Release(); 337 } 338 return null; } 340 353 public boolean isDisposed () { 354 return (display == null); 355 } 356 357 404 public void setContents(Object [] data, Transfer[] dataTypes) { 405 setContents(data, dataTypes, DND.CLIPBOARD); 406 } 407 408 467 public void setContents(Object [] data, Transfer[] dataTypes, int clipboards) { 468 checkWidget(); 469 if (data == null || dataTypes == null || data.length != dataTypes.length || data.length == 0) { 470 DND.error(SWT.ERROR_INVALID_ARGUMENT); 471 } 472 for (int i = 0; i < data.length; i++) { 473 if (data[i] == null || dataTypes[i] == null || !dataTypes[i].validate(data[i])) { 474 DND.error(SWT.ERROR_INVALID_ARGUMENT); 475 } 476 } 477 if ((clipboards & DND.CLIPBOARD) == 0) return; 478 this.data = data; 479 this.transferAgents = dataTypes; 480 484 int result = COM.OleSetClipboard(iDataObject.getAddress()); 485 486 496 int retryCount = 0; 497 while (result != COM.S_OK && retryCount++ < 10) { 498 try {Thread.sleep(50);} catch (Throwable t) {} 499 MSG msg = new MSG(); 500 OS.PeekMessage(msg, 0, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD); 501 result = COM.OleSetClipboard(iDataObject.getAddress()); 502 } 503 if (result != COM.S_OK) { 504 DND.error(DND.ERROR_CANNOT_SET_CLIPBOARD); 505 } 506 } 507 private int AddRef() { 508 refCount++; 509 return refCount; 510 } 511 private void createCOMInterfaces() { 512 iDataObject = new COMObject(new int[]{2, 0, 0, 2, 2, 1, 2, 3, 2, 4, 1, 1}){ 514 public int method0(int[] args) {return QueryInterface(args[0], args[1]);} 515 public int method1(int[] args) {return AddRef();} 516 public int method2(int[] args) {return Release();} 517 public int method3(int[] args) {return GetData(args[0], args[1]);} 518 public int method5(int[] args) {return QueryGetData(args[0]);} 520 public int method8(int[] args) {return EnumFormatEtc(args[0], args[1]);} 523 }; 527 } 528 private void disposeCOMInterfaces() { 529 if (iDataObject != null) 530 iDataObject.dispose(); 531 iDataObject = null; 532 } 533 538 private int EnumFormatEtc(int dwDirection, int ppenumFormatetc) { 539 if (dwDirection == COM.DATADIR_SET) return COM.E_NOTIMPL; 541 TransferData[] allowedDataTypes = new TransferData[0]; 543 for (int i = 0; i < transferAgents.length; i++){ 544 TransferData[] formats = transferAgents[i].getSupportedTypes(); 545 TransferData[] newAllowedDataTypes = new TransferData[allowedDataTypes.length + formats.length]; 546 System.arraycopy(allowedDataTypes, 0, newAllowedDataTypes, 0, allowedDataTypes.length); 547 System.arraycopy(formats, 0, newAllowedDataTypes, allowedDataTypes.length, formats.length); 548 allowedDataTypes = newAllowedDataTypes; 549 } 550 OleEnumFORMATETC enumFORMATETC = new OleEnumFORMATETC(); 551 enumFORMATETC.AddRef(); 552 FORMATETC[] formats = new FORMATETC[allowedDataTypes.length + 1]; 553 for (int i = 0; i < allowedDataTypes.length; i++){ 554 formats[i] = allowedDataTypes[i].formatetc; 555 } 556 FORMATETC dropeffect = new FORMATETC(); 558 dropeffect.cfFormat = CFSTR_PREFERREDDROPEFFECT; 559 dropeffect.dwAspect = COM.DVASPECT_CONTENT; 560 dropeffect.lindex = -1; 561 dropeffect.tymed = COM.TYMED_HGLOBAL; 562 formats[formats.length -1] = dropeffect; 563 enumFORMATETC.setFormats(formats); 564 OS.MoveMemory(ppenumFormatetc, new int[] {enumFORMATETC.getAddress()}, 4); 565 return COM.S_OK; 566 } 567 private int GetData(int pFormatetc, int pmedium) { 568 573 if (pFormatetc == 0 || pmedium == 0) return COM.E_INVALIDARG; 574 if (QueryGetData(pFormatetc) != COM.S_OK) return COM.DV_E_FORMATETC; 575 576 TransferData transferData = new TransferData(); 577 transferData.formatetc = new FORMATETC(); 578 COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof); 579 transferData.type = transferData.formatetc.cfFormat; 580 transferData.stgmedium = new STGMEDIUM(); 581 transferData.result = COM.E_FAIL; 582 583 if (transferData.type == CFSTR_PREFERREDDROPEFFECT) { 584 STGMEDIUM stgmedium = new STGMEDIUM(); 586 stgmedium.tymed = COM.TYMED_HGLOBAL; 587 stgmedium.unionField = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, 4); 588 OS.MoveMemory(stgmedium.unionField, new int[] {COM.DROPEFFECT_COPY}, 4); 589 stgmedium.pUnkForRelease = 0; 590 COM.MoveMemory(pmedium, stgmedium, STGMEDIUM.sizeof); 591 return COM.S_OK; 592 } 593 594 int transferIndex = -1; 596 for (int i = 0; i < transferAgents.length; i++){ 597 if (transferAgents[i].isSupportedType(transferData)){ 598 transferIndex = i; 599 break; 600 } 601 } 602 if (transferIndex == -1) return COM.DV_E_FORMATETC; 603 transferAgents[transferIndex].javaToNative(data[transferIndex], transferData); 604 COM.MoveMemory(pmedium, transferData.stgmedium, STGMEDIUM.sizeof); 605 return transferData.result; 606 } 607 608 private int QueryGetData(int pFormatetc) { 609 if (transferAgents == null) return COM.E_FAIL; 610 TransferData transferData = new TransferData(); 611 transferData.formatetc = new FORMATETC(); 612 COM.MoveMemory(transferData.formatetc, pFormatetc, FORMATETC.sizeof); 613 transferData.type = transferData.formatetc.cfFormat; 614 if (transferData.type == CFSTR_PREFERREDDROPEFFECT) return COM.S_OK; 615 for (int i = 0; i < transferAgents.length; i++){ 617 if (transferAgents[i].isSupportedType(transferData)) 618 return COM.S_OK; 619 } 620 621 return COM.DV_E_FORMATETC; 622 } 623 627 private int QueryInterface(int riid, int ppvObject) { 628 if (riid == 0 || ppvObject == 0) return COM.E_INVALIDARG; 629 GUID guid = new GUID(); 630 COM.MoveMemory(guid, riid, GUID.sizeof); 631 if (COM.IsEqualGUID(guid, COM.IIDIUnknown) || COM.IsEqualGUID(guid, COM.IIDIDataObject) ) { 632 OS.MoveMemory(ppvObject, new int[] {iDataObject.getAddress()}, 4); 633 AddRef(); 634 return COM.S_OK; 635 } 636 OS.MoveMemory(ppvObject, new int[] {0}, 4); 637 return COM.E_NOINTERFACE; 638 } 639 private int Release() { 640 refCount--; 641 if (refCount == 0) { 642 this.data = new Object [0]; 643 this.transferAgents = new Transfer[0]; 644 disposeCOMInterfaces(); 645 COM.CoFreeUnusedLibraries(); 646 } 647 return refCount; 648 } 649 650 665 public TransferData[] getAvailableTypes() { 666 return getAvailableTypes(DND.CLIPBOARD); 667 } 668 669 692 public TransferData[] getAvailableTypes(int clipboards) { 693 checkWidget(); 694 if ((clipboards & DND.CLIPBOARD) == 0) return new TransferData[0]; 695 FORMATETC[] types = _getAvailableTypes(); 696 TransferData[] data = new TransferData[types.length]; 697 for (int i = 0; i < types.length; i++) { 698 data[i] = new TransferData(); 699 data[i].type = types[i].cfFormat; 700 data[i].formatetc = types[i]; 701 } 702 return data; 703 } 704 705 721 public String [] getAvailableTypeNames() { 722 checkWidget(); 723 FORMATETC[] types = _getAvailableTypes(); 724 String [] names = new String [types.length]; 725 int maxSize = 128; 726 for (int i = 0; i < types.length; i++){ 727 TCHAR buffer = new TCHAR(0, maxSize); 728 int size = OS.GetClipboardFormatName(types[i].cfFormat, buffer, maxSize); 729 if (size != 0) { 730 names[i] = buffer.toString(0, size); 731 } else { 732 switch (types[i].cfFormat) { 733 case COM.CF_HDROP: names[i] = "CF_HDROP"; break; case COM.CF_TEXT: names[i] = "CF_TEXT"; break; case COM.CF_BITMAP: names[i] = "CF_BITMAP"; break; case COM.CF_METAFILEPICT: names[i] = "CF_METAFILEPICT"; break; case COM.CF_SYLK: names[i] = "CF_SYLK"; break; case COM.CF_DIF: names[i] = "CF_DIF"; break; case COM.CF_TIFF: names[i] = "CF_TIFF"; break; case COM.CF_OEMTEXT: names[i] = "CF_OEMTEXT"; break; case COM.CF_DIB: names[i] = "CF_DIB"; break; case COM.CF_PALETTE: names[i] = "CF_PALETTE"; break; case COM.CF_PENDATA: names[i] = "CF_PENDATA"; break; case COM.CF_RIFF: names[i] = "CF_RIFF"; break; case COM.CF_WAVE: names[i] = "CF_WAVE"; break; case COM.CF_UNICODETEXT: names[i] = "CF_UNICODETEXT"; break; case COM.CF_ENHMETAFILE: names[i] = "CF_ENHMETAFILE"; break; case COM.CF_LOCALE: names[i] = "CF_LOCALE"; break; case COM.CF_MAX: names[i] = "CF_MAX"; break; default: names[i] = "UNKNOWN"; } 752 } 753 } 754 return names; 755 } 756 757 private FORMATETC[] _getAvailableTypes() { 758 FORMATETC[] types = new FORMATETC[0]; 759 int[] ppv = new int[1]; 760 763 if (COM.OleGetClipboard(ppv) != COM.S_OK) return types; 764 IDataObject dataObject = new IDataObject(ppv[0]); 765 int[] ppFormatetc = new int[1]; 766 769 int rc = dataObject.EnumFormatEtc(COM.DATADIR_GET, ppFormatetc); 770 dataObject.Release(); 771 if (rc != COM.S_OK)return types; 772 IEnumFORMATETC enumFormatetc = new IEnumFORMATETC(ppFormatetc[0]); 773 int rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof); 775 int[] pceltFetched = new int[1]; 776 enumFormatetc.Reset(); 777 while (enumFormatetc.Next(1, rgelt, pceltFetched) == COM.S_OK && pceltFetched[0] == 1) { 778 FORMATETC formatetc = new FORMATETC(); 779 COM.MoveMemory(formatetc, rgelt, FORMATETC.sizeof); 780 FORMATETC[] newTypes = new FORMATETC[types.length + 1]; 781 System.arraycopy(types, 0, newTypes, 0, types.length); 782 newTypes[types.length] = formatetc; 783 types = newTypes; 784 } 785 OS.GlobalFree(rgelt); 786 enumFormatetc.Release(); 787 return types; 788 } 789 } 790 | Popular Tags |