]> git.saurik.com Git - wxWidgets.git/blame - src/msw/clipbrd.cpp
moved SEH stuff to crashrpt.cpp
[wxWidgets.git] / src / msw / clipbrd.cpp
CommitLineData
2bda0e17
KB
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$
6c9a19aa
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
26f86486
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
26f86486 21 #pragma implementation "clipbrd.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
26f86486 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
26f86486 32 #include "wx/setup.h"
2bda0e17
KB
33#endif
34
47d67540 35#if wxUSE_CLIPBOARD
2bda0e17
KB
36
37#ifndef WX_PRECOMP
26f86486
VZ
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"
0c589ad0 44 #include "wx/intl.h"
2bda0e17
KB
45#endif
46
06e43511 47#if wxUSE_METAFILE
26f86486 48 #include "wx/metafile.h"
06e43511
JS
49#endif
50
dbda9e86 51#include "wx/log.h"
2bda0e17 52#include "wx/clipbrd.h"
06e43511 53
3f480da3 54#include <string.h>
06e43511
JS
55#include <windows.h>
56
2bda0e17 57#include "wx/msw/private.h"
8cb172b4 58
4676948b 59#if wxUSE_WXDIB
2bda0e17 60#include "wx/msw/dib.h"
8cb172b4 61#endif
2bda0e17 62
d59ceba5
VZ
63// wxDataObject is tied to OLE/drag and drop implementation, therefore so are
64// the functions using wxDataObject in wxClipboard
1e6feb95 65//#define wxUSE_DATAOBJ wxUSE_DRAG_AND_DROP
d59ceba5
VZ
66
67#if wxUSE_DATAOBJ
26f86486 68 #include "wx/dataobj.h"
bd52bee1 69#endif
3f480da3 70
f07dc2e2 71#if wxUSE_OLE && !defined(__WXWINCE__)
b94e73ae
VZ
72 // use OLE clipboard
73 #define wxUSE_OLE_CLIPBOARD 1
d59ceba5
VZ
74#else // !wxUSE_DATAOBJ
75 // use Win clipboard API
76 #define wxUSE_OLE_CLIPBOARD 0
2bda0e17
KB
77#endif
78
d59ceba5
VZ
79#if wxUSE_OLE_CLIPBOARD
80 #include <ole2.h>
81#endif // wxUSE_OLE_CLIPBOARD
82
26f86486
VZ
83// ===========================================================================
84// implementation
85// ===========================================================================
86
87// ---------------------------------------------------------------------------
88// old-style clipboard functions using Windows API
89// ---------------------------------------------------------------------------
2bda0e17 90
26f86486
VZ
91static bool gs_wxClipboardIsOpen = FALSE;
92
93bool wxOpenClipboard()
2bda0e17 94{
223d09f6 95 wxCHECK_MSG( !gs_wxClipboardIsOpen, TRUE, wxT("clipboard already opened.") );
26f86486
VZ
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 {
223d09f6 109 wxLogDebug(wxT("Can not open clipboard without a main window."));
26f86486
VZ
110
111 return FALSE;
112 }
2bda0e17
KB
113}
114
26f86486 115bool wxCloseClipboard()
2bda0e17 116{
223d09f6 117 wxCHECK_MSG( gs_wxClipboardIsOpen, FALSE, wxT("clipboard is not opened") );
26f86486
VZ
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;
2bda0e17
KB
129}
130
26f86486 131bool wxEmptyClipboard()
2bda0e17 132{
26f86486
VZ
133 if ( ::EmptyClipboard() == 0 )
134 {
135 wxLogSysError(_("Failed to empty the clipboard."));
136
137 return FALSE;
138 }
139
140 return TRUE;
2bda0e17
KB
141}
142
26f86486 143bool wxIsClipboardOpened()
2bda0e17 144{
26f86486 145 return gs_wxClipboardIsOpen;
2bda0e17
KB
146}
147
06e43511 148bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
2bda0e17 149{
d9317fd4
VZ
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
4676948b 163#if wxUSE_ENH_METAFILE && !defined(__WIN16__) && !defined(__WXWINCE__)
d9317fd4
VZ
164 case CF_METAFILEPICT:
165 return ::IsClipboardFormatAvailable(CF_ENHMETAFILE) != 0;
166#endif // wxUSE_ENH_METAFILE
167
168 default:
169 return FALSE;
170 }
2bda0e17
KB
171}
172
e9196d9c 173
26f86486
VZ
174bool wxSetClipboardData(wxDataFormat dataFormat,
175 const void *data,
176 int width, int height)
2bda0e17 177{
26f86486
VZ
178 HANDLE handle = 0; // return value of SetClipboardData
179
180 switch (dataFormat)
2bda0e17 181 {
26f86486
VZ
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
4676948b 218#if wxUSE_WXDIB
26f86486
VZ
219 case wxDF_DIB:
220 {
26f86486 221 wxBitmap *bitmap = (wxBitmap *)data;
2b254edf
VZ
222
223 HGLOBAL hDIB = wxDIB::ConvertFromBitmap(GetHbitmapOf(*bitmap));
224 if ( hDIB )
225 {
226 handle = ::SetClipboardData(CF_DIB, hDIB);
227 }
26f86486
VZ
228 break;
229 }
4676948b 230#endif
26f86486 231
d9317fd4 232 // VZ: I'm told that this code works, but it doesn't seem to work for me
4676948b 233 // and, anyhow, I'd be highly surprised if it did. So I leave it here
d9317fd4 234 // but IMNSHO it is completely broken.
4676948b 235#if wxUSE_METAFILE && !defined(wxMETAFILE_IS_ENH) && !defined(__WXWINCE__)
26f86486
VZ
236 case wxDF_METAFILE:
237 {
238 wxMetafile *wxMF = (wxMetafile *)data;
239 HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
26f86486 240 METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
2bda0e17 241
26f86486
VZ
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);
2bda0e17 248
26f86486
VZ
249 handle = SetClipboardData(CF_METAFILEPICT, data);
250 break;
251 }
d9317fd4
VZ
252#endif // wxUSE_METAFILE
253
4676948b 254#if wxUSE_ENH_METAFILE && !defined(__WIN16__) && !defined(__WXWINCE__)
d9317fd4
VZ
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
26f86486
VZ
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 }
2bda0e17 275
26f86486
VZ
276 case wxDF_OEMTEXT:
277 dataFormat = wxDF_TEXT;
278 // fall through
2bda0e17 279
26f86486
VZ
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 {
26f86486 290 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
2bda0e17 291
26f86486 292 memcpy(lpGlobalMemory, s, l);
2bda0e17 293
26f86486
VZ
294 GlobalUnlock(hGlobalMemory);
295 }
2bda0e17 296
26f86486
VZ
297 handle = SetClipboardData(dataFormat, hGlobalMemory);
298 break;
299 }
387ebd3e
JS
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
2bda0e17 374 }
26f86486
VZ
375
376 if ( handle == 0 )
2bda0e17 377 {
26f86486
VZ
378 wxLogSysError(_("Failed to set clipboard data."));
379
380 return FALSE;
2bda0e17 381 }
26f86486
VZ
382
383 return TRUE;
384}
385
386void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
387{
388 void *retval = NULL;
389
390 switch ( dataFormat )
2bda0e17 391 {
4676948b 392#ifndef __WXWINCE__
26f86486
VZ
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);
6d167489 434#if WXWIN_COMPATIBILITY_2
26f86486 435 wxBM->SetOk(TRUE);
6d167489 436#endif // WXWIN_COMPATIBILITY_2
26f86486
VZ
437 retval = wxBM;
438 break;
439 }
4676948b 440#endif
26f86486
VZ
441 case wxDF_METAFILE:
442 case CF_SYLK:
443 case CF_DIF:
444 case CF_TIFF:
445 case CF_PALETTE:
446 case wxDF_DIB:
f7f50f49
VZ
447 wxLogError(_("Unsupported clipboard format."));
448 return NULL;
26f86486
VZ
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;
2bda0e17 459
26f86486
VZ
460 DWORD hsize = ::GlobalSize(hGlobalMemory);
461 if (len)
462 *len = hsize;
2bda0e17 463
26f86486
VZ
464 char *s = new char[hsize];
465 if (!s)
466 break;
2bda0e17 467
4676948b 468 LPSTR lpGlobalMemory = (LPSTR) GlobalLock(hGlobalMemory);
2bda0e17 469
26f86486 470 memcpy(s, lpGlobalMemory, hsize);
2bda0e17 471
4676948b 472 GlobalUnlock(hGlobalMemory);
26f86486
VZ
473
474 retval = s;
475 break;
476 }
3f480da3
VZ
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
4676948b 492 LPSTR lpGlobalMemory = (LPSTR) GlobalLock(hGlobalMemory);
3f480da3
VZ
493
494 memcpy(buf, lpGlobalMemory, size);
495
4676948b 496 GlobalUnlock(hGlobalMemory);
3f480da3
VZ
497
498 retval = buf;
499 break;
500 }
26f86486 501 }
2bda0e17 502
26f86486
VZ
503 if ( !retval )
504 {
505 wxLogSysError(_("Failed to retrieve data from the clipboard."));
2bda0e17 506 }
26f86486
VZ
507
508 return retval;
2bda0e17
KB
509}
510
3f480da3 511wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
2bda0e17 512{
33ac7e6f 513 return (wxDataFormat::NativeFormat)::EnumClipboardFormats(dataFormat);
2bda0e17
KB
514}
515
837e5743 516int wxRegisterClipboardFormat(wxChar *formatName)
2bda0e17
KB
517{
518 return ::RegisterClipboardFormat(formatName);
519}
520
26f86486 521bool wxGetClipboardFormatName(wxDataFormat dataFormat,
837e5743 522 wxChar *formatName,
26f86486 523 int maxCount)
2bda0e17 524{
26f86486 525 return ::GetClipboardFormatName((int)dataFormat, formatName, maxCount) > 0;
2bda0e17
KB
526}
527
26f86486 528// ---------------------------------------------------------------------------
06e43511 529// wxClipboard
26f86486 530// ---------------------------------------------------------------------------
2bda0e17 531
26f86486 532IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
2bda0e17
KB
533
534wxClipboard::wxClipboard()
535{
d59ceba5 536 m_clearOnExit = FALSE;
a36d790a 537 m_isOpened = FALSE;
2bda0e17
KB
538}
539
540wxClipboard::~wxClipboard()
541{
d59ceba5
VZ
542 if ( m_clearOnExit )
543 {
544 Clear();
545 }
2bda0e17
KB
546}
547
06e43511 548void wxClipboard::Clear()
2bda0e17 549{
d59ceba5
VZ
550#if wxUSE_OLE_CLIPBOARD
551 if ( FAILED(OleSetClipboard(NULL)) )
552 {
f6bcfd97 553 wxLogLastError(wxT("OleSetClipboard(NULL)"));
d59ceba5
VZ
554 }
555#endif
556}
557
558bool wxClipboard::Flush()
559{
7ffdaf81 560#if wxUSE_OLE_CLIPBOARD
d59ceba5
VZ
561 if ( FAILED(OleFlushClipboard()) )
562 {
f6bcfd97 563 wxLogLastError(wxT("OleFlushClipboard"));
d59ceba5
VZ
564
565 return FALSE;
566 }
567 else
568 {
569 m_clearOnExit = FALSE;
570
571 return TRUE;
572 }
7ffdaf81
VZ
573#else // !wxUSE_OLE_CLIPBOARD
574 return FALSE;
575#endif // wxUSE_OLE_CLIPBOARD/!wxUSE_OLE_CLIPBOARD
2bda0e17
KB
576}
577
06e43511 578bool wxClipboard::Open()
2bda0e17 579{
d59ceba5 580 // OLE opens clipboard for us
a36d790a 581 m_isOpened = TRUE;
d59ceba5
VZ
582#if wxUSE_OLE_CLIPBOARD
583 return TRUE;
584#else
06e43511 585 return wxOpenClipboard();
d59ceba5 586#endif
2bda0e17
KB
587}
588
f536e0f2
VZ
589bool wxClipboard::IsOpened() const
590{
591#if wxUSE_OLE_CLIPBOARD
a36d790a 592 return m_isOpened;
f536e0f2
VZ
593#else
594 return wxIsClipboardOpened();
595#endif
596}
597
06e43511 598bool wxClipboard::SetData( wxDataObject *data )
2bda0e17 599{
51edda6a 600#if !wxUSE_OLE_CLIPBOARD
26f86486 601 (void)wxEmptyClipboard();
51edda6a 602#endif // wxUSE_OLE_CLIPBOARD
26f86486
VZ
603
604 if ( data )
605 return AddData(data);
606 else
607 return TRUE;
608}
609
610bool wxClipboard::AddData( wxDataObject *data )
611{
223d09f6 612 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
06e43511 613
d59ceba5
VZ
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
223d09f6 640 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
26f86486 641
7fc0bd1c 642 wxDataFormat format = data->GetPreferredFormat();
26f86486
VZ
643
644 switch ( format )
06e43511
JS
645 {
646 case wxDF_TEXT:
647 case wxDF_OEMTEXT:
648 {
649 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
650 wxString str(textDataObject->GetText());
26f86486 651 return wxSetClipboardData(format, str.c_str());
06e43511 652 }
26f86486 653
06e43511
JS
654 case wxDF_BITMAP:
655 case wxDF_DIB:
656 {
657 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
658 wxBitmap bitmap(bitmapDataObject->GetBitmap());
7fc0bd1c 659 return wxSetClipboardData(data->GetPreferredFormat(), &bitmap);
06e43511 660 }
26f86486 661
06e43511
JS
662#if wxUSE_METAFILE
663 case wxDF_METAFILE:
664 {
7fc0bd1c
JS
665#if 1
666 // TODO
667 wxLogError("Not implemented because wxMetafileDataObject does not contain width and height values.");
668 return FALSE;
669#else
33ac7e6f 670 wxMetafileDataObject* metaFileDataObject =
26f86486 671 (wxMetafileDataObject*) data;
06e43511 672 wxMetafile metaFile = metaFileDataObject->GetMetafile();
26f86486
VZ
673 return wxSetClipboardData(wxDF_METAFILE, &metaFile,
674 metaFileDataObject->GetWidth(),
675 metaFileDataObject->GetHeight());
7fc0bd1c 676#endif
06e43511 677 }
26f86486
VZ
678#endif // wxUSE_METAFILE
679
06e43511 680 default:
7fc0bd1c
JS
681 {
682// This didn't compile, of course
683// return wxSetClipboardData(data);
684 // TODO
f07dc2e2 685 wxLogError(wxT("Not implemented."));
7fc0bd1c
JS
686 return FALSE;
687 }
06e43511 688 }
d59ceba5 689#else // !wxUSE_DATAOBJ
06e43511 690 return FALSE;
d59ceba5 691#endif // wxUSE_DATAOBJ/!wxUSE_DATAOBJ
2bda0e17
KB
692}
693
06e43511 694void wxClipboard::Close()
2bda0e17 695{
a36d790a 696 m_isOpened = FALSE;
d59ceba5
VZ
697 // OLE closes clipboard for us
698#if !wxUSE_OLE_CLIPBOARD
06e43511 699 wxCloseClipboard();
d59ceba5 700#endif
2bda0e17
KB
701}
702
26f86486 703bool wxClipboard::IsSupported( wxDataFormat format )
2bda0e17 704{
06e43511 705 return wxIsClipboardFormatAvailable(format);
2bda0e17
KB
706}
707
1e8335b0 708bool wxClipboard::GetData( wxDataObject& data )
2bda0e17 709{
d59ceba5
VZ
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
1e8335b0 721 size_t nFormats = data.GetFormatCount(wxDataObject::Set);
33ac7e6f 722 wxDataFormat format;
c5639a87 723 wxDataFormat *formats;
d59ceba5
VZ
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
1e8335b0 735 data.GetAllFormats(formats, wxDataObject::Set);
d59ceba5
VZ
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;
d59ceba5
VZ
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
265b0c07
VZ
806 // use the appropriate tymed
807 switch ( formatEtc.cfFormat )
808 {
809 case CF_BITMAP:
810 formatEtc.tymed = TYMED_GDI;
811 break;
4676948b 812#ifndef __WXWINCE__
265b0c07
VZ
813 case CF_METAFILEPICT:
814 formatEtc.tymed = TYMED_MFPICT;
815 break;
816
d9317fd4
VZ
817 case CF_ENHMETAFILE:
818 formatEtc.tymed = TYMED_ENHMF;
819 break;
4676948b 820#endif
265b0c07
VZ
821 default:
822 formatEtc.tymed = TYMED_HGLOBAL;
823 }
824
d59ceba5
VZ
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
1e8335b0 840 hr = data.GetInterface()->SetData(&formatEtc, &medium, TRUE);
d59ceba5
VZ
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
223d09f6 864 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
26f86486 865
7fc0bd1c 866 wxDataFormat format = data.GetPreferredFormat();
26f86486 867 switch ( format )
06e43511
JS
868 {
869 case wxDF_TEXT:
870 case wxDF_OEMTEXT:
871 {
1e8335b0
VZ
872 wxTextDataObject& textDataObject = (wxTextDataObject &)data;
873 char* s = (char*)wxGetClipboardData(format);
874 if ( !s )
06e43511 875 return FALSE;
1e8335b0 876
f07dc2e2 877 textDataObject.SetText(wxString::FromAscii(s));
1e8335b0
VZ
878 delete [] s;
879
880 return TRUE;
06e43511 881 }
26f86486 882
06e43511
JS
883 case wxDF_BITMAP:
884 case wxDF_DIB:
885 {
1e8335b0 886 wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data;
7fc0bd1c 887 wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(data.GetPreferredFormat());
1e8335b0 888 if ( !bitmap )
06e43511 889 return FALSE;
1e8335b0
VZ
890
891 bitmapDataObject.SetBitmap(*bitmap);
892 delete bitmap;
893
894 return TRUE;
06e43511
JS
895 }
896#if wxUSE_METAFILE
897 case wxDF_METAFILE:
898 {
1e8335b0 899 wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
26f86486 900 wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE);
1e8335b0 901 if ( !metaFile )
06e43511 902 return FALSE;
3f480da3 903
1e8335b0
VZ
904 metaFileDataObject.SetMetafile(*metaFile);
905 delete metaFile;
26f86486 906
1e8335b0
VZ
907 return TRUE;
908 }
909#endif // wxUSE_METAFILE
06e43511 910 }
3897b707 911 return FALSE;
d59ceba5 912#else // !wxUSE_DATAOBJ
1e8335b0 913 wxFAIL_MSG( wxT("no clipboard implementation") );
06e43511 914 return FALSE;
3897b707 915#endif // wxUSE_OLE_CLIPBOARD/wxUSE_DATAOBJ
2bda0e17
KB
916}
917
47d67540 918#endif // wxUSE_CLIPBOARD
4ce81a75 919