X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/71cc158eaabaeac51b6219a9df8eac06b96c794b..2078e2f129c323dd1b01aeef5061f787f8475386:/src/mac/carbon/dataobj.cpp diff --git a/src/mac/carbon/dataobj.cpp b/src/mac/carbon/dataobj.cpp index 4865f6f5ac..e7070a1e44 100644 --- a/src/mac/carbon/dataobj.cpp +++ b/src/mac/carbon/dataobj.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: mac/dataobj.cpp +// Name: src/mac/carbon/dataobj.cpp // Purpose: implementation of wxDataObject class // Author: Stefan Csomor // Modified by: @@ -9,36 +9,30 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -// ============================================================================ -// declarations -// ============================================================================ - -// ---------------------------------------------------------------------------- -// headers -// ---------------------------------------------------------------------------- - -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "dataobj.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#if wxUSE_DATAOBJ + +#include "wx/dataobj.h" + #ifndef WX_PRECOMP -#include "wx/intl.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/dcmemory.h" + #include "wx/image.h" #endif -#include "wx/log.h" -#include "wx/dataobj.h" #include "wx/mstream.h" -#include "wx/image.h" #include "wx/metafile.h" -#include "wx/mac/private.h" -#include +#include "wx/tokenzr.h" + +#include "wx/mac/uma.h" + +#ifdef __DARWIN__ + #include +#endif -// ---------------------------------------------------------------------------- -// functions -// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // wxDataFormat @@ -50,79 +44,169 @@ wxDataFormat::wxDataFormat() m_format = 0; } -wxDataFormat::wxDataFormat( wxDataFormatId vType ) +wxDataFormat::wxDataFormat( wxDataFormatId vType ) { - SetType(vType); + m_format = 0; + m_type = wxDF_INVALID; + SetType( vType ); } -wxDataFormat::wxDataFormat( const wxChar* zId) +wxDataFormat::wxDataFormat( const wxChar *zId ) { - SetId(zId); + m_format = 0; + m_type = wxDF_INVALID; + SetId( zId ); } -wxDataFormat::wxDataFormat( const wxString& rId) +wxDataFormat::wxDataFormat( const wxString& rId ) { - SetId(rId); + m_format = 0; + m_type = wxDF_INVALID; + SetId( rId ); } -wxDataFormat::wxDataFormat( NativeFormat vFormat) +wxDataFormat::wxDataFormat(const wxDataFormat& rFormat) { - SetId(vFormat); + if ( rFormat.m_format ) + m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format); + else + m_format = 0; + m_type = rFormat.m_type; + m_id = rFormat.m_id; } -void wxDataFormat::SetType( wxDataFormatId Type ) +wxDataFormat::wxDataFormat( NativeFormat vFormat ) { - m_type = Type; + m_format = 0; + m_type = wxDF_INVALID; + SetId( vFormat ); +} - if (m_type == wxDF_TEXT ) - m_format = kScrapFlavorTypeText; - else if (m_type == wxDF_UNICODETEXT ) - m_format = kScrapFlavorTypeUnicode ; - else if (m_type == wxDF_BITMAP || m_type == wxDF_METAFILE ) - m_format = kScrapFlavorTypePicture; - else if (m_type == wxDF_FILENAME) - m_format = kDragFlavorTypeHFS ; - else +wxDataFormat::~wxDataFormat() +{ + if ( m_format != 0 ) { - wxFAIL_MSG( wxT("invalid dataformat") ); + CFRelease( (CFStringRef) m_format ); + m_format = 0; + } +} + +// in order to be correct for 10.3 we restrict to the available types there +// http://developer.apple.com/qa/qa2005/qa1406.html +// TODO : Use UTCoreTypes.h constants once we support 10.4+ only - // this is '????' but it can't be used in the code because ??' is - // parsed as a trigraph! - m_format = 0x3f3f3f3f; +wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat) +{ + if ( m_format != 0 ) + { + CFRelease( (CFStringRef) m_format ); + m_format = 0; } + if ( rFormat.m_format ) + m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format); + m_type = rFormat.m_type; + m_id = rFormat.m_id; + return *this; } -wxString wxDataFormat::GetId() const +void wxDataFormat::SetType( wxDataFormatId dataType ) { - // note that m_format is not a pointer to string, it *is* itself a 4 - // character string - char text[5] ; - strncpy( text , (char*) &m_format , 4 ) ; - text[4] = 0 ; + m_type = dataType; + if ( m_format != 0 ) + { + CFRelease( (CFStringRef) m_format ); + m_format = 0; + } - return wxString::FromAscii( text ) ; + switch (m_type) + { + case wxDF_TEXT: + m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") ); + break; + + case wxDF_UNICODETEXT: + m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") ); + break; + + case wxDF_BITMAP: + m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") ); + break; + case wxDF_METAFILE: + m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") ); + break; + + case wxDF_FILENAME: + m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") ); + break; + + default: + wxFAIL_MSG( wxT("invalid data format") ); + break; + } } -void wxDataFormat::SetId( NativeFormat format ) +wxString wxDataFormat::GetId() const { - m_format = format; + wxCHECK_MSG( !IsStandard(), wxEmptyString, + wxT("name of predefined format cannot be retrieved") ); - if (m_format == kScrapFlavorTypeText) - m_type = wxDF_TEXT; - else if (m_format == kScrapFlavorTypeUnicode ) + return m_id; +} + +void wxDataFormat::SetId( NativeFormat format ) +{ + if ( m_format != 0 ) + { + CFRelease( (CFStringRef) m_format ); + m_format = 0; + } + m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format); + if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) ) + { m_type = wxDF_UNICODETEXT; - else if (m_format == kScrapFlavorTypePicture) + } + else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) ) + { + m_type = wxDF_TEXT; + } + else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) ) + { m_type = wxDF_BITMAP; - else if (m_format == kDragFlavorTypeHFS ) + } + else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) ) + { + m_type = wxDF_METAFILE; + } + else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) ) + { m_type = wxDF_FILENAME; - else + } + else + { m_type = wxDF_PRIVATE; + m_id = wxMacCFStringHolder( (CFStringRef) CFRetain((CFStringRef) format )).AsString(); + } } -void wxDataFormat::SetId( const wxChar* zId ) +void wxDataFormat::SetId( const wxString& zId ) { m_type = wxDF_PRIVATE; - m_format = 0;// TODO: get the format gdk_atom_intern( wxMBSTRINGCAST tmp.mbc_str(), FALSE ); + m_id = zId; + if ( m_format != 0 ) + { + CFRelease( (CFStringRef) m_format ); + m_format = 0; + } + // since it is private, no need to conform to anything ... + m_format = (long) wxMacCFStringHolder(m_id).Detach(); +} + +bool wxDataFormat::operator==(const wxDataFormat& format) const +{ + if (IsStandard() || format.IsStandard()) + return (format.m_type == m_type); + else + return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) ); } //------------------------------------------------------------------------- @@ -133,37 +217,327 @@ wxDataObject::wxDataObject() { } -bool wxDataObject::IsSupportedFormat( - const wxDataFormat& rFormat -, Direction vDir -) const +bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const { - size_t nFormatCount = GetFormatCount(vDir); + size_t nFormatCount = GetFormatCount( vDir ); + bool found = false; if (nFormatCount == 1) { - return rFormat == GetPreferredFormat(); + found = (rFormat == GetPreferredFormat()); } else { - wxDataFormat* pFormats = new wxDataFormat[nFormatCount]; - GetAllFormats( pFormats - ,vDir - ); + wxDataFormat *pFormats = new wxDataFormat[nFormatCount]; + GetAllFormats( pFormats, vDir ); - size_t n; - - for (n = 0; n < nFormatCount; n++) + for (size_t n = 0; n < nFormatCount; n++) { if (pFormats[n] == rFormat) + { + found = true; break; + } } delete [] pFormats; + } - // found? - return n < nFormatCount; + return found; +} + +void wxDataObject::AddToPasteboard( void * pb, int itemID ) +{ + PasteboardRef pasteboard = (PasteboardRef) pb; + // get formats from wxDataObjects + wxDataFormat *array = new wxDataFormat[ GetFormatCount() ]; + GetAllFormats( array ); + + for (size_t i = 0; i < GetFormatCount(); i++) + { + wxDataFormat thisFormat = array[ i ]; + + // add four bytes at the end for data objs like text that + // have a datasize = strlen but still need a buffer for the + // string including trailing zero + + size_t datasize = GetDataSize( thisFormat ); + size_t sz = datasize + 4; + void* buf = malloc( sz ); + if ( buf != NULL ) + { + // empty the buffer because in some case GetDataHere does not fill buf + memset( buf, 0, sz ); + if ( GetDataHere( array[ i ], buf ) ) + { + int counter = 1 ; + if ( thisFormat.GetType() == wxDF_FILENAME ) + { + // the data is D-normalized UTF8 strings of filenames delimited with \n + char *fname = strtok((char*) buf,"\n"); + while (fname != NULL) + { + // translate the filepath into a fileurl and put that into the pasteobard + CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false); + CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false); + CFRelease(path); + CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true); + CFRelease(url); + PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter, + (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags); + CFRelease( data ); + counter++; + fname = strtok (NULL,"\n"); + } + + } + else + { + CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize ); + if ( thisFormat.GetType() == wxDF_TEXT ) + PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID, + CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags); + else + PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID, + (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags); + CFRelease( data ); + } + } + free( buf ); + } + } + + delete [] array; +} + +bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat ) +{ + PasteboardRef pasteboard = (PasteboardRef) pb; + bool hasData = false; + OSStatus err = noErr; + ItemCount itemCount; + + // we synchronize here once again, so we don't mind which flags get returned + PasteboardSynchronize( pasteboard ); + + err = PasteboardGetItemCount( pasteboard, &itemCount ); + if ( err == noErr ) + { + for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ ) + { + PasteboardItemID itemID; + CFArrayRef flavorTypeArray; + CFIndex flavorCount; + + err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ); + if ( err != noErr ) + continue; + + err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray ); + if ( err != noErr ) + continue; + + flavorCount = CFArrayGetCount( flavorTypeArray ); + + for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ ) + { + CFStringRef flavorType; + + flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray, + flavorIndex ); + + wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType ); + if ( dataFormat == flavorFormat ) + hasData = true; + else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT ) + hasData = true; + } + CFRelease (flavorTypeArray); + } + } + + return hasData; +} + +bool wxDataObject::GetFromPasteboard( void * pb ) +{ + PasteboardRef pasteboard = (PasteboardRef) pb; + size_t formatcount = GetFormatCount() + 1; + wxDataFormat *array = new wxDataFormat[ formatcount ]; + array[0] = GetPreferredFormat(); + GetAllFormats( &array[1] ); + ItemCount itemCount = 0; + wxString filenamesPassed; + bool transferred = false; + + // we synchronize here once again, so we don't mind which flags get returned + PasteboardSynchronize( pasteboard ); + + OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount ); + if ( err == noErr ) + { + for (size_t i = 0; !transferred && i < formatcount; i++) + { + // go through the data in our order of preference + wxDataFormat dataFormat = array[ i ]; + + for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ ) + { + PasteboardItemID itemID = 0; + CFArrayRef flavorTypeArray = NULL; + CFIndex flavorCount = 0; + + err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ); + if ( err != noErr ) + continue; + + err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray ); + if ( err != noErr ) + continue; + + flavorCount = CFArrayGetCount( flavorTypeArray ); + + for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ ) + { + CFStringRef flavorType; + CFDataRef flavorData; + CFIndex flavorDataSize; + + flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray, + flavorIndex ); + + wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType ); + + if ( dataFormat == flavorFormat ) + { + err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData ); + if ( err == noErr ) + { + flavorDataSize = CFDataGetLength( flavorData ); + if (dataFormat.GetType() == wxDF_FILENAME ) + { + // revert the translation and decomposition to arrive at a proper utf8 string again + CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL ); + CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle ); + CFRelease( url ); + CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString); + CFRelease( cfString ); + CFStringNormalize(cfMutableString,kCFStringNormalizationFormC); + wxString path = wxMacCFStringHolder(cfMutableString).AsString(); + if (!path.empty()) + filenamesPassed += path + wxT("\n"); + } + else + { + // because some data implementation expect trailing a trailing NUL, we add some headroom + void *buf = malloc( flavorDataSize + 4 ); + if ( buf ) + { + memset( buf, 0, flavorDataSize + 4 ); + memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize ); + + if (dataFormat.GetType() == wxDF_TEXT) + wxMacConvertNewlines10To13( (char*) buf ); + SetData( flavorFormat, flavorDataSize, buf ); + transferred = true; + free( buf ); + } + } + CFRelease (flavorData); + } + } + else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT ) + { + err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData ); + if ( err == noErr ) + { + flavorDataSize = CFDataGetLength( flavorData ); + void *asciibuf = malloc( flavorDataSize + 1 ); + if ( asciibuf ) + { + memset( asciibuf, 0, flavorDataSize + 1 ); + memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize ); + CFRelease (flavorData); + + SetData( wxDF_TEXT, flavorDataSize, asciibuf ); + transferred = true; + free( asciibuf ); + } + else + CFRelease (flavorData); + } + } + } + CFRelease( flavorTypeArray ); + } + if (filenamesPassed.length() > 0) + { + wxCharBuffer buf = filenamesPassed.fn_str(); + SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf ); + transferred = true; + } + } } + return transferred; +} + +bool wxDataObject::HasDataInPasteboard( void * pb ) +{ + PasteboardRef pasteboard = (PasteboardRef) pb; + size_t formatcount = GetFormatCount() + 1; + wxDataFormat *array = new wxDataFormat[ formatcount ]; + array[0] = GetPreferredFormat(); + GetAllFormats( &array[1] ); + ItemCount itemCount = 0; + bool hasData = false; + + // we synchronize here once again, so we don't mind which flags get returned + PasteboardSynchronize( pasteboard ); + + OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount ); + if ( err == noErr ) + { + for (size_t i = 0; !hasData && i < formatcount; i++) + { + // go through the data in our order of preference + wxDataFormat dataFormat = array[ i ]; + + for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ ) + { + PasteboardItemID itemID = 0; + CFArrayRef flavorTypeArray = NULL; + CFIndex flavorCount = 0; + + err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ); + if ( err != noErr ) + continue; + + err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray ); + if ( err != noErr ) + continue; + + flavorCount = CFArrayGetCount( flavorTypeArray ); + + for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ ) + { + CFStringRef flavorType; + + flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray, + flavorIndex ); + + wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType ); + + if ( dataFormat == flavorFormat || + dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT ) + { + hasData = true; + } + } + CFRelease( flavorTypeArray ); + } + } + } + return hasData; } // ---------------------------------------------------------------------------- @@ -171,67 +545,75 @@ bool wxDataObject::IsSupportedFormat( // ---------------------------------------------------------------------------- #if wxUSE_UNICODE -void wxTextDataObject::GetAllFormats(wxDataFormat *formats, wxDataObjectBase::Direction dir) const +void wxTextDataObject::GetAllFormats(wxDataFormat *formats, + wxDataObjectBase::Direction WXUNUSED(dir)) const { *formats++ = wxDataFormat( wxDF_TEXT ); *formats = wxDataFormat( wxDF_UNICODETEXT ); } - #endif // ---------------------------------------------------------------------------- // wxFileDataObject // ---------------------------------------------------------------------------- -bool wxFileDataObject::GetDataHere( - void* pBuf -) const +void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const { - wxString sFilenames; + wxString filenames; for (size_t i = 0; i < m_filenames.GetCount(); i++) { - sFilenames += m_filenames[i]; - sFilenames += (wxChar)0; + filenames += m_filenames[i]; + filenames += wxT('\n'); } - memcpy(pBuf, sFilenames.mbc_str(), sFilenames.Len() + 1); - return TRUE; + buf = filenames.fn_str(); } -size_t wxFileDataObject::GetDataSize() const +bool wxFileDataObject::GetDataHere( void *pBuf ) const { - size_t nRes = 0; + if (pBuf == NULL) + return false; - for (size_t i = 0; i < m_filenames.GetCount(); i++) - { - nRes += m_filenames[i].Len(); - nRes += 1; - } + wxCharBuffer buf; + size_t buffLength; + + GetFileNames( buf ); + buffLength = strlen( buf ); + memcpy( pBuf, (const char*)buf, buffLength + 1 ); - return nRes + 1; + return true; } -bool wxFileDataObject::SetData( - size_t WXUNUSED(nSize) -, const void* pBuf -) +size_t wxFileDataObject::GetDataSize() const { - m_filenames.Empty(); + wxCharBuffer buf; + size_t buffLength; + + GetFileNames( buf ); + buffLength = strlen( buf ); + // terminating 0 + return buffLength + 1; +} - // only add if this is not an empty string - // we can therefore clear the list by just setting an empty string - if ( (*(char*)pBuf) != 0 ) - AddFile(wxString::FromAscii((char*)pBuf)); +bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf ) +{ + wxString filenames; - return TRUE; +#if wxUSE_UNICODE + filenames = wxString( (const char*)pBuf, *wxConvFileName ); +#else + filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf))); +#endif + + m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK ); + + return true; } -void wxFileDataObject::AddFile( - const wxString& rFilename -) +void wxFileDataObject::AddFile( const wxString& rFilename ) { - m_filenames.Add(rFilename); + m_filenames.Add( rFilename ); } // ---------------------------------------------------------------------------- @@ -243,16 +625,14 @@ wxBitmapDataObject::wxBitmapDataObject() Init(); } -wxBitmapDataObject::wxBitmapDataObject( - const wxBitmap& rBitmap -) -: wxBitmapDataObjectBase(rBitmap) +wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap ) +: wxBitmapDataObjectBase( rBitmap ) { Init(); - if ( m_bitmap.Ok() ) + + if (m_bitmap.Ok()) { - m_pictHandle = wxMacCreatePicHandle( rBitmap ) ; - m_pictCreated = true ; + SetBitmap( rBitmap ); } } @@ -261,72 +641,116 @@ wxBitmapDataObject::~wxBitmapDataObject() Clear(); } -void wxBitmapDataObject::SetBitmap( - const wxBitmap& rBitmap -) +void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap ) { Clear(); - wxBitmapDataObjectBase::SetBitmap(rBitmap); - if ( m_bitmap.Ok() ) + wxBitmapDataObjectBase::SetBitmap( rBitmap ); + if (m_bitmap.Ok()) { - m_pictHandle = wxMacCreatePicHandle( rBitmap ) ; - m_pictCreated = true ; + CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage(); + + CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); + CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL ); + if ( destination ) + { + CGImageDestinationAddImage( destination, cgImageRef, NULL ); + CGImageDestinationFinalize( destination ); + CFRelease( destination ); + } + m_pictHandle = NewHandle(CFDataGetLength(data)); + if ( m_pictHandle ) + { + memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) ); + } + CFRelease( data ); + + CGImageRelease(cgImageRef); } } -void wxBitmapDataObject::Init() -{ - m_pictHandle = NULL ; - m_pictCreated = false ; -} +void wxBitmapDataObject::Init() +{ + m_pictHandle = NULL; + m_pictCreated = false; +} -void wxBitmapDataObject::Clear() +void wxBitmapDataObject::Clear() { - if ( m_pictCreated && m_pictHandle ) + if (m_pictHandle != NULL) { - KillPicture( (PicHandle) m_pictHandle ) ; + DisposeHandle( (Handle) m_pictHandle ); + m_pictHandle = NULL; } - m_pictHandle = NULL ; + m_pictCreated = false; } -bool wxBitmapDataObject::GetDataHere( - void* pBuf -) const +bool wxBitmapDataObject::GetDataHere( void *pBuf ) const { - if (!m_pictHandle) + if (m_pictHandle == NULL) { - wxFAIL_MSG(wxT("attempt to copy empty bitmap failed")); - return FALSE; + wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") ); + return false; } - memcpy(pBuf, *(Handle)m_pictHandle, GetHandleSize((Handle)m_pictHandle)); - return TRUE; + + if (pBuf == NULL) + return false; + + memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) ); + + return true; } size_t wxBitmapDataObject::GetDataSize() const { - return GetHandleSize((Handle)m_pictHandle) ; + if (m_pictHandle != NULL) + return GetHandleSize( (Handle)m_pictHandle ); + else + return 0; } -bool wxBitmapDataObject::SetData( - size_t nSize -, const void* pBuf -) +Handle MacCreateDataReferenceHandle(Handle theDataHandle) +{ + Handle dataRef = NULL; + OSErr err = noErr; + + // Create a data reference handle for our data. + err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle)); + + return dataRef; +} + +bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf ) { Clear(); - PicHandle picHandle = (PicHandle) NewHandle( nSize ) ; - memcpy( *picHandle , pBuf , nSize ) ; - m_pictHandle = picHandle ; - // ownership is transferred to the bitmap - m_pictCreated = false ; - Rect frame = (**picHandle).picFrame ; - - wxMetafile mf ; - mf.SetHMETAFILE( (WXHMETAFILE) m_pictHandle ) ; - wxMemoryDC mdc ; - m_bitmap.Create( frame.right - frame.left ,frame.bottom - frame.top ) ; - mdc.SelectObject(m_bitmap ) ; - mf.Play( &mdc ) ; - mdc.SelectObject( wxNullBitmap ) ; - + + if ((pBuf == NULL) || (nSize == 0)) + return false; + + Handle picHandle = NewHandle( nSize ); + memcpy( *picHandle, pBuf, nSize ); + m_pictHandle = picHandle; + CGImageRef cgImageRef = 0; + + CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull); + CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL ); + if ( source ) + { + cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL); + } + CFRelease( source ); + CFRelease( data ); + + if ( cgImageRef ) + { + m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) ); + CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) ); + // since our context is upside down we dont use CGContextDrawImage + wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ; + CGImageRelease(cgImageRef); + cgImageRef = NULL; + } + return m_bitmap.Ok(); } + +#endif