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