]> git.saurik.com Git - wxWidgets.git/blob - src/msw/clipbrd.cpp
fixes to pass tests
[wxWidgets.git] / src / msw / clipbrd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/clipbrd.cpp
3 // Purpose: Clipboard functionality
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_CLIPBOARD
28
29 #include "wx/clipbrd.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/object.h"
33 #include "wx/event.h"
34 #include "wx/app.h"
35 #include "wx/frame.h"
36 #include "wx/bitmap.h"
37 #include "wx/utils.h"
38 #include "wx/intl.h"
39 #include "wx/log.h"
40 #include "wx/dataobj.h"
41 #endif
42
43 #if wxUSE_METAFILE
44 #include "wx/metafile.h"
45 #endif
46
47
48 #include <string.h>
49
50 #include "wx/msw/private.h"
51 #include "wx/msw/ole/oleutils.h"
52
53 #if wxUSE_WXDIB
54 #include "wx/msw/dib.h"
55 #endif
56
57 // wxDataObject is tied to OLE/drag and drop implementation, therefore so are
58 // the functions using wxDataObject in wxClipboard
59 //#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP
60
61 #if wxUSE_OLE && !defined(__WXWINCE__)
62 // use OLE clipboard
63 #define wxUSE_OLE_CLIPBOARD 1
64 #else // !wxUSE_DATAOBJ
65 // use Win clipboard API
66 #define wxUSE_OLE_CLIPBOARD 0
67 #endif
68
69 #if wxUSE_OLE_CLIPBOARD
70 #include <ole2.h>
71 #endif // wxUSE_OLE_CLIPBOARD
72
73 // ===========================================================================
74 // implementation
75 // ===========================================================================
76
77 // ---------------------------------------------------------------------------
78 // old-style clipboard functions using Windows API
79 // ---------------------------------------------------------------------------
80
81 static bool gs_wxClipboardIsOpen = false;
82 static int gs_htmlcfid = 0;
83
84 bool wxOpenClipboard()
85 {
86 wxCHECK_MSG( !gs_wxClipboardIsOpen, true, wxT("clipboard already opened.") );
87
88 wxWindow *win = wxTheApp->GetTopWindow();
89 if ( win )
90 {
91 gs_wxClipboardIsOpen = ::OpenClipboard((HWND)win->GetHWND()) != 0;
92
93 if ( !gs_wxClipboardIsOpen )
94 {
95 wxLogSysError(_("Failed to open the clipboard."));
96 }
97
98 return gs_wxClipboardIsOpen;
99 }
100 else
101 {
102 wxLogDebug(wxT("Cannot open clipboard without a main window."));
103
104 return false;
105 }
106 }
107
108 bool wxCloseClipboard()
109 {
110 wxCHECK_MSG( gs_wxClipboardIsOpen, false, wxT("clipboard is not opened") );
111
112 gs_wxClipboardIsOpen = false;
113
114 if ( ::CloseClipboard() == 0 )
115 {
116 wxLogSysError(_("Failed to close the clipboard."));
117
118 return false;
119 }
120
121 return true;
122 }
123
124 bool wxEmptyClipboard()
125 {
126 if ( ::EmptyClipboard() == 0 )
127 {
128 wxLogSysError(_("Failed to empty the clipboard."));
129
130 return false;
131 }
132
133 return true;
134 }
135
136 bool wxIsClipboardOpened()
137 {
138 return gs_wxClipboardIsOpen;
139 }
140
141 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
142 {
143 wxDataFormat::NativeFormat cf = dataFormat.GetFormatId();
144 if (cf == wxDF_HTML)
145 cf = gs_htmlcfid;
146
147 if ( ::IsClipboardFormatAvailable(cf) )
148 {
149 // ok from the first try
150 return true;
151 }
152
153 // for several standard formats, we can convert from some other ones too
154 switch ( cf )
155 {
156 // for bitmaps, DIBs will also do
157 case CF_BITMAP:
158 return ::IsClipboardFormatAvailable(CF_DIB) != 0;
159
160 #if wxUSE_ENH_METAFILE && !defined(__WXWINCE__)
161 case CF_METAFILEPICT:
162 return ::IsClipboardFormatAvailable(CF_ENHMETAFILE) != 0;
163 #endif // wxUSE_ENH_METAFILE
164
165 default:
166 return false;
167 }
168 }
169
170
171 bool wxSetClipboardData(wxDataFormat dataFormat,
172 const void *data,
173 int width, int height)
174 {
175 HANDLE handle = 0; // return value of SetClipboardData
176
177 switch (dataFormat)
178 {
179 case wxDF_BITMAP:
180 {
181 wxBitmap *bitmap = (wxBitmap *)data;
182
183 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
184 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
185 HBITMAP old = (HBITMAP)
186 ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP());
187 HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
188 bitmap->GetWidth(),
189 bitmap->GetHeight());
190 if (!hBitmap)
191 {
192 SelectObject(hdcSrc, old);
193 DeleteDC(hdcMem);
194 DeleteDC(hdcSrc);
195 return false;
196 }
197
198 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
199 BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(),
200 hdcSrc, 0, 0, SRCCOPY);
201
202 // Select new bitmap out of memory DC
203 SelectObject(hdcMem, old1);
204
205 // Set the data
206 handle = ::SetClipboardData(CF_BITMAP, hBitmap);
207
208 // Clean up
209 SelectObject(hdcSrc, old);
210 DeleteDC(hdcSrc);
211 DeleteDC(hdcMem);
212 break;
213 }
214
215 #if wxUSE_WXDIB
216 case wxDF_DIB:
217 {
218 wxBitmap *bitmap = (wxBitmap *)data;
219
220 if ( bitmap && bitmap->IsOk() )
221 {
222 wxDIB dib(*bitmap);
223 if ( dib.IsOk() )
224 {
225 handle = ::SetClipboardData(CF_DIB, dib.Detach());
226 }
227 }
228 break;
229 }
230 #endif
231
232 // VZ: I'm told that this code works, but it doesn't seem to work for me
233 // and, anyhow, I'd be highly surprised if it did. So I leave it here
234 // but IMNSHO it is completely broken.
235 #if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH) && !defined(__WXWINCE__)
236 case wxDF_METAFILE:
237 {
238 wxMetafile *wxMF = (wxMetafile *)data;
239 HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
240 METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
241
242 mf->mm = wxMF->GetWindowsMappingMode();
243 mf->xExt = width;
244 mf->yExt = height;
245 mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
246 GlobalUnlock(data);
247 wxMF->SetHMETAFILE((WXHANDLE) NULL);
248
249 handle = SetClipboardData(CF_METAFILEPICT, data);
250 break;
251 }
252 #endif // wxUSE_METAFILE
253
254 #if wxUSE_ENH_METAFILE && !defined(__WXWINCE__)
255 case wxDF_ENHMETAFILE:
256 {
257 wxEnhMetaFile *emf = (wxEnhMetaFile *)data;
258 wxEnhMetaFile emfCopy = *emf;
259
260 handle = SetClipboardData(CF_ENHMETAFILE,
261 (void *)emfCopy.GetHENHMETAFILE());
262 }
263 break;
264 #endif // wxUSE_ENH_METAFILE
265
266 case CF_SYLK:
267 case CF_DIF:
268 case CF_TIFF:
269 case CF_PALETTE:
270 default:
271 {
272 wxLogError(_("Unsupported clipboard format."));
273 return false;
274 }
275
276 case wxDF_OEMTEXT:
277 dataFormat = wxDF_TEXT;
278 // fall through
279
280 case wxDF_TEXT:
281 {
282 char *s = (char *)data;
283
284 width = strlen(s) + 1;
285 height = 1;
286 DWORD l = (width * height);
287 HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
288 if ( hGlobalMemory )
289 {
290 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
291
292 memcpy(lpGlobalMemory, s, l);
293
294 GlobalUnlock(hGlobalMemory);
295 }
296
297 handle = SetClipboardData(dataFormat, hGlobalMemory);
298 break;
299 }
300 // Only tested with Visual C++ 6.0 so far
301 #if defined(__VISUALC__)
302 case wxDF_HTML:
303 {
304 char* html = (char *)data;
305
306 // Create temporary buffer for HTML header...
307 char *buf = new char [400 + strlen(html)];
308 if(!buf) return false;
309
310 // Create a template string for the HTML header...
311 strcpy(buf,
312 "Version:0.9\r\n"
313 "StartHTML:00000000\r\n"
314 "EndHTML:00000000\r\n"
315 "StartFragment:00000000\r\n"
316 "EndFragment:00000000\r\n"
317 "<html><body>\r\n"
318 "<!--StartFragment -->\r\n");
319
320 // Append the HTML...
321 strcat(buf, html);
322 strcat(buf, "\r\n");
323 // Finish up the HTML format...
324 strcat(buf,
325 "<!--EndFragment-->\r\n"
326 "</body>\r\n"
327 "</html>");
328
329 // Now go back, calculate all the lengths, and write out the
330 // necessary header information. Note, wsprintf() truncates the
331 // string when you overwrite it so you follow up with code to replace
332 // the 0 appended at the end with a '\r'...
333 char *ptr = strstr(buf, "StartHTML");
334 sprintf(ptr+10, "%08u", (unsigned)(strstr(buf, "<html>") - buf));
335 *(ptr+10+8) = '\r';
336
337 ptr = strstr(buf, "EndHTML");
338 sprintf(ptr+8, "%08u", (unsigned)strlen(buf));
339 *(ptr+8+8) = '\r';
340
341 ptr = strstr(buf, "StartFragment");
342 sprintf(ptr+14, "%08u", (unsigned)(strstr(buf, "<!--StartFrag") - buf));
343 *(ptr+14+8) = '\r';
344
345 ptr = strstr(buf, "EndFragment");
346 sprintf(ptr+12, "%08u", (unsigned)(strstr(buf, "<!--EndFrag") - buf));
347 *(ptr+12+8) = '\r';
348
349 // Now you have everything in place ready to put on the
350 // clipboard.
351
352 // Allocate global memory for transfer...
353 HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, strlen(buf)+4);
354
355 // Put your string in the global memory...
356 ptr = (char *)GlobalLock(hText);
357 strcpy(ptr, buf);
358 GlobalUnlock(hText);
359
360 handle = ::SetClipboardData(gs_htmlcfid, hText);
361
362 // Free memory...
363 GlobalFree(hText);
364
365 // Clean up...
366 delete [] buf;
367 break;
368 }
369 #endif
370 }
371
372 if ( handle == 0 )
373 {
374 wxLogSysError(_("Failed to set clipboard data."));
375
376 return false;
377 }
378
379 return true;
380 }
381
382 void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
383 {
384 void *retval = NULL;
385
386 switch ( dataFormat )
387 {
388 #ifndef __WXWINCE__
389 case wxDF_BITMAP:
390 {
391 BITMAP bm;
392 HBITMAP hBitmap = (HBITMAP) GetClipboardData(CF_BITMAP);
393 if (!hBitmap)
394 break;
395
396 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
397 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
398
399 HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, hBitmap);
400 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
401
402 HBITMAP hNewBitmap = CreateBitmapIndirect(&bm);
403
404 if (!hNewBitmap)
405 {
406 SelectObject(hdcSrc, old);
407 DeleteDC(hdcMem);
408 DeleteDC(hdcSrc);
409 break;
410 }
411
412 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hNewBitmap);
413 BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,
414 hdcSrc, 0, 0, SRCCOPY);
415
416 // Select new bitmap out of memory DC
417 SelectObject(hdcMem, old1);
418
419 // Clean up
420 SelectObject(hdcSrc, old);
421 DeleteDC(hdcSrc);
422 DeleteDC(hdcMem);
423
424 // Create and return a new wxBitmap
425 wxBitmap *wxBM = new wxBitmap;
426 wxBM->SetHBITMAP((WXHBITMAP) hNewBitmap);
427 wxBM->SetWidth(bm.bmWidth);
428 wxBM->SetHeight(bm.bmHeight);
429 wxBM->SetDepth(bm.bmPlanes);
430 retval = wxBM;
431 break;
432 }
433 #endif
434 case wxDF_METAFILE:
435 case CF_SYLK:
436 case CF_DIF:
437 case CF_TIFF:
438 case CF_PALETTE:
439 case wxDF_DIB:
440 wxLogError(_("Unsupported clipboard format."));
441 return NULL;
442
443 case wxDF_OEMTEXT:
444 dataFormat = wxDF_TEXT;
445 // fall through
446
447 case wxDF_TEXT:
448 {
449 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
450 if (!hGlobalMemory)
451 break;
452
453 DWORD hsize = ::GlobalSize(hGlobalMemory);
454 if (len)
455 *len = hsize;
456
457 char *s = new char[hsize];
458 if (!s)
459 break;
460
461 LPSTR lpGlobalMemory = (LPSTR) GlobalLock(hGlobalMemory);
462
463 memcpy(s, lpGlobalMemory, hsize);
464
465 GlobalUnlock(hGlobalMemory);
466
467 retval = s;
468 break;
469 }
470
471 default:
472 {
473 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
474 if ( !hGlobalMemory )
475 break;
476
477 DWORD size = ::GlobalSize(hGlobalMemory);
478 if ( len )
479 *len = size;
480
481 void *buf = malloc(size);
482 if ( !buf )
483 break;
484
485 LPSTR lpGlobalMemory = (LPSTR) GlobalLock(hGlobalMemory);
486
487 memcpy(buf, lpGlobalMemory, size);
488
489 GlobalUnlock(hGlobalMemory);
490
491 retval = buf;
492 break;
493 }
494 }
495
496 if ( !retval )
497 {
498 wxLogSysError(_("Failed to retrieve data from the clipboard."));
499 }
500
501 return retval;
502 }
503
504 wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
505 {
506 return (wxDataFormat::NativeFormat)::EnumClipboardFormats(dataFormat);
507 }
508
509 int wxRegisterClipboardFormat(wxChar *formatName)
510 {
511 return ::RegisterClipboardFormat(formatName);
512 }
513
514 bool wxGetClipboardFormatName(wxDataFormat dataFormat,
515 wxChar *formatName,
516 int maxCount)
517 {
518 return ::GetClipboardFormatName((int)dataFormat, formatName, maxCount) > 0;
519 }
520
521 // ---------------------------------------------------------------------------
522 // wxClipboard
523 // ---------------------------------------------------------------------------
524
525 IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
526
527 wxClipboard::wxClipboard()
528 {
529 #if wxUSE_OLE_CLIPBOARD
530 wxOleInitialize();
531 #endif
532
533 m_lastDataObject = NULL;
534 m_isOpened = false;
535 }
536
537 wxClipboard::~wxClipboard()
538 {
539 if ( m_lastDataObject )
540 {
541 Clear();
542 }
543
544 #if wxUSE_OLE_CLIPBOARD
545 wxOleUninitialize();
546 #endif
547 }
548
549 void wxClipboard::Clear()
550 {
551 if ( IsUsingPrimarySelection() )
552 return;
553
554 #if wxUSE_OLE_CLIPBOARD
555 if (m_lastDataObject)
556 {
557 // don't touch data set by other applications
558 HRESULT hr = OleIsCurrentClipboard(m_lastDataObject);
559 if (S_OK == hr)
560 {
561 hr = OleSetClipboard(NULL);
562 if ( FAILED(hr) )
563 {
564 wxLogApiError(wxT("OleSetClipboard(NULL)"), hr);
565 }
566 }
567 m_lastDataObject = NULL;
568 }
569 #endif // wxUSE_OLE_CLIPBOARD
570 }
571
572 bool wxClipboard::Flush()
573 {
574 #if wxUSE_OLE_CLIPBOARD
575 if (m_lastDataObject)
576 {
577 // don't touch data set by other applications
578 HRESULT hr = OleIsCurrentClipboard(m_lastDataObject);
579 m_lastDataObject = NULL;
580 if (S_OK == hr)
581 {
582 hr = OleFlushClipboard();
583 if ( FAILED(hr) )
584 {
585 wxLogApiError(wxT("OleFlushClipboard"), hr);
586
587 return false;
588 }
589 return true;
590 }
591 }
592 return false;
593 #else // !wxUSE_OLE_CLIPBOARD
594 return false;
595 #endif // wxUSE_OLE_CLIPBOARD/!wxUSE_OLE_CLIPBOARD
596 }
597
598 bool wxClipboard::Open()
599 {
600 // Get clipboard id for HTML format...
601 if(!gs_htmlcfid)
602 gs_htmlcfid = RegisterClipboardFormat(wxT("HTML Format"));
603
604 // OLE opens clipboard for us
605 m_isOpened = true;
606 #if wxUSE_OLE_CLIPBOARD
607 return true;
608 #else
609 return wxOpenClipboard();
610 #endif
611 }
612
613 bool wxClipboard::IsOpened() const
614 {
615 #if wxUSE_OLE_CLIPBOARD
616 return m_isOpened;
617 #else
618 return wxIsClipboardOpened();
619 #endif
620 }
621
622 bool wxClipboard::SetData( wxDataObject *data )
623 {
624 if ( IsUsingPrimarySelection() )
625 return false;
626
627 #if !wxUSE_OLE_CLIPBOARD
628 (void)wxEmptyClipboard();
629 #endif // wxUSE_OLE_CLIPBOARD
630
631 if ( data )
632 return AddData(data);
633 else
634 return true;
635 }
636
637 bool wxClipboard::AddData( wxDataObject *data )
638 {
639 if ( IsUsingPrimarySelection() )
640 return false;
641
642 wxCHECK_MSG( data, false, wxT("data is invalid") );
643
644 #if wxUSE_OLE_CLIPBOARD
645 HRESULT hr = OleSetClipboard(data->GetInterface());
646 if ( FAILED(hr) )
647 {
648 wxLogSysError(hr, _("Failed to put data on the clipboard"));
649
650 // don't free anything in this case
651
652 return false;
653 }
654
655 // we have to call either OleSetClipboard(NULL) or OleFlushClipboard() when
656 // using OLE clipboard when the app terminates - by default, we call
657 // OleSetClipboard(NULL) which won't waste RAM, but the app can call
658 // wxClipboard::Flush() to change this
659 m_lastDataObject = data->GetInterface();
660
661 // we have a problem here because we should delete wxDataObject, but we
662 // can't do it because IDataObject which we just gave to the clipboard
663 // would try to use it when it will need the data. IDataObject is ref
664 // counted and so doesn't suffer from such problem, so we release it now
665 // and tell it to delete wxDataObject when it is deleted itself.
666 data->SetAutoDelete();
667
668 return true;
669 #elif wxUSE_DATAOBJ
670 wxCHECK_MSG( wxIsClipboardOpened(), false, wxT("clipboard not open") );
671
672 wxDataFormat format = data->GetPreferredFormat();
673
674 switch ( format )
675 {
676 case wxDF_TEXT:
677 case wxDF_OEMTEXT:
678 {
679 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
680 wxString str(textDataObject->GetText());
681 return wxSetClipboardData(format, str.c_str());
682 }
683
684 case wxDF_BITMAP:
685 case wxDF_DIB:
686 {
687 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
688 wxBitmap bitmap(bitmapDataObject->GetBitmap());
689 return wxSetClipboardData(data->GetPreferredFormat(), &bitmap);
690 }
691
692 #if wxUSE_METAFILE
693 case wxDF_METAFILE:
694 {
695 #if 1
696 // TODO
697 wxLogError(wxT("Not implemented because wxMetafileDataObject does not contain width and height values."));
698 return false;
699 #else
700 wxMetafileDataObject* metaFileDataObject =
701 (wxMetafileDataObject*) data;
702 wxMetafile metaFile = metaFileDataObject->GetMetafile();
703 return wxSetClipboardData(wxDF_METAFILE, &metaFile,
704 metaFileDataObject->GetWidth(),
705 metaFileDataObject->GetHeight());
706 #endif
707 }
708 #endif // wxUSE_METAFILE
709
710 default:
711 {
712 // This didn't compile, of course
713 // return wxSetClipboardData(data);
714 // TODO
715 wxLogError(wxT("Not implemented."));
716 return false;
717 }
718 }
719 #else // !wxUSE_DATAOBJ
720 return false;
721 #endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
722 }
723
724 void wxClipboard::Close()
725 {
726 m_isOpened = false;
727 // OLE closes clipboard for us
728 #if !wxUSE_OLE_CLIPBOARD
729 wxCloseClipboard();
730 #endif
731 }
732
733 bool wxClipboard::IsSupported( const wxDataFormat& format )
734 {
735 return !IsUsingPrimarySelection() && wxIsClipboardFormatAvailable(format);
736 }
737
738 bool wxClipboard::GetData( wxDataObject& data )
739 {
740 if ( IsUsingPrimarySelection() )
741 return false;
742
743 #if wxUSE_OLE_CLIPBOARD
744 IDataObject *pDataObject = NULL;
745 HRESULT hr = OleGetClipboard(&pDataObject);
746 if ( FAILED(hr) || !pDataObject )
747 {
748 wxLogSysError(hr, _("Failed to get data from the clipboard"));
749
750 return false;
751 }
752
753 // build the list of supported formats
754 size_t nFormats = data.GetFormatCount(wxDataObject::Set);
755 wxDataFormat format;
756 wxDataFormat *formats;
757 if ( nFormats == 1 )
758 {
759 // the most common case
760 formats = &format;
761 }
762 else
763 {
764 // bad luck, need to alloc mem
765 formats = new wxDataFormat[nFormats];
766 }
767
768 data.GetAllFormats(formats, wxDataObject::Set);
769
770 // get the data for the given formats
771 FORMATETC formatEtc;
772 CLIPFORMAT cf;
773 bool result = false;
774
775 // enumerate all explicit formats on the clipboard.
776 // note that this does not include implicit / synthetic (automatically
777 // converted) formats.
778 #if wxDEBUG_LEVEL >= 2
779 // get the format enumerator
780 IEnumFORMATETC *pEnumFormatEtc = NULL;
781 hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormatEtc);
782 if ( FAILED(hr) || !pEnumFormatEtc )
783 {
784 wxLogSysError(hr,
785 _("Failed to retrieve the supported clipboard formats"));
786 }
787 else
788 {
789 // ask for the supported formats and see if there are any we support
790 for ( ;; )
791 {
792 ULONG nCount;
793 hr = pEnumFormatEtc->Next(1, &formatEtc, &nCount);
794
795 // don't use FAILED() because S_FALSE would pass it
796 if ( hr != S_OK )
797 {
798 // no more formats
799 break;
800 }
801
802 cf = formatEtc.cfFormat;
803
804 wxLogTrace(wxTRACE_OleCalls,
805 wxT("Object on the clipboard supports format %s."),
806 wxDataObject::GetFormatName(cf));
807 }
808
809 pEnumFormatEtc->Release();
810 }
811 #endif // wxDEBUG_LEVEL >= 2
812
813 STGMEDIUM medium;
814 // stop at the first valid format found on the clipboard
815 for ( size_t n = 0; !result && (n < nFormats); n++ )
816 {
817 // convert to NativeFormat Id
818 cf = formats[n].GetFormatId();
819
820 if (cf == wxDF_HTML)
821 cf = gs_htmlcfid;
822 // if the format is not available, try the next one
823 // this test includes implicit / sythetic formats
824 if ( !::IsClipboardFormatAvailable(cf) )
825 continue;
826
827 formatEtc.cfFormat = cf;
828 formatEtc.ptd = NULL;
829 formatEtc.dwAspect = DVASPECT_CONTENT;
830 formatEtc.lindex = -1;
831
832 // use the appropriate tymed
833 switch ( formatEtc.cfFormat )
834 {
835 case CF_BITMAP:
836 formatEtc.tymed = TYMED_GDI;
837 break;
838
839 #ifndef __WXWINCE__
840 case CF_METAFILEPICT:
841 formatEtc.tymed = TYMED_MFPICT;
842 break;
843
844 case CF_ENHMETAFILE:
845 formatEtc.tymed = TYMED_ENHMF;
846 break;
847 #endif
848
849 default:
850 formatEtc.tymed = TYMED_HGLOBAL;
851 }
852
853 // try to get data
854 hr = pDataObject->GetData(&formatEtc, &medium);
855 if ( FAILED(hr) )
856 {
857 // try other tymed for GDI objects
858 if ( formatEtc.cfFormat == CF_BITMAP )
859 {
860 formatEtc.tymed = TYMED_HGLOBAL;
861 hr = pDataObject->GetData(&formatEtc, &medium);
862 }
863 }
864
865 if ( SUCCEEDED(hr) )
866 {
867 // pass the data to the data object
868 hr = data.GetInterface()->SetData(&formatEtc, &medium, true);
869 if ( FAILED(hr) )
870 {
871 wxLogDebug(wxT("Failed to set data in wxIDataObject"));
872
873 // IDataObject only takes the ownership of data if it
874 // successfully got it - which is not the case here
875 ReleaseStgMedium(&medium);
876 }
877 else
878 {
879 result = true;
880 }
881 }
882 //else: unsupported tymed?
883 }
884
885 if ( formats != &format )
886 {
887 delete [] formats;
888 }
889 //else: we didn't allocate any memory
890
891 // clean up and return
892 pDataObject->Release();
893
894 return result;
895 #elif wxUSE_DATAOBJ
896 wxCHECK_MSG( wxIsClipboardOpened(), false, wxT("clipboard not open") );
897
898 wxDataFormat format = data.GetPreferredFormat();
899 switch ( format )
900 {
901 case wxDF_TEXT:
902 case wxDF_OEMTEXT:
903 {
904 wxTextDataObject& textDataObject = (wxTextDataObject &)data;
905 char* s = (char*)wxGetClipboardData(format);
906 if ( !s )
907 return false;
908
909 textDataObject.SetText(wxString::FromAscii(s));
910 delete [] s;
911
912 return true;
913 }
914
915 case wxDF_BITMAP:
916 case wxDF_DIB:
917 {
918 wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data;
919 wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(data.GetPreferredFormat());
920 if ( !bitmap )
921 return false;
922
923 bitmapDataObject.SetBitmap(*bitmap);
924 delete bitmap;
925
926 return true;
927 }
928 #if wxUSE_METAFILE
929 case wxDF_METAFILE:
930 {
931 wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
932 wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE);
933 if ( !metaFile )
934 return false;
935
936 metaFileDataObject.SetMetafile(*metaFile);
937 delete metaFile;
938
939 return true;
940 }
941 #endif // wxUSE_METAFILE
942 }
943 return false;
944 #else // !wxUSE_DATAOBJ
945 wxFAIL_MSG( wxT("no clipboard implementation") );
946 return false;
947 #endif // wxUSE_OLE_CLIPBOARD/wxUSE_DATAOBJ
948 }
949
950 #endif // wxUSE_CLIPBOARD