]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/dataobj.cpp
making sure it always returns a valid string
[wxWidgets.git] / src / mac / carbon / dataobj.cpp
CommitLineData
72e7876b 1///////////////////////////////////////////////////////////////////////////////
51d4293d 2// Name: src/mac/carbon/dataobj.cpp
427ff662
SC
3// Purpose: implementation of wxDataObject class
4// Author: Stefan Csomor
72e7876b
SC
5// Modified by:
6// Created: 10/21/99
7// RCS-ID: $Id$
427ff662 8// Copyright: (c) 1999 Stefan Csomor
65571936 9// Licence: wxWindows licence
72e7876b
SC
10///////////////////////////////////////////////////////////////////////////////
11
72e7876b
SC
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
179e085f
RN
15#if wxUSE_DATAOBJ
16
88a7a4e1
WS
17#include "wx/dataobj.h"
18
72e7876b 19#ifndef WX_PRECOMP
88a7a4e1 20 #include "wx/intl.h"
e4db172a 21 #include "wx/log.h"
f38924e8 22 #include "wx/dcmemory.h"
155ecd4c 23 #include "wx/image.h"
72e7876b 24#endif
72e7876b 25
72e7876b 26#include "wx/mstream.h"
71cc158e 27#include "wx/metafile.h"
d7b284e5
SC
28#include "wx/tokenzr.h"
29
6239ee05 30#include "wx/mac/uma.h"
51d4293d 31
6239ee05
SC
32#ifdef __DARWIN__
33 #include <QuickTime/QuickTime.h>
768c6e8b 34#endif
72e7876b 35
72e7876b
SC
36
37// ----------------------------------------------------------------------------
38// wxDataFormat
39// ----------------------------------------------------------------------------
40
41wxDataFormat::wxDataFormat()
42{
2f1ae414
SC
43 m_type = wxDF_INVALID;
44 m_format = 0;
72e7876b
SC
45}
46
51d4293d 47wxDataFormat::wxDataFormat( wxDataFormatId vType )
72e7876b 48{
6239ee05
SC
49 m_format = 0;
50 m_type = wxDF_INVALID;
51d4293d 51 SetType( vType );
72e7876b
SC
52}
53
6239ee05
SC
54wxDataFormat::wxDataFormat( const wxChar *zId )
55{
56 m_format = 0;
57 m_type = wxDF_INVALID;
58 SetId( zId );
59}
60
51d4293d 61wxDataFormat::wxDataFormat( const wxString& rId )
72e7876b 62{
6239ee05
SC
63 m_format = 0;
64 m_type = wxDF_INVALID;
51d4293d 65 SetId( rId );
72e7876b
SC
66}
67
6239ee05
SC
68wxDataFormat::wxDataFormat(const wxDataFormat& rFormat)
69{
70 if ( rFormat.m_format )
71 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
72 else
73 m_format = 0;
74 m_type = rFormat.m_type;
75 m_id = rFormat.m_id;
76}
77
51d4293d 78wxDataFormat::wxDataFormat( NativeFormat vFormat )
72e7876b 79{
6239ee05
SC
80 m_format = 0;
81 m_type = wxDF_INVALID;
51d4293d 82 SetId( vFormat );
72e7876b
SC
83}
84
6239ee05
SC
85wxDataFormat::~wxDataFormat()
86{
87 if ( m_format != 0 )
88 {
89 CFRelease( (CFStringRef) m_format );
90 m_format = 0;
91 }
92}
93
94// in order to be correct for 10.3 we restrict to the available types there
95// http://developer.apple.com/qa/qa2005/qa1406.html
96// TODO : Use UTCoreTypes.h constants once we support 10.4+ only
97
98wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
99{
100 if ( m_format != 0 )
101 {
102 CFRelease( (CFStringRef) m_format );
103 m_format = 0;
104 }
105 if ( rFormat.m_format )
106 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
107 m_type = rFormat.m_type;
108 m_id = rFormat.m_id;
109 return *this;
110}
111
51d4293d 112void wxDataFormat::SetType( wxDataFormatId dataType )
72e7876b 113{
51d4293d 114 m_type = dataType;
6239ee05
SC
115 if ( m_format != 0 )
116 {
117 CFRelease( (CFStringRef) m_format );
118 m_format = 0;
119 }
2f1ae414 120
51d4293d
DS
121 switch (m_type)
122 {
123 case wxDF_TEXT:
6239ee05 124 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
51d4293d
DS
125 break;
126
127 case wxDF_UNICODETEXT:
6239ee05 128 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
51d4293d
DS
129 break;
130
131 case wxDF_BITMAP:
6239ee05 132 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
6239ee05 133 break;
51d4293d 134 case wxDF_METAFILE:
6239ee05 135 m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
51d4293d 136 break;
72e7876b 137
51d4293d 138 case wxDF_FILENAME:
6239ee05 139 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
51d4293d
DS
140 break;
141
142 default:
143 wxFAIL_MSG( wxT("invalid data format") );
51d4293d 144 break;
63b8dd39 145 }
72e7876b
SC
146}
147
148wxString wxDataFormat::GetId() const
149{
ea6bea0f 150 return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
72e7876b
SC
151}
152
51d4293d 153void wxDataFormat::SetId( NativeFormat format )
72e7876b 154{
6239ee05
SC
155 if ( m_format != 0 )
156 {
157 CFRelease( (CFStringRef) m_format );
158 m_format = 0;
159 }
160 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
161 if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) )
51d4293d 162 {
427ff662 163 m_type = wxDF_UNICODETEXT;
6239ee05
SC
164 }
165 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
166 {
167 m_type = wxDF_TEXT;
168 }
6239ee05
SC
169 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
170 {
72e7876b 171 m_type = wxDF_BITMAP;
6239ee05
SC
172 }
173 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
174 {
175 m_type = wxDF_METAFILE;
176 }
6239ee05
SC
177 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
178 {
72e7876b 179 m_type = wxDF_FILENAME;
6239ee05
SC
180 }
181 else
182 {
72e7876b 183 m_type = wxDF_PRIVATE;
dbe4a80c 184 m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
0b6db82f 185 }
72e7876b
SC
186}
187
a1eb65c2 188void wxDataFormat::SetId( const wxString& zId )
72e7876b 189{
2f1ae414 190 m_type = wxDF_PRIVATE;
51d4293d 191 m_id = zId;
6239ee05
SC
192 if ( m_format != 0 )
193 {
194 CFRelease( (CFStringRef) m_format );
195 m_format = 0;
196 }
197 // since it is private, no need to conform to anything ...
dbe4a80c 198 m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
0b6db82f
SC
199}
200
51d4293d 201bool wxDataFormat::operator==(const wxDataFormat& format) const
0b6db82f 202{
51d4293d
DS
203 if (IsStandard() || format.IsStandard())
204 return (format.m_type == m_type);
0b6db82f 205 else
6239ee05 206 return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
72e7876b
SC
207}
208
209//-------------------------------------------------------------------------
210// wxDataObject
211//-------------------------------------------------------------------------
212
213wxDataObject::wxDataObject()
214{
215}
216
51d4293d 217bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
72e7876b 218{
51d4293d
DS
219 size_t nFormatCount = GetFormatCount( vDir );
220 bool found = false;
72e7876b
SC
221
222 if (nFormatCount == 1)
223 {
51d4293d 224 found = (rFormat == GetPreferredFormat());
72e7876b
SC
225 }
226 else
227 {
5aa67d66 228 wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
51d4293d 229 GetAllFormats( pFormats, vDir );
72e7876b 230
51d4293d 231 for (size_t n = 0; n < nFormatCount; n++)
72e7876b
SC
232 {
233 if (pFormats[n] == rFormat)
51d4293d 234 {
5aa67d66 235 found = true;
72e7876b 236 break;
51d4293d 237 }
72e7876b
SC
238 }
239
240 delete [] pFormats;
72e7876b 241 }
51d4293d
DS
242
243 return found;
72e7876b
SC
244}
245
6239ee05
SC
246void wxDataObject::AddToPasteboard( void * pb, int itemID )
247{
248 PasteboardRef pasteboard = (PasteboardRef) pb;
249 // get formats from wxDataObjects
250 wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
251 GetAllFormats( array );
252
253 for (size_t i = 0; i < GetFormatCount(); i++)
254 {
255 wxDataFormat thisFormat = array[ i ];
256
257 // add four bytes at the end for data objs like text that
258 // have a datasize = strlen but still need a buffer for the
259 // string including trailing zero
260
261 size_t datasize = GetDataSize( thisFormat );
262 size_t sz = datasize + 4;
263 void* buf = malloc( sz );
264 if ( buf != NULL )
265 {
266 // empty the buffer because in some case GetDataHere does not fill buf
267 memset( buf, 0, sz );
268 if ( GetDataHere( array[ i ], buf ) )
269 {
270 int counter = 1 ;
271 if ( thisFormat.GetType() == wxDF_FILENAME )
272 {
273 // the data is D-normalized UTF8 strings of filenames delimited with \n
274 char *fname = strtok((char*) buf,"\n");
275 while (fname != NULL)
276 {
277 // translate the filepath into a fileurl and put that into the pasteobard
278 CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
279 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
280 CFRelease(path);
281 CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
282 CFRelease(url);
283 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
284 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
285 CFRelease( data );
286 counter++;
287 fname = strtok (NULL,"\n");
288 }
289
290 }
291 else
292 {
293 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
294 if ( thisFormat.GetType() == wxDF_TEXT )
295 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
296 CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
297 else
298 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
299 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
300 CFRelease( data );
301 }
302 }
303 free( buf );
304 }
305 }
306
307 delete [] array;
308}
309
310bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
311{
312 PasteboardRef pasteboard = (PasteboardRef) pb;
313 bool hasData = false;
314 OSStatus err = noErr;
315 ItemCount itemCount;
316
317 // we synchronize here once again, so we don't mind which flags get returned
318 PasteboardSynchronize( pasteboard );
319
320 err = PasteboardGetItemCount( pasteboard, &itemCount );
321 if ( err == noErr )
322 {
323 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
324 {
325 PasteboardItemID itemID;
326 CFArrayRef flavorTypeArray;
327 CFIndex flavorCount;
328
329 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
330 if ( err != noErr )
331 continue;
332
333 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
334 if ( err != noErr )
335 continue;
336
337 flavorCount = CFArrayGetCount( flavorTypeArray );
338
339 for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
340 {
341 CFStringRef flavorType;
342
343 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
344 flavorIndex );
345
346 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
347 if ( dataFormat == flavorFormat )
348 hasData = true;
349 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
350 hasData = true;
351 }
352 CFRelease (flavorTypeArray);
353 }
354 }
355
356 return hasData;
357}
358
359bool wxDataObject::GetFromPasteboard( void * pb )
360{
361 PasteboardRef pasteboard = (PasteboardRef) pb;
362 size_t formatcount = GetFormatCount() + 1;
363 wxDataFormat *array = new wxDataFormat[ formatcount ];
364 array[0] = GetPreferredFormat();
365 GetAllFormats( &array[1] );
366 ItemCount itemCount = 0;
367 wxString filenamesPassed;
368 bool transferred = false;
369
370 // we synchronize here once again, so we don't mind which flags get returned
371 PasteboardSynchronize( pasteboard );
372
373 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
374 if ( err == noErr )
375 {
376 for (size_t i = 0; !transferred && i < formatcount; i++)
377 {
378 // go through the data in our order of preference
379 wxDataFormat dataFormat = array[ i ];
380
381 for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
382 {
383 PasteboardItemID itemID = 0;
384 CFArrayRef flavorTypeArray = NULL;
385 CFIndex flavorCount = 0;
386
387 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
388 if ( err != noErr )
389 continue;
390
391 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
392 if ( err != noErr )
393 continue;
394
395 flavorCount = CFArrayGetCount( flavorTypeArray );
396
397 for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
398 {
399 CFStringRef flavorType;
400 CFDataRef flavorData;
401 CFIndex flavorDataSize;
402
403 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
404 flavorIndex );
405
406 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
407
408 if ( dataFormat == flavorFormat )
409 {
410 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
411 if ( err == noErr )
412 {
413 flavorDataSize = CFDataGetLength( flavorData );
414 if (dataFormat.GetType() == wxDF_FILENAME )
415 {
416 // revert the translation and decomposition to arrive at a proper utf8 string again
417 CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
418 CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
419 CFRelease( url );
420 CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
421 CFRelease( cfString );
422 CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
dbe4a80c 423 wxString path = wxCFStringRef(cfMutableString).AsString();
6239ee05
SC
424 if (!path.empty())
425 filenamesPassed += path + wxT("\n");
426 }
427 else
428 {
429 // because some data implementation expect trailing a trailing NUL, we add some headroom
430 void *buf = malloc( flavorDataSize + 4 );
431 if ( buf )
432 {
433 memset( buf, 0, flavorDataSize + 4 );
434 memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
435
436 if (dataFormat.GetType() == wxDF_TEXT)
437 wxMacConvertNewlines10To13( (char*) buf );
438 SetData( flavorFormat, flavorDataSize, buf );
439 transferred = true;
440 free( buf );
441 }
442 }
443 CFRelease (flavorData);
444 }
445 }
446 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
447 {
448 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
449 if ( err == noErr )
450 {
451 flavorDataSize = CFDataGetLength( flavorData );
452 void *asciibuf = malloc( flavorDataSize + 1 );
453 if ( asciibuf )
454 {
455 memset( asciibuf, 0, flavorDataSize + 1 );
456 memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
457 CFRelease (flavorData);
458
459 SetData( wxDF_TEXT, flavorDataSize, asciibuf );
460 transferred = true;
461 free( asciibuf );
462 }
463 else
464 CFRelease (flavorData);
465 }
466 }
467 }
468 CFRelease( flavorTypeArray );
469 }
470 if (filenamesPassed.length() > 0)
471 {
472 wxCharBuffer buf = filenamesPassed.fn_str();
473 SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
474 transferred = true;
475 }
476 }
477 }
478 return transferred;
479}
480
481bool wxDataObject::HasDataInPasteboard( void * pb )
482{
483 PasteboardRef pasteboard = (PasteboardRef) pb;
484 size_t formatcount = GetFormatCount() + 1;
485 wxDataFormat *array = new wxDataFormat[ formatcount ];
486 array[0] = GetPreferredFormat();
487 GetAllFormats( &array[1] );
488 ItemCount itemCount = 0;
489 bool hasData = false;
490
491 // we synchronize here once again, so we don't mind which flags get returned
492 PasteboardSynchronize( pasteboard );
493
494 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
495 if ( err == noErr )
496 {
497 for (size_t i = 0; !hasData && i < formatcount; i++)
498 {
499 // go through the data in our order of preference
500 wxDataFormat dataFormat = array[ i ];
501
502 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
503 {
504 PasteboardItemID itemID = 0;
505 CFArrayRef flavorTypeArray = NULL;
506 CFIndex flavorCount = 0;
507
508 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
509 if ( err != noErr )
510 continue;
511
512 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
513 if ( err != noErr )
514 continue;
515
516 flavorCount = CFArrayGetCount( flavorTypeArray );
517
518 for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
519 {
520 CFStringRef flavorType;
521
522 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
523 flavorIndex );
524
525 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
526
527 if ( dataFormat == flavorFormat ||
528 dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
529 {
530 hasData = true;
531 }
532 }
533 CFRelease( flavorTypeArray );
534 }
535 }
536 }
537 return hasData;
538}
539
25758297
SC
540// ----------------------------------------------------------------------------
541// wxTextDataObject
542// ----------------------------------------------------------------------------
543
544#if wxUSE_UNICODE
89954433
VZ
545void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
546 wxDataObjectBase::Direction WXUNUSED(dir)) const
25758297
SC
547{
548 *formats++ = wxDataFormat( wxDF_TEXT );
549 *formats = wxDataFormat( wxDF_UNICODETEXT );
550}
25758297
SC
551#endif
552
72e7876b
SC
553// ----------------------------------------------------------------------------
554// wxFileDataObject
555// ----------------------------------------------------------------------------
556
5aa67d66 557void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
d7b284e5
SC
558{
559 wxString filenames;
5aa67d66 560
d7b284e5
SC
561 for (size_t i = 0; i < m_filenames.GetCount(); i++)
562 {
563 filenames += m_filenames[i];
564 filenames += wxT('\n');
565 }
5aa67d66 566
d7b284e5
SC
567 buf = filenames.fn_str();
568}
569
51d4293d 570bool wxFileDataObject::GetDataHere( void *pBuf ) const
72e7876b 571{
51d4293d
DS
572 if (pBuf == NULL)
573 return false;
574
d7b284e5 575 wxCharBuffer buf;
5aa67d66 576 size_t buffLength;
72e7876b 577
5aa67d66
DS
578 GetFileNames( buf );
579 buffLength = strlen( buf );
580 memcpy( pBuf, (const char*)buf, buffLength + 1 );
51d4293d
DS
581
582 return true;
72e7876b
SC
583}
584
585size_t wxFileDataObject::GetDataSize() const
586{
d7b284e5 587 wxCharBuffer buf;
5aa67d66
DS
588 size_t buffLength;
589
d7b284e5 590 GetFileNames( buf );
5aa67d66 591 buffLength = strlen( buf );
6239ee05 592 // terminating 0
5aa67d66 593 return buffLength + 1;
72e7876b
SC
594}
595
89954433 596bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
72e7876b 597{
d7b284e5 598 wxString filenames;
5aa67d66 599
d7b284e5 600#if wxUSE_UNICODE
5aa67d66 601 filenames = wxString( (const char*)pBuf, *wxConvFileName );
d7b284e5 602#else
5088ab3f 603 filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
d7b284e5 604#endif
72e7876b 605
5aa67d66
DS
606 m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
607
51d4293d 608 return true;
72e7876b
SC
609}
610
51d4293d 611void wxFileDataObject::AddFile( const wxString& rFilename )
72e7876b 612{
51d4293d 613 m_filenames.Add( rFilename );
72e7876b
SC
614}
615
616// ----------------------------------------------------------------------------
617// wxBitmapDataObject
618// ----------------------------------------------------------------------------
619
620wxBitmapDataObject::wxBitmapDataObject()
621{
622 Init();
623}
624
51d4293d
DS
625wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
626: wxBitmapDataObjectBase( rBitmap )
72e7876b
SC
627{
628 Init();
51d4293d
DS
629
630 if (m_bitmap.Ok())
2a391f87 631 {
6239ee05 632 SetBitmap( rBitmap );
e40298d5 633 }
72e7876b
SC
634}
635
636wxBitmapDataObject::~wxBitmapDataObject()
637{
638 Clear();
639}
640
51d4293d 641void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
72e7876b 642{
2a391f87 643 Clear();
51d4293d
DS
644 wxBitmapDataObjectBase::SetBitmap( rBitmap );
645 if (m_bitmap.Ok())
2a391f87 646 {
968c951f 647 CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
e1673e52
SC
648
649 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
650 CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
651 if ( destination )
6239ee05 652 {
e1673e52
SC
653 CGImageDestinationAddImage( destination, cgImageRef, NULL );
654 CGImageDestinationFinalize( destination );
655 CFRelease( destination );
6239ee05 656 }
e1673e52
SC
657 m_pictHandle = NewHandle(CFDataGetLength(data));
658 if ( m_pictHandle )
6239ee05 659 {
e1673e52 660 memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
6239ee05 661 }
e1673e52
SC
662 CFRelease( data );
663
6239ee05 664 CGImageRelease(cgImageRef);
e40298d5 665 }
2a391f87
SC
666}
667
51d4293d
DS
668void wxBitmapDataObject::Init()
669{
670 m_pictHandle = NULL;
671 m_pictCreated = false;
672}
2a391f87 673
51d4293d 674void wxBitmapDataObject::Clear()
2a391f87 675{
51d4293d 676 if (m_pictHandle != NULL)
e40298d5 677 {
6239ee05 678 DisposeHandle( (Handle) m_pictHandle );
51d4293d 679 m_pictHandle = NULL;
e40298d5 680 }
51d4293d 681 m_pictCreated = false;
72e7876b
SC
682}
683
51d4293d 684bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
72e7876b 685{
51d4293d 686 if (m_pictHandle == NULL)
72e7876b 687 {
51d4293d
DS
688 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
689 return false;
72e7876b 690 }
51d4293d
DS
691
692 if (pBuf == NULL)
693 return false;
694
695 memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
696
697 return true;
72e7876b
SC
698}
699
2a391f87
SC
700size_t wxBitmapDataObject::GetDataSize() const
701{
51d4293d
DS
702 if (m_pictHandle != NULL)
703 return GetHandleSize( (Handle)m_pictHandle );
704 else
705 return 0;
2a391f87
SC
706}
707
6239ee05
SC
708Handle MacCreateDataReferenceHandle(Handle theDataHandle)
709{
710 Handle dataRef = NULL;
711 OSErr err = noErr;
712
713 // Create a data reference handle for our data.
714 err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
715
716 return dataRef;
717}
718
51d4293d 719bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
72e7876b
SC
720{
721 Clear();
51d4293d
DS
722
723 if ((pBuf == NULL) || (nSize == 0))
724 return false;
725
6239ee05
SC
726 Handle picHandle = NewHandle( nSize );
727 memcpy( *picHandle, pBuf, nSize );
728 m_pictHandle = picHandle;
729 CGImageRef cgImageRef = 0;
e1673e52
SC
730
731 CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
732 CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
733 if ( source )
6239ee05 734 {
e1673e52 735 cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
6239ee05 736 }
e1673e52
SC
737 CFRelease( source );
738 CFRelease( data );
739
6239ee05
SC
740 if ( cgImageRef )
741 {
742 m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
743 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
744 // since our context is upside down we dont use CGContextDrawImage
276ee533 745 wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
6239ee05
SC
746 CGImageRelease(cgImageRef);
747 cgImageRef = NULL;
748 }
51d4293d 749
72e7876b
SC
750 return m_bitmap.Ok();
751}
179e085f 752
51d4293d 753#endif