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