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