]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/dataobj.cpp
set m_isBeingDeleted to true (only) in SendDestroyEvent(); call it as early as possib...
[wxWidgets.git] / src / osx / carbon / dataobj.cpp
CommitLineData
489468fe 1///////////////////////////////////////////////////////////////////////////////
524c47aa 2// Name: src/osx/carbon/dataobj.cpp
489468fe
SC
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
524c47aa 30#include "wx/osx/private.h"
489468fe
SC
31
32#ifdef __DARWIN__
33 #include <QuickTime/QuickTime.h>
34#endif
35
36
37// ----------------------------------------------------------------------------
38// wxDataFormat
39// ----------------------------------------------------------------------------
40
41wxDataFormat::wxDataFormat()
42{
43 m_type = wxDF_INVALID;
44 m_format = 0;
45}
46
47wxDataFormat::wxDataFormat( wxDataFormatId vType )
48{
49 m_format = 0;
50 m_type = wxDF_INVALID;
51 SetType( vType );
52}
53
54wxDataFormat::wxDataFormat( const wxChar *zId )
55{
56 m_format = 0;
57 m_type = wxDF_INVALID;
58 SetId( zId );
59}
60
61wxDataFormat::wxDataFormat( const wxString& rId )
62{
63 m_format = 0;
64 m_type = wxDF_INVALID;
65 SetId( rId );
66}
67
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
78wxDataFormat::wxDataFormat( NativeFormat vFormat )
79{
80 m_format = 0;
81 m_type = wxDF_INVALID;
82 SetId( vFormat );
83}
84
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
112void 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_BITMAP:
132 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
133 break;
134 case wxDF_METAFILE:
135 m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
136 break;
137
138 case wxDF_FILENAME:
139 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
140 break;
141
142 default:
143 wxFAIL_MSG( wxT("invalid data format") );
144 break;
145 }
146}
147
148wxString wxDataFormat::GetId() const
149{
150 return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
151}
152
153void wxDataFormat::SetId( NativeFormat format )
154{
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") ) )
162 {
163 m_type = wxDF_UNICODETEXT;
164 }
165 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
166 {
167 m_type = wxDF_TEXT;
168 }
169 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
170 {
171 m_type = wxDF_BITMAP;
172 }
173 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
174 {
175 m_type = wxDF_METAFILE;
176 }
177 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
178 {
179 m_type = wxDF_FILENAME;
180 }
181 else
182 {
183 m_type = wxDF_PRIVATE;
184 m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
185 }
186}
187
188void wxDataFormat::SetId( const wxString& zId )
189{
190 m_type = wxDF_PRIVATE;
191 m_id = zId;
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 ...
198 m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
199}
200
201bool wxDataFormat::operator==(const wxDataFormat& format) const
202{
203 if (IsStandard() || format.IsStandard())
204 return (format.m_type == m_type);
205 else
206 return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
207}
208
209//-------------------------------------------------------------------------
210// wxDataObject
211//-------------------------------------------------------------------------
212
213wxDataObject::wxDataObject()
214{
215}
216
217bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
218{
219 size_t nFormatCount = GetFormatCount( vDir );
220 bool found = false;
221
222 if (nFormatCount == 1)
223 {
224 found = (rFormat == GetPreferredFormat());
225 }
226 else
227 {
228 wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
229 GetAllFormats( pFormats, vDir );
230
231 for (size_t n = 0; n < nFormatCount; n++)
232 {
233 if (pFormats[n] == rFormat)
234 {
235 found = true;
236 break;
237 }
238 }
239
240 delete [] pFormats;
241 }
242
243 return found;
244}
245
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
d89af57a
SC
406 // avoid utf8 being treated closer to plain-text than unicode by forcing a conversion
407 if ( UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text") ) )
408 {
409 flavorType = CFSTR("public.utf16-plain-text");
410 }
489468fe
SC
411 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
412
413 if ( dataFormat == flavorFormat )
414 {
415 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
416 if ( err == noErr )
417 {
418 flavorDataSize = CFDataGetLength( flavorData );
419 if (dataFormat.GetType() == wxDF_FILENAME )
420 {
421 // revert the translation and decomposition to arrive at a proper utf8 string again
422 CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
423 CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
424 CFRelease( url );
425 CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
426 CFRelease( cfString );
427 CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
428 wxString path = wxCFStringRef(cfMutableString).AsString();
429 if (!path.empty())
430 filenamesPassed += path + wxT("\n");
431 }
432 else
433 {
434 // because some data implementation expect trailing a trailing NUL, we add some headroom
435 void *buf = malloc( flavorDataSize + 4 );
436 if ( buf )
437 {
438 memset( buf, 0, flavorDataSize + 4 );
439 memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
440
441 if (dataFormat.GetType() == wxDF_TEXT)
442 wxMacConvertNewlines10To13( (char*) buf );
443 SetData( flavorFormat, flavorDataSize, buf );
444 transferred = true;
445 free( buf );
446 }
447 }
448 CFRelease (flavorData);
449 }
450 }
451 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
452 {
453 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
454 if ( err == noErr )
455 {
456 flavorDataSize = CFDataGetLength( flavorData );
457 void *asciibuf = malloc( flavorDataSize + 1 );
458 if ( asciibuf )
459 {
460 memset( asciibuf, 0, flavorDataSize + 1 );
461 memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
462 CFRelease (flavorData);
463
464 SetData( wxDF_TEXT, flavorDataSize, asciibuf );
465 transferred = true;
466 free( asciibuf );
467 }
468 else
469 CFRelease (flavorData);
470 }
471 }
472 }
473 CFRelease( flavorTypeArray );
474 }
475 if (filenamesPassed.length() > 0)
476 {
477 wxCharBuffer buf = filenamesPassed.fn_str();
478 SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
479 transferred = true;
480 }
481 }
482 }
483 return transferred;
484}
485
486bool wxDataObject::HasDataInPasteboard( void * pb )
487{
488 PasteboardRef pasteboard = (PasteboardRef) pb;
489 size_t formatcount = GetFormatCount() + 1;
490 wxDataFormat *array = new wxDataFormat[ formatcount ];
491 array[0] = GetPreferredFormat();
492 GetAllFormats( &array[1] );
493 ItemCount itemCount = 0;
494 bool hasData = false;
495
496 // we synchronize here once again, so we don't mind which flags get returned
497 PasteboardSynchronize( pasteboard );
498
499 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
500 if ( err == noErr )
501 {
502 for (size_t i = 0; !hasData && i < formatcount; i++)
503 {
504 // go through the data in our order of preference
505 wxDataFormat dataFormat = array[ i ];
506
507 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
508 {
509 PasteboardItemID itemID = 0;
510 CFArrayRef flavorTypeArray = NULL;
511 CFIndex flavorCount = 0;
512
513 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
514 if ( err != noErr )
515 continue;
516
517 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
518 if ( err != noErr )
519 continue;
520
521 flavorCount = CFArrayGetCount( flavorTypeArray );
522
523 for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
524 {
525 CFStringRef flavorType;
526
527 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
528 flavorIndex );
529
530 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
531
532 if ( dataFormat == flavorFormat ||
533 dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
534 {
535 hasData = true;
536 }
537 }
538 CFRelease( flavorTypeArray );
539 }
540 }
541 }
542 return hasData;
543}
544
545// ----------------------------------------------------------------------------
546// wxTextDataObject
547// ----------------------------------------------------------------------------
548
549#if wxUSE_UNICODE
550void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
551 wxDataObjectBase::Direction WXUNUSED(dir)) const
552{
553 *formats++ = wxDataFormat( wxDF_TEXT );
554 *formats = wxDataFormat( wxDF_UNICODETEXT );
555}
556#endif
557
558// ----------------------------------------------------------------------------
559// wxFileDataObject
560// ----------------------------------------------------------------------------
561
562void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
563{
564 wxString filenames;
565
566 for (size_t i = 0; i < m_filenames.GetCount(); i++)
567 {
568 filenames += m_filenames[i];
569 filenames += wxT('\n');
570 }
571
572 buf = filenames.fn_str();
573}
574
575bool wxFileDataObject::GetDataHere( void *pBuf ) const
576{
577 if (pBuf == NULL)
578 return false;
579
580 wxCharBuffer buf;
581 size_t buffLength;
582
583 GetFileNames( buf );
584 buffLength = strlen( buf );
585 memcpy( pBuf, (const char*)buf, buffLength + 1 );
586
587 return true;
588}
589
590size_t wxFileDataObject::GetDataSize() const
591{
592 wxCharBuffer buf;
593 size_t buffLength;
594
595 GetFileNames( buf );
596 buffLength = strlen( buf );
597 // terminating 0
598 return buffLength + 1;
599}
600
601bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
602{
603 wxString filenames;
604
605#if wxUSE_UNICODE
606 filenames = wxString( (const char*)pBuf, *wxConvFileName );
607#else
608 filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
609#endif
610
611 m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
612
613 return true;
614}
615
616void wxFileDataObject::AddFile( const wxString& rFilename )
617{
618 m_filenames.Add( rFilename );
619}
620
621// ----------------------------------------------------------------------------
622// wxBitmapDataObject
623// ----------------------------------------------------------------------------
624
625wxBitmapDataObject::wxBitmapDataObject()
626{
627 Init();
628}
629
630wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
631: wxBitmapDataObjectBase( rBitmap )
632{
633 Init();
634
635 if (m_bitmap.Ok())
636 {
637 SetBitmap( rBitmap );
638 }
639}
640
641wxBitmapDataObject::~wxBitmapDataObject()
642{
643 Clear();
644}
645
646void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
647{
648 Clear();
649 wxBitmapDataObjectBase::SetBitmap( rBitmap );
650 if (m_bitmap.Ok())
651 {
652 CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
653
654 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
655 CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
656 if ( destination )
657 {
658 CGImageDestinationAddImage( destination, cgImageRef, NULL );
659 CGImageDestinationFinalize( destination );
660 CFRelease( destination );
661 }
662 m_pictHandle = NewHandle(CFDataGetLength(data));
663 if ( m_pictHandle )
664 {
665 memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
666 }
667 CFRelease( data );
668
669 CGImageRelease(cgImageRef);
670 }
671}
672
673void wxBitmapDataObject::Init()
674{
675 m_pictHandle = NULL;
676 m_pictCreated = false;
677}
678
679void wxBitmapDataObject::Clear()
680{
681 if (m_pictHandle != NULL)
682 {
683 DisposeHandle( (Handle) m_pictHandle );
684 m_pictHandle = NULL;
685 }
686 m_pictCreated = false;
687}
688
689bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
690{
691 if (m_pictHandle == NULL)
692 {
693 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
694 return false;
695 }
696
697 if (pBuf == NULL)
698 return false;
699
700 memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
701
702 return true;
703}
704
705size_t wxBitmapDataObject::GetDataSize() const
706{
707 if (m_pictHandle != NULL)
708 return GetHandleSize( (Handle)m_pictHandle );
709 else
710 return 0;
711}
712
713Handle MacCreateDataReferenceHandle(Handle theDataHandle)
714{
715 Handle dataRef = NULL;
716 OSErr err = noErr;
717
718 // Create a data reference handle for our data.
719 err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
720
721 return dataRef;
722}
723
724bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
725{
726 Clear();
727
728 if ((pBuf == NULL) || (nSize == 0))
729 return false;
730
731 Handle picHandle = NewHandle( nSize );
732 memcpy( *picHandle, pBuf, nSize );
733 m_pictHandle = picHandle;
734 CGImageRef cgImageRef = 0;
735
736 CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
737 CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
738 if ( source )
739 {
740 cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
741 }
742 CFRelease( source );
743 CFRelease( data );
744
745 if ( cgImageRef )
746 {
747 m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
748 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
749 // since our context is upside down we dont use CGContextDrawImage
750 wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
751 CGImageRelease(cgImageRef);
752 cgImageRef = NULL;
753 }
754
755 return m_bitmap.Ok();
756}
757
758#endif