]> git.saurik.com Git - wxWidgets.git/blame - src/osx/carbon/dataobj.cpp
follow up parent chain to properly support modal dialog parents, see #15383
[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
489468fe
SC
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"
fb35086d 28#include "wx/filename.h"
489468fe 29
524c47aa 30#include "wx/osx/private.h"
489468fe 31
afd5d91c 32#if wxOSX_USE_COCOA_OR_CARBON
489468fe
SC
33 #include <QuickTime/QuickTime.h>
34#endif
35
489468fe
SC
36// ----------------------------------------------------------------------------
37// wxDataFormat
38// ----------------------------------------------------------------------------
39
40wxDataFormat::wxDataFormat()
41{
42 m_type = wxDF_INVALID;
43 m_format = 0;
44}
45
46wxDataFormat::wxDataFormat( wxDataFormatId vType )
47{
48 m_format = 0;
49 m_type = wxDF_INVALID;
50 SetType( vType );
51}
52
53wxDataFormat::wxDataFormat( const wxChar *zId )
54{
55 m_format = 0;
56 m_type = wxDF_INVALID;
57 SetId( zId );
58}
59
60wxDataFormat::wxDataFormat( const wxString& rId )
61{
62 m_format = 0;
63 m_type = wxDF_INVALID;
64 SetId( rId );
65}
66
67wxDataFormat::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
77wxDataFormat::wxDataFormat( NativeFormat vFormat )
78{
79 m_format = 0;
80 m_type = wxDF_INVALID;
81 SetId( vFormat );
82}
83
84wxDataFormat::~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
97wxDataFormat& 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
111void 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:
2979ddbe 123 m_format = (long) CFStringCreateCopy( NULL, kUTTypePlainText );
489468fe
SC
124 break;
125
126 case wxDF_UNICODETEXT:
2979ddbe 127 m_format = (long) CFStringCreateCopy( NULL, kUTTypeUTF16PlainText );
489468fe
SC
128 break;
129
b8acf11e 130 case wxDF_HTML:
2979ddbe 131 m_format = (long) CFStringCreateCopy( NULL, kUTTypeHTML );
b8acf11e
RD
132 break;
133
489468fe 134 case wxDF_BITMAP:
2979ddbe 135 m_format = (long) CFStringCreateCopy( NULL, kUTTypeTIFF );
489468fe
SC
136 break;
137 case wxDF_METAFILE:
2979ddbe 138 m_format = (long) CFStringCreateCopy( NULL, kUTTypePDF );
489468fe
SC
139 break;
140
141 case wxDF_FILENAME:
2979ddbe 142 m_format = (long) CFStringCreateCopy( NULL, kUTTypeFileURL );
489468fe
SC
143 break;
144
145 default:
146 wxFAIL_MSG( wxT("invalid data format") );
147 break;
148 }
149}
150
151wxString wxDataFormat::GetId() const
152{
153 return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
154}
155
156void 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);
2979ddbe 164 if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeHTML ) )
b8acf11e
RD
165 {
166 m_type = wxDF_HTML;
167 }
2979ddbe 168 if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeUTF16PlainText ) )
489468fe
SC
169 {
170 m_type = wxDF_UNICODETEXT;
90dad08e 171 }
2979ddbe 172 else if ( UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF16ExternalPlainText ) )
90dad08e
SC
173 {
174 m_type = wxDF_UNICODETEXT;
03647350 175 }
2979ddbe
SC
176 else if ( UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF8PlainText ) )
177 {
178 m_type = wxDF_UNICODETEXT;
179 }
180 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypePlainText ) )
489468fe
SC
181 {
182 m_type = wxDF_TEXT;
183 }
2979ddbe 184 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeImage ) )
489468fe
SC
185 {
186 m_type = wxDF_BITMAP;
187 }
2979ddbe 188 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypePDF ) )
489468fe
SC
189 {
190 m_type = wxDF_METAFILE;
191 }
2979ddbe 192 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeFileURL ) ||
fb35086d 193 UTTypeConformsTo( (CFStringRef)format, kPasteboardTypeFileURLPromise))
489468fe
SC
194 {
195 m_type = wxDF_FILENAME;
196 }
03647350 197 else
489468fe
SC
198 {
199 m_type = wxDF_PRIVATE;
200 m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
201 }
202}
203
204void 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
217bool 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
229wxDataObject::wxDataObject()
230{
231}
232
233bool 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
262void wxDataObject::AddToPasteboard( void * pb, int 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 ];
03647350
VZ
272
273 // add four bytes at the end for data objs like text that
489468fe
SC
274 // have a datasize = strlen but still need a buffer for the
275 // string including trailing zero
03647350 276
489468fe 277 size_t datasize = GetDataSize( thisFormat );
2979ddbe
SC
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
489468fe
SC
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 );
2979ddbe 302 if ( GetDataHere( thisFormat, buf ) )
489468fe
SC
303 {
304 int 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 }
03647350 323
489468fe
SC
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
344bool 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;
03647350 362
489468fe
SC
363 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
364 if ( err != noErr )
365 continue;
03647350 366
489468fe
SC
367 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
368 if ( err != noErr )
369 continue;
03647350 370
489468fe 371 flavorCount = CFArrayGetCount( flavorTypeArray );
03647350 372
489468fe
SC
373 for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
374 {
375 CFStringRef flavorType;
03647350 376
489468fe
SC
377 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
378 flavorIndex );
03647350 379
489468fe
SC
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
393bool wxDataObject::GetFromPasteboard( void * pb )
394{
395 PasteboardRef pasteboard = (PasteboardRef) pb;
d018f3f7
SC
396
397 size_t formatcount = GetFormatCount(wxDataObject::Set);
489468fe 398 wxDataFormat *array = new wxDataFormat[ formatcount ];
d018f3f7
SC
399 GetAllFormats(array, wxDataObject::Set);
400
489468fe
SC
401 ItemCount itemCount = 0;
402 wxString filenamesPassed;
403 bool transferred = false;
3c703700 404 bool pastelocationset = false;
489468fe
SC
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;
03647350 430
489468fe
SC
431 flavorCount = CFArrayGetCount( flavorTypeArray );
432
433 for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
434 {
435 CFStringRef flavorType;
436 CFDataRef flavorData;
437 CFIndex flavorDataSize;
03647350 438
489468fe
SC
439 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
440 flavorIndex );
441
442 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
03647350 443
489468fe
SC
444 if ( dataFormat == flavorFormat )
445 {
fb35086d
SC
446 if ( UTTypeConformsTo( (CFStringRef)flavorType, kPasteboardTypeFileURLPromise) )
447 {
3c703700
SC
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 }
fb35086d 460 }
2979ddbe
SC
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
489468fe
SC
467 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
468 if ( err == noErr )
469 {
470 flavorDataSize = CFDataGetLength( flavorData );
471 if (dataFormat.GetType() == wxDF_FILENAME )
472 {
fb35086d 473 // revert the translation and decomposition to arrive at a proper utf8 string again
489468fe
SC
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 );
03647350 492
489468fe
SC
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 }
6636ef8d 527 if ( !filenamesPassed.empty() )
489468fe
SC
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
538bool wxDataObject::HasDataInPasteboard( void * pb )
539{
540 PasteboardRef pasteboard = (PasteboardRef) pb;
d018f3f7 541 size_t formatcount = GetFormatCount(wxDataObject::Set);
489468fe 542 wxDataFormat *array = new wxDataFormat[ formatcount ];
d018f3f7 543 GetAllFormats(array, wxDataObject::Set);
489468fe
SC
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;
03647350 571
489468fe
SC
572 flavorCount = CFArrayGetCount( flavorTypeArray );
573
574 for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
575 {
576 CFStringRef flavorType;
03647350 577
489468fe
SC
578 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
579 flavorIndex );
580
581 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
03647350
VZ
582
583 if ( dataFormat == flavorFormat ||
c9e98a88 584 (dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT) )
489468fe
SC
585 {
586 hasData = true;
587 }
588 }
589 CFRelease( flavorTypeArray );
590 }
591 }
592 }
593 return hasData;
594}
595
f31c06b3
SC
596#if wxOSX_USE_COCOA
597
598void wxDataObject::AddSupportedTypes( void* cfarray)
599{
d018f3f7
SC
600 size_t nFormats = GetFormatCount(wxDataObject::Set);
601 wxDataFormat *array = new wxDataFormat[nFormats];
602 GetAllFormats(array, wxDataObject::Set);
f31c06b3 603
d018f3f7 604 for (size_t i = 0; i < nFormats; i++)
f31c06b3
SC
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 }
9e1bfb3c
SC
631 else if ( dataFormat.GetType() == wxDF_PRIVATE )
632 {
633 CFArrayAppendValue((CFMutableArrayRef)cfarray, (CFStringRef) dataFormat.GetFormatId());
634 }
f31c06b3
SC
635 }
636 delete[] array;
637}
638
639#endif
640
489468fe
SC
641// ----------------------------------------------------------------------------
642// wxTextDataObject
643// ----------------------------------------------------------------------------
644
645#if wxUSE_UNICODE
646void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
647 wxDataObjectBase::Direction WXUNUSED(dir)) const
648{
468e33ff
SC
649 *formats++ = wxDataFormat(wxDF_UNICODETEXT);
650 *formats = wxDataFormat(wxDF_TEXT);
489468fe
SC
651}
652#endif
653
654// ----------------------------------------------------------------------------
655// wxFileDataObject
656// ----------------------------------------------------------------------------
657
658void 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
671bool 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
686size_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
697bool 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
712void wxFileDataObject::AddFile( const wxString& rFilename )
713{
714 m_filenames.Add( rFilename );
715}
716
717// ----------------------------------------------------------------------------
718// wxBitmapDataObject
719// ----------------------------------------------------------------------------
720
721wxBitmapDataObject::wxBitmapDataObject()
722{
723 Init();
724}
725
726wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
727: wxBitmapDataObjectBase( rBitmap )
728{
729 Init();
730
a1b806b9 731 if (m_bitmap.IsOk())
489468fe 732 {
03647350 733 SetBitmap( rBitmap );
489468fe
SC
734 }
735}
736
737wxBitmapDataObject::~wxBitmapDataObject()
738{
739 Clear();
740}
741
742void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
743{
744 Clear();
745 wxBitmapDataObjectBase::SetBitmap( rBitmap );
a1b806b9 746 if (m_bitmap.IsOk())
489468fe
SC
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
769void wxBitmapDataObject::Init()
770{
771 m_pictHandle = NULL;
772 m_pictCreated = false;
773}
774
775void 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
785bool 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
801size_t wxBitmapDataObject::GetDataSize() const
802{
803 if (m_pictHandle != NULL)
804 return GetHandleSize( (Handle)m_pictHandle );
805 else
806 return 0;
807}
808
809Handle 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
820bool 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);
c9e98a88 837 CFRelease( source );
489468fe 838 }
489468fe
SC
839 CFRelease( data );
840
841 if ( cgImageRef )
842 {
843 m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
844 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
845 // since our context is upside down we dont use CGContextDrawImage
846 wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
847 CGImageRelease(cgImageRef);
848 cgImageRef = NULL;
849 }
850
a1b806b9 851 return m_bitmap.IsOk();
489468fe
SC
852}
853
854#endif