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