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