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