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