]> git.saurik.com Git - wxWidgets.git/blame - src/msw/clipbrd.cpp
more new files
[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$
8// Copyright: (c) Julian Smart and Markus Holzem
26f86486 9// Licence: wxWindows license
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"
2bda0e17
KB
44#endif
45
06e43511 46#if wxUSE_METAFILE
26f86486 47 #include "wx/metafile.h"
06e43511
JS
48#endif
49
dbda9e86 50#include "wx/log.h"
2bda0e17 51#include "wx/clipbrd.h"
06e43511 52
3f480da3 53#include <string.h>
06e43511
JS
54#include <windows.h>
55
2bda0e17
KB
56#include "wx/msw/private.h"
57#include "wx/msw/dib.h"
58
06e43511
JS
59// wxDataObject is tied to OLE/drag and drop implementation,
60// therefore so is wxClipboard :-(
61#if wxUSE_DRAG_AND_DROP
26f86486 62 #include "wx/dataobj.h"
3f480da3
VZ
63
64 static bool wxSetClipboardData(wxDataObject *data);
2bda0e17
KB
65#endif
66
3f480da3
VZ
67#ifdef __WIN16__
68 #define memcpy hmemcpy
69#endif
06e43511 70
26f86486
VZ
71// ===========================================================================
72// implementation
73// ===========================================================================
74
75// ---------------------------------------------------------------------------
76// old-style clipboard functions using Windows API
77// ---------------------------------------------------------------------------
2bda0e17 78
26f86486
VZ
79static bool gs_wxClipboardIsOpen = FALSE;
80
81bool wxOpenClipboard()
2bda0e17 82{
26f86486
VZ
83 wxCHECK_MSG( !gs_wxClipboardIsOpen, TRUE, "clipboard already opened." );
84
85 wxWindow *win = wxTheApp->GetTopWindow();
86 if ( win )
87 {
88 gs_wxClipboardIsOpen = ::OpenClipboard((HWND)win->GetHWND()) != 0;
89
90 if ( !gs_wxClipboardIsOpen )
91 wxLogSysError(_("Failed to open the clipboard."));
92
93 return gs_wxClipboardIsOpen;
94 }
95 else
96 {
97 wxLogDebug("Can not open clipboard without a main window,");
98
99 return FALSE;
100 }
2bda0e17
KB
101}
102
26f86486 103bool wxCloseClipboard()
2bda0e17 104{
26f86486
VZ
105 wxCHECK_MSG( gs_wxClipboardIsOpen, FALSE, "clipboard is not opened" );
106
107 gs_wxClipboardIsOpen = FALSE;
108
109 if ( ::CloseClipboard() == 0 )
110 {
111 wxLogSysError(_("Failed to close the clipboard."));
112
113 return FALSE;
114 }
115
116 return TRUE;
2bda0e17
KB
117}
118
26f86486 119bool wxEmptyClipboard()
2bda0e17 120{
26f86486
VZ
121 if ( ::EmptyClipboard() == 0 )
122 {
123 wxLogSysError(_("Failed to empty the clipboard."));
124
125 return FALSE;
126 }
127
128 return TRUE;
2bda0e17
KB
129}
130
26f86486 131bool wxIsClipboardOpened()
2bda0e17 132{
26f86486 133 return gs_wxClipboardIsOpen;
2bda0e17
KB
134}
135
06e43511 136bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
2bda0e17 137{
26f86486 138 return ::IsClipboardFormatAvailable(dataFormat) != 0;
2bda0e17
KB
139}
140
3f480da3
VZ
141#if wxUSE_DRAG_AND_DROP
142static bool wxSetClipboardData(wxDataObject *data)
143{
144 size_t size = data->GetDataSize();
145 HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
146 if ( !hGlobal )
147 {
148 wxLogSysError(_("Failed to allocate %dKb of memory for clipboard "
149 "transfer."), size / 1024);
150
151 return FALSE;
152 }
153
154 LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
155
156 data->GetDataHere(lpGlobalMemory);
157
158 GlobalUnlock(hGlobal);
159
160 wxDataFormat format = data->GetPreferredFormat();
161 if ( !::SetClipboardData(format, hGlobal) )
162 {
163 wxLogSysError(_("Failed to set clipboard data in format %s"),
164 wxDataObject::GetFormatName(format));
165
166 return FALSE;
167 }
168
169 return TRUE;
170}
171#endif // wxUSE_DRAG_AND_DROP
172
26f86486
VZ
173bool wxSetClipboardData(wxDataFormat dataFormat,
174 const void *data,
175 int width, int height)
2bda0e17 176{
26f86486
VZ
177 HANDLE handle = 0; // return value of SetClipboardData
178
179 switch (dataFormat)
2bda0e17 180 {
26f86486
VZ
181 case wxDF_BITMAP:
182 {
183 wxBitmap *bitmap = (wxBitmap *)data;
184
185 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
186 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
187 HBITMAP old = (HBITMAP)
188 ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP());
189 HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
190 bitmap->GetWidth(),
191 bitmap->GetHeight());
192 if (!hBitmap)
193 {
194 SelectObject(hdcSrc, old);
195 DeleteDC(hdcMem);
196 DeleteDC(hdcSrc);
197 return FALSE;
198 }
199
200 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
201 BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(),
202 hdcSrc, 0, 0, SRCCOPY);
203
204 // Select new bitmap out of memory DC
205 SelectObject(hdcMem, old1);
206
207 // Set the data
208 handle = ::SetClipboardData(CF_BITMAP, hBitmap);
209
210 // Clean up
211 SelectObject(hdcSrc, old);
212 DeleteDC(hdcSrc);
213 DeleteDC(hdcMem);
214 break;
215 }
216
217 case wxDF_DIB:
218 {
47d67540 219#if wxUSE_IMAGE_LOADING_IN_MSW
26f86486
VZ
220 wxBitmap *bitmap = (wxBitmap *)data;
221 HBITMAP hBitmap = (HBITMAP)bitmap->GetHBITMAP();
222 // NULL palette means to use the system one
223 HANDLE hDIB = BitmapToDIB(hBitmap, (HPALETTE)NULL);
224 handle = SetClipboardData(CF_DIB, hDIB);
2bda0e17 225#endif
26f86486
VZ
226 break;
227 }
228
47d67540 229#if wxUSE_METAFILE
26f86486
VZ
230 case wxDF_METAFILE:
231 {
232 wxMetafile *wxMF = (wxMetafile *)data;
233 HANDLE data = GlobalAlloc(GHND, sizeof(METAFILEPICT) + 1);
26f86486 234 METAFILEPICT *mf = (METAFILEPICT *)GlobalLock(data);
2bda0e17 235
26f86486
VZ
236 mf->mm = wxMF->GetWindowsMappingMode();
237 mf->xExt = width;
238 mf->yExt = height;
239 mf->hMF = (HMETAFILE) wxMF->GetHMETAFILE();
240 GlobalUnlock(data);
241 wxMF->SetHMETAFILE((WXHANDLE) NULL);
2bda0e17 242
26f86486
VZ
243 handle = SetClipboardData(CF_METAFILEPICT, data);
244 break;
245 }
2bda0e17 246#endif
26f86486
VZ
247 case CF_SYLK:
248 case CF_DIF:
249 case CF_TIFF:
250 case CF_PALETTE:
251 default:
252 {
253 wxLogError(_("Unsupported clipboard format."));
254 return FALSE;
255 }
2bda0e17 256
26f86486
VZ
257 case wxDF_OEMTEXT:
258 dataFormat = wxDF_TEXT;
259 // fall through
2bda0e17 260
26f86486
VZ
261 case wxDF_TEXT:
262 {
263 char *s = (char *)data;
264
265 width = strlen(s) + 1;
266 height = 1;
267 DWORD l = (width * height);
268 HANDLE hGlobalMemory = GlobalAlloc(GHND, l);
269 if ( hGlobalMemory )
270 {
26f86486 271 LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
2bda0e17 272
26f86486 273 memcpy(lpGlobalMemory, s, l);
2bda0e17 274
26f86486
VZ
275 GlobalUnlock(hGlobalMemory);
276 }
2bda0e17 277
26f86486
VZ
278 handle = SetClipboardData(dataFormat, hGlobalMemory);
279 break;
280 }
2bda0e17 281 }
26f86486
VZ
282
283 if ( handle == 0 )
2bda0e17 284 {
26f86486
VZ
285 wxLogSysError(_("Failed to set clipboard data."));
286
287 return FALSE;
2bda0e17 288 }
26f86486
VZ
289
290 return TRUE;
291}
292
293void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
294{
295 void *retval = NULL;
296
297 switch ( dataFormat )
2bda0e17 298 {
26f86486
VZ
299 case wxDF_BITMAP:
300 {
301 BITMAP bm;
302 HBITMAP hBitmap = (HBITMAP) GetClipboardData(CF_BITMAP);
303 if (!hBitmap)
304 break;
305
306 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
307 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
308
309 HBITMAP old = (HBITMAP) ::SelectObject(hdcSrc, hBitmap);
310 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
311
312 HBITMAP hNewBitmap = CreateBitmapIndirect(&bm);
313
314 if (!hNewBitmap)
315 {
316 SelectObject(hdcSrc, old);
317 DeleteDC(hdcMem);
318 DeleteDC(hdcSrc);
319 break;
320 }
321
322 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hNewBitmap);
323 BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight,
324 hdcSrc, 0, 0, SRCCOPY);
325
326 // Select new bitmap out of memory DC
327 SelectObject(hdcMem, old1);
328
329 // Clean up
330 SelectObject(hdcSrc, old);
331 DeleteDC(hdcSrc);
332 DeleteDC(hdcMem);
333
334 // Create and return a new wxBitmap
335 wxBitmap *wxBM = new wxBitmap;
336 wxBM->SetHBITMAP((WXHBITMAP) hNewBitmap);
337 wxBM->SetWidth(bm.bmWidth);
338 wxBM->SetHeight(bm.bmHeight);
339 wxBM->SetDepth(bm.bmPlanes);
340 wxBM->SetOk(TRUE);
341 retval = wxBM;
342 break;
343 }
344
345 case wxDF_METAFILE:
346 case CF_SYLK:
347 case CF_DIF:
348 case CF_TIFF:
349 case CF_PALETTE:
350 case wxDF_DIB:
26f86486
VZ
351 {
352 wxLogError(_("Unsupported clipboard format."));
353 return FALSE;
354 }
355
356 case wxDF_OEMTEXT:
357 dataFormat = wxDF_TEXT;
358 // fall through
359
360 case wxDF_TEXT:
361 {
362 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
363 if (!hGlobalMemory)
364 break;
2bda0e17 365
26f86486
VZ
366 DWORD hsize = ::GlobalSize(hGlobalMemory);
367 if (len)
368 *len = hsize;
2bda0e17 369
26f86486
VZ
370 char *s = new char[hsize];
371 if (!s)
372 break;
2bda0e17 373
26f86486 374 LPSTR lpGlobalMemory = (LPSTR)::GlobalLock(hGlobalMemory);
2bda0e17 375
26f86486 376 memcpy(s, lpGlobalMemory, hsize);
2bda0e17 377
26f86486
VZ
378 ::GlobalUnlock(hGlobalMemory);
379
380 retval = s;
381 break;
382 }
3f480da3
VZ
383
384 default:
385 {
386 HANDLE hGlobalMemory = ::GetClipboardData(dataFormat);
387 if ( !hGlobalMemory )
388 break;
389
390 DWORD size = ::GlobalSize(hGlobalMemory);
391 if ( len )
392 *len = size;
393
394 void *buf = malloc(size);
395 if ( !buf )
396 break;
397
398 LPSTR lpGlobalMemory = (LPSTR)::GlobalLock(hGlobalMemory);
399
400 memcpy(buf, lpGlobalMemory, size);
401
402 ::GlobalUnlock(hGlobalMemory);
403
404 retval = buf;
405 break;
406 }
26f86486 407 }
2bda0e17 408
26f86486
VZ
409 if ( !retval )
410 {
411 wxLogSysError(_("Failed to retrieve data from the clipboard."));
2bda0e17 412 }
26f86486
VZ
413
414 return retval;
2bda0e17
KB
415}
416
3f480da3 417wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
2bda0e17 418{
3f480da3 419 return ::EnumClipboardFormats(dataFormat);
2bda0e17
KB
420}
421
26f86486 422int wxRegisterClipboardFormat(char *formatName)
2bda0e17
KB
423{
424 return ::RegisterClipboardFormat(formatName);
425}
426
26f86486
VZ
427bool wxGetClipboardFormatName(wxDataFormat dataFormat,
428 char *formatName,
429 int maxCount)
2bda0e17 430{
26f86486 431 return ::GetClipboardFormatName((int)dataFormat, formatName, maxCount) > 0;
2bda0e17
KB
432}
433
26f86486 434// ---------------------------------------------------------------------------
06e43511 435// wxClipboard
26f86486 436// ---------------------------------------------------------------------------
2bda0e17 437
26f86486 438IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
2bda0e17 439
26f86486 440wxClipboard* wxTheClipboard = (wxClipboard *)NULL;
4ce81a75 441
2bda0e17
KB
442wxClipboard::wxClipboard()
443{
2bda0e17
KB
444}
445
446wxClipboard::~wxClipboard()
447{
26f86486 448 Clear();
2bda0e17
KB
449}
450
06e43511 451void wxClipboard::Clear()
2bda0e17 452{
2bda0e17
KB
453}
454
06e43511 455bool wxClipboard::Open()
2bda0e17 456{
06e43511 457 return wxOpenClipboard();
2bda0e17
KB
458}
459
06e43511 460bool wxClipboard::SetData( wxDataObject *data )
2bda0e17 461{
26f86486
VZ
462 (void)wxEmptyClipboard();
463
464 if ( data )
465 return AddData(data);
466 else
467 return TRUE;
468}
469
470bool wxClipboard::AddData( wxDataObject *data )
471{
06e43511 472 wxCHECK_MSG( data, FALSE, "data is invalid" );
06e43511 473
26f86486
VZ
474#if wxUSE_DRAG_AND_DROP
475 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, "clipboard not open" );
476
477 wxDataFormat format = data->GetFormat();
478
479 switch ( format )
06e43511
JS
480 {
481 case wxDF_TEXT:
482 case wxDF_OEMTEXT:
483 {
484 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
485 wxString str(textDataObject->GetText());
26f86486 486 return wxSetClipboardData(format, str.c_str());
06e43511 487 }
26f86486 488
06e43511
JS
489 case wxDF_BITMAP:
490 case wxDF_DIB:
491 {
492 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
493 wxBitmap bitmap(bitmapDataObject->GetBitmap());
26f86486 494 return wxSetClipboardData(data->GetFormat(), &bitmap);
06e43511 495 }
26f86486 496
06e43511
JS
497#if wxUSE_METAFILE
498 case wxDF_METAFILE:
499 {
26f86486
VZ
500 wxMetafileDataObject* metaFileDataObject =
501 (wxMetafileDataObject*) data;
06e43511 502 wxMetafile metaFile = metaFileDataObject->GetMetafile();
26f86486
VZ
503 return wxSetClipboardData(wxDF_METAFILE, &metaFile,
504 metaFileDataObject->GetWidth(),
505 metaFileDataObject->GetHeight());
06e43511 506 }
26f86486
VZ
507#endif // wxUSE_METAFILE
508
06e43511 509 default:
3f480da3 510 return wxSetClipboardData(data);
06e43511 511 }
3f480da3 512#else // !wxUSE_DRAG_AND_DROP
06e43511 513 return FALSE;
3f480da3 514#endif // wxUSE_DRAG_AND_DROP/!wxUSE_DRAG_AND_DROP
2bda0e17
KB
515}
516
06e43511 517void wxClipboard::Close()
2bda0e17 518{
06e43511 519 wxCloseClipboard();
2bda0e17
KB
520}
521
26f86486 522bool wxClipboard::IsSupported( wxDataFormat format )
2bda0e17 523{
06e43511 524 return wxIsClipboardFormatAvailable(format);
2bda0e17
KB
525}
526
06e43511 527bool wxClipboard::GetData( wxDataObject *data )
2bda0e17 528{
26f86486
VZ
529 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, "clipboard not open" );
530
06e43511 531#if wxUSE_DRAG_AND_DROP
26f86486
VZ
532 wxDataFormat format = data->GetFormat();
533 switch ( format )
06e43511
JS
534 {
535 case wxDF_TEXT:
536 case wxDF_OEMTEXT:
537 {
538 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
26f86486
VZ
539 char* s = (char*) wxGetClipboardData(format);
540 if ( s )
06e43511
JS
541 {
542 textDataObject->SetText(s);
543 delete[] s;
544 return TRUE;
545 }
546 else
547 return FALSE;
06e43511 548 }
26f86486 549
06e43511
JS
550 case wxDF_BITMAP:
551 case wxDF_DIB:
552 {
26f86486
VZ
553 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject *)data;
554 wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(data->GetFormat());
06e43511
JS
555 if (bitmap)
556 {
557 bitmapDataObject->SetBitmap(* bitmap);
558 delete bitmap;
559 return TRUE;
560 }
561 else
562 return FALSE;
06e43511
JS
563 }
564#if wxUSE_METAFILE
565 case wxDF_METAFILE:
566 {
26f86486
VZ
567 wxMetafileDataObject* metaFileDataObject = (wxMetafileDataObject *)data;
568 wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE);
06e43511
JS
569 if (metaFile)
570 {
26f86486 571 metaFileDataObject->SetMetafile(*metaFile);
06e43511
JS
572 delete metaFile;
573 return TRUE;
574 }
575 else
576 return FALSE;
06e43511
JS
577 }
578#endif
579 default:
3f480da3
VZ
580 {
581 long len;
582 void *buf = wxGetClipboardData(format, &len);
583 if ( buf )
584 {
585 // FIXME this is for testing only!!
586 ((wxPrivateDataObject *)data)->SetData(buf, len);
587 free(buf);
588
589 return TRUE;
590 }
591 }
26f86486 592
06e43511 593 return FALSE;
06e43511 594 }
06e43511
JS
595#else
596 return FALSE;
597#endif
2bda0e17
KB
598}
599
4ce81a75
JS
600//-----------------------------------------------------------------------------
601// wxClipboardModule
602//-----------------------------------------------------------------------------
603
604IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
605
606bool wxClipboardModule::OnInit()
607{
608 wxTheClipboard = new wxClipboard();
26f86486 609
4ce81a75
JS
610 return TRUE;
611}
612
613void wxClipboardModule::OnExit()
614{
615 if (wxTheClipboard) delete wxTheClipboard;
616 wxTheClipboard = (wxClipboard*) NULL;
617}
618
26f86486
VZ
619#else
620 #error "Please turn wxUSE_CLIPBOARD on to compile this file."
47d67540 621#endif // wxUSE_CLIPBOARD
4ce81a75 622