]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/clipbrd.cpp
another attempt to fix wxPanel/wxFrame::m_winLastFocused handling
[wxWidgets.git] / src / mac / carbon / clipbrd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: clipbrd.cpp
3 // Purpose: Clipboard functionality
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #pragma implementation "clipbrd.h"
15 #endif
16
17 #include "wx/app.h"
18 #include "wx/frame.h"
19 #include "wx/bitmap.h"
20 #include "wx/utils.h"
21 #include "wx/metafile.h"
22 #include "wx/clipbrd.h"
23 #include "wx/intl.h"
24
25 #define wxUSE_DATAOBJ 1
26
27 #include <string.h>
28
29 // open/close
30
31 bool clipboard_opened = false ;
32
33 bool wxOpenClipboard()
34 {
35 clipboard_opened = true ;
36 return TRUE;
37 }
38
39 bool wxCloseClipboard()
40 {
41 clipboard_opened = false ;
42 return TRUE;
43 }
44
45 bool wxIsClipboardOpened()
46 {
47 return clipboard_opened;
48 }
49
50 bool wxEmptyClipboard()
51 {
52
53 #if TARGET_CARBON
54 OSStatus err ;
55 err = ClearCurrentScrap( );
56 #else
57 OSErr err ;
58 err = ZeroScrap( );
59 #endif
60 if ( err )
61 {
62 wxLogSysError(_("Failed to empty the clipboard."));
63 return FALSE ;
64 }
65 return TRUE;
66 }
67
68 // get/set data
69
70 // clipboard formats
71
72 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
73 {
74 #if TARGET_CARBON
75 OSStatus err = noErr;
76 ScrapRef scrapRef;
77
78 err = GetCurrentScrap( &scrapRef );
79 if ( err != noTypeErr && err != memFullErr )
80 {
81 ScrapFlavorFlags flavorFlags;
82 Size byteCount;
83
84 if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr)
85 {
86 if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr)
87 {
88 return TRUE ;
89 }
90 }
91 }
92 return FALSE;
93
94 #else
95 long offset ;
96 Handle datahandle = NewHandle(0) ;
97 HLock( datahandle ) ;
98 GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ;
99 HUnlock( datahandle ) ;
100 bool hasData = GetHandleSize( datahandle ) > 0 ;
101 DisposeHandle( datahandle ) ;
102 return hasData ;
103 #endif
104 }
105
106 bool wxSetClipboardData(wxDataFormat dataFormat,const void *data,int width , int height)
107 {
108 #if !TARGET_CARBON
109 OSErr err = noErr ;
110 #else
111 OSStatus err = noErr ;
112 #endif
113
114 switch (dataFormat.GetType())
115 {
116 case wxDF_BITMAP:
117 {
118 /*
119 wxBitmap *bitmap = (wxBitmap *)data;
120
121 HDC hdcMem = CreateCompatibleDC((HDC) NULL);
122 HDC hdcSrc = CreateCompatibleDC((HDC) NULL);
123 HBITMAP old = (HBITMAP)
124 ::SelectObject(hdcSrc, (HBITMAP)bitmap->GetHBITMAP());
125 HBITMAP hBitmap = CreateCompatibleBitmap(hdcSrc,
126 bitmap->GetWidth(),
127 bitmap->GetHeight());
128 if (!hBitmap)
129 {
130 SelectObject(hdcSrc, old);
131 DeleteDC(hdcMem);
132 DeleteDC(hdcSrc);
133 return FALSE;
134 }
135
136 HBITMAP old1 = (HBITMAP) SelectObject(hdcMem, hBitmap);
137 BitBlt(hdcMem, 0, 0, bitmap->GetWidth(), bitmap->GetHeight(),
138 hdcSrc, 0, 0, SRCCOPY);
139
140 // Select new bitmap out of memory DC
141 SelectObject(hdcMem, old1);
142
143 // Set the data
144 handle = ::SetClipboardData(CF_BITMAP, hBitmap);
145
146 // Clean up
147 SelectObject(hdcSrc, old);
148 DeleteDC(hdcSrc);
149 DeleteDC(hdcMem);
150 */
151 break;
152 }
153
154 case wxDF_DIB:
155 {
156 /*
157 #if wxUSE_IMAGE_LOADING_IN_MSW
158 wxBitmap *bitmap = (wxBitmap *)data;
159 HBITMAP hBitmap = (HBITMAP)bitmap->GetHBITMAP();
160 // NULL palette means to use the system one
161 HANDLE hDIB = wxBitmapToDIB(hBitmap, (HPALETTE)NULL);
162 handle = SetClipboardData(CF_DIB, hDIB);
163 #endif // wxUSE_IMAGE_LOADING_IN_MSW
164 */
165 break;
166 }
167
168 #if wxUSE_METAFILE
169 case wxDF_METAFILE:
170 {
171 wxMetafile *wxMF = (wxMetafile *)data;
172 PicHandle pict = wxMF->GetHMETAFILE() ;
173 HLock( (Handle) pict ) ;
174 #if !TARGET_CARBON
175 err = PutScrap( GetHandleSize( (Handle) pict ) , 'PICT' , *pict ) ;
176 #else
177 ScrapRef scrap;
178 err = GetCurrentScrap (&scrap);
179 if ( !err )
180 {
181 err = PutScrapFlavor (scrap, 'PICT', 0, GetHandleSize((Handle) pict), *pict);
182 }
183 #endif
184 HUnlock( (Handle) pict ) ;
185 break;
186 }
187 #endif
188 case wxDF_SYLK:
189 case wxDF_DIF:
190 case wxDF_TIFF:
191 case wxDF_PALETTE:
192 default:
193 {
194 wxLogError(_("Unsupported clipboard format."));
195 return FALSE;
196 }
197
198 case wxDF_OEMTEXT:
199 dataFormat = wxDF_TEXT;
200 // fall through
201
202 case wxDF_TEXT:
203 {
204 wxString mac ;
205 if ( wxApp::s_macDefaultEncodingIsPC )
206 {
207 mac = wxMacMakeMacStringFromPC((char *)data) ;
208 }
209 else
210 {
211 mac = (char *)data ;
212 }
213 #if !TARGET_CARBON
214 err = PutScrap( mac.Length() , 'TEXT' , mac.c_str() ) ;
215 #else
216 ScrapRef scrap;
217 err = GetCurrentScrap (&scrap);
218 if ( !err )
219 {
220 err = PutScrapFlavor (scrap, 'TEXT', 0, mac.Length(), mac.c_str());
221 }
222 #endif
223 break;
224 }
225 }
226
227 if ( err )
228 {
229 wxLogSysError(_("Failed to set clipboard data."));
230
231 return FALSE;
232 }
233
234 return TRUE;
235 }
236
237 wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
238 {
239 return wxDataFormat();
240 }
241
242 int wxRegisterClipboardFormat(wxChar *formatName)
243 {
244 return 0;
245 }
246
247 bool wxGetClipboardFormatName(wxDataFormat dataFormat, wxChar *formatName, int maxCount)
248 {
249 return FALSE;
250 }
251
252 void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
253 {
254 #if !TARGET_CARBON
255 OSErr err = noErr ;
256 #else
257 OSStatus err = noErr ;
258 #endif
259 void * data = NULL ;
260
261 switch (dataFormat.GetType())
262 {
263 case wxDF_BITMAP:
264 case wxDF_DIB:
265 #if wxUSE_METAFILE
266 case wxDF_METAFILE:
267 #endif
268 case wxDF_SYLK:
269 case wxDF_DIF:
270 case wxDF_TIFF:
271 case wxDF_PALETTE:
272 default:
273 {
274 wxLogError(_("Unsupported clipboard format."));
275 return NULL;
276 }
277
278 case wxDF_OEMTEXT:
279 dataFormat = wxDF_TEXT;
280 // fall through
281
282 case wxDF_TEXT:
283 break;
284 }
285
286 #if TARGET_CARBON
287 ScrapRef scrapRef;
288
289 err = GetCurrentScrap( &scrapRef );
290 if ( err != noTypeErr && err != memFullErr )
291 {
292 ScrapFlavorFlags flavorFlags;
293 Size byteCount;
294
295 if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr)
296 {
297 if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr)
298 {
299 if ( dataFormat.GetType() == wxDF_TEXT )
300 byteCount++ ;
301
302 data = new char[ byteCount ] ;
303 if (( err = GetScrapFlavorData( scrapRef, dataFormat.GetFormatId(), &byteCount , data )) == noErr )
304 {
305 *len = byteCount ;
306 if ( dataFormat.GetType() == wxDF_TEXT )
307 ((char*)data)[byteCount] = 0 ;
308 }
309 else
310 {
311 delete[] data ;
312 data = NULL ;
313 }
314 }
315 }
316 }
317
318 #else
319 long offset ;
320 Handle datahandle = NewHandle(0) ;
321 HLock( datahandle ) ;
322 GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ;
323 HUnlock( datahandle ) ;
324 if ( GetHandleSize( datahandle ) > 0 )
325 {
326 long byteCount = GetHandleSize( datahandle ) ;
327 if ( dataFormat.GetType() == wxDF_TEXT )
328 data = new char[ byteCount + 1] ;
329 else
330 data = new char[ byteCount ] ;
331
332 memcpy( (char*) data , (char*) *datahandle , byteCount ) ;
333 if ( dataFormat.GetType() == wxDF_TEXT )
334 ((char*)data)[byteCount] = 0 ;
335 * len = byteCount ;
336 }
337 DisposeHandle( datahandle ) ;
338 #endif
339 if ( err )
340 {
341 wxLogSysError(_("Failed to get clipboard data."));
342
343 return NULL ;
344 }
345 if ( dataFormat.GetType() == wxDF_TEXT && wxApp::s_macDefaultEncodingIsPC )
346 {
347 wxMacConvertToPC((char*)data) ;
348 }
349 return data;
350 }
351
352
353 /*
354 * Generalized clipboard implementation by Matthew Flatt
355 */
356
357 IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxClipboardBase)
358
359 wxClipboard::wxClipboard()
360 {
361 m_clearOnExit = FALSE;
362 }
363
364 wxClipboard::~wxClipboard()
365 {
366 if ( m_clearOnExit )
367 {
368 Clear();
369 }
370 }
371
372 void wxClipboard::Clear()
373 {
374 }
375
376 bool wxClipboard::Flush()
377 {
378 return FALSE;
379 }
380
381 bool wxClipboard::Open()
382 {
383 return wxOpenClipboard();
384 }
385
386 bool wxClipboard::IsOpened() const
387 {
388 return wxIsClipboardOpened();
389 }
390
391 static int FormatStringToID(char *str)
392 {
393 if (!strcmp(str, "TEXT"))
394 return wxDF_TEXT;
395
396 return wxRegisterClipboardFormat(str);
397 }
398
399 bool wxClipboard::SetData( wxDataObject *data )
400 {
401 (void)wxEmptyClipboard();
402
403 if ( data )
404 return AddData(data);
405 else
406 return TRUE;
407 }
408
409 bool wxClipboard::AddData( wxDataObject *data )
410 {
411 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
412
413 #if wxUSE_DATAOBJ
414 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
415
416 wxDataFormat format = data->GetPreferredFormat();
417
418 switch ( format.GetType() )
419 {
420 case wxDF_TEXT:
421 case wxDF_OEMTEXT:
422 {
423 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
424 wxString str(textDataObject->GetText());
425 return wxSetClipboardData(format, str.c_str());
426 }
427
428 case wxDF_BITMAP:
429 case wxDF_DIB:
430 {
431 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data;
432 wxBitmap bitmap(bitmapDataObject->GetBitmap());
433 return wxSetClipboardData(format, &bitmap);
434 }
435
436 #if 0 // wxUSE_METAFILE
437 case wxDF_METAFILE:
438 {
439 wxMetafileDataObject* metaFileDataObject =
440 (wxMetafileDataObject*) data;
441 wxMetafile metaFile = metaFileDataObject->GetMetafile();
442 return wxSetClipboardData(wxDF_METAFILE, &metaFile,
443 metaFileDataObject->GetWidth(),
444 metaFileDataObject->GetHeight());
445 }
446 #endif // wxUSE_METAFILE
447
448 default:
449 // return wxSetClipboardData(data);
450 break ;
451 }
452 #else // !wxUSE_DATAOBJ
453 #endif
454 return FALSE;
455 }
456
457 void wxClipboard::Close()
458 {
459 wxCloseClipboard();
460 }
461
462 bool wxClipboard::IsSupported( const wxDataFormat &format )
463 {
464 return wxIsClipboardFormatAvailable(format);
465 }
466
467 bool wxClipboard::GetData( wxDataObject& data )
468 {
469 #if wxUSE_DATAOBJ
470 wxCHECK_MSG( wxIsClipboardOpened(), FALSE, wxT("clipboard not open") );
471
472 wxDataFormat format = data.GetPreferredFormat();
473 switch ( format.GetType() )
474 {
475 case wxDF_TEXT:
476 case wxDF_OEMTEXT:
477 {
478 wxTextDataObject& textDataObject = (wxTextDataObject &)data;
479 char* s = (char*)wxGetClipboardData(format);
480 if ( !s )
481 return FALSE;
482
483 textDataObject.SetText(s);
484 delete [] s;
485
486 return TRUE;
487 }
488
489 case wxDF_BITMAP:
490 case wxDF_DIB:
491 {
492 wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data;
493 wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(format );
494 if ( !bitmap )
495 return FALSE;
496
497 bitmapDataObject.SetBitmap(*bitmap);
498 delete bitmap;
499
500 return TRUE;
501 }
502 #if 0 // wxUSE_METAFILE
503 case wxDF_METAFILE:
504 {
505 wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data;
506 wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE);
507 if ( !metaFile )
508 return FALSE;
509
510 metaFileDataObject.SetMetafile(*metaFile);
511 delete metaFile;
512
513 return TRUE;
514 }
515 #endif // wxUSE_METAFILE
516 }
517 #else // !wxUSE_DATAOBJ
518 wxFAIL_MSG( wxT("no clipboard implementation") );
519 #endif
520 return FALSE;
521 }
522 /*
523 void wxClipboard::SetClipboardClient(wxClipboardClient *client, long time)
524 {
525 bool got_selection;
526
527 if (clipOwner)
528 clipOwner->BeingReplaced();
529 clipOwner = client;
530 if (cbString) {
531 delete[] cbString;
532 cbString = NULL;
533 }
534
535 if (wxOpenClipboard()) {
536 char **formats, *data;
537 int i;
538 int ftype;
539 long size;
540
541 formats = clipOwner->formats.ListToArray(FALSE);
542 for (i = clipOwner->formats.Number(); i--; ) {
543 ftype = FormatStringToID(formats[i]);
544 data = clipOwner->GetData(formats[i], &size);
545 if (!wxSetClipboardData(ftype, (wxObject *)data, size, 1)) {
546 got_selection = FALSE;
547 break;
548 }
549 }
550
551 if (i < 0)
552 got_selection = wxCloseClipboard();
553 } else
554 got_selection = FALSE;
555
556 got_selection = FALSE; // Assume another process takes over
557
558 if (!got_selection) {
559 clipOwner->BeingReplaced();
560 clipOwner = NULL;
561 }
562 }
563
564 wxClipboardClient *wxClipboard::GetClipboardClient()
565 {
566 return clipOwner;
567 }
568
569 void wxClipboard::SetClipboardString(char *str, long time)
570 {
571 bool got_selection;
572
573 if (clipOwner) {
574 clipOwner->BeingReplaced();
575 clipOwner = NULL;
576 }
577 if (cbString)
578 delete[] cbString;
579
580 cbString = str;
581
582 if (wxOpenClipboard()) {
583 if (!wxSetClipboardData(wxDF_TEXT, (wxObject *)str))
584 got_selection = FALSE;
585 else
586 got_selection = wxCloseClipboard();
587 } else
588 got_selection = FALSE;
589
590 got_selection = FALSE; // Assume another process takes over
591
592 if (!got_selection) {
593 delete[] cbString;
594 cbString = NULL;
595 }
596 }
597 char *wxClipboard::GetClipboardString(long time)
598 {
599 char *str;
600 long length;
601
602 str = GetClipboardData("TEXT", &length, time);
603 if (!str) {
604 str = new char[1];
605 *str = 0;
606 }
607
608 return str;
609 }
610
611
612 char *wxClipboard::GetClipboardData(char *format, long *length, long time)
613 {
614 if (clipOwner) {
615 if (clipOwner->formats.Member(format))
616 return clipOwner->GetData(format, length);
617 else
618 return NULL;
619 } else if (cbString) {
620 if (!strcmp(format, "TEXT"))
621 return copystring(cbString);
622 else
623 return NULL;
624 } else {
625 if (wxOpenClipboard()) {
626 receivedString = (char *)wxGetClipboardData(FormatStringToID(format),
627 length);
628 wxCloseClipboard();
629 } else
630 receivedString = NULL;
631
632 return receivedString;
633 }
634 }
635 */
636