]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/dataobj.cpp
fixing string param
[wxWidgets.git] / src / mac / carbon / dataobj.cpp
index bffbbe55e9a450f6a9e66fa0bda252b10b1f9153..cdec68b05d7028d784a85c4fa2fe733d446ead98 100644 (file)
@@ -1,43 +1,38 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        os2/dataobj.cpp
-// Purpose:     implementation of wx[I]DataObject class
-// Author:      David Webster
+// Name:        src/mac/carbon/dataobj.cpp
+// Purpose:     implementation of wxDataObject class
+// Author:      Stefan Csomor
 // Modified by:
 // Created:     10/21/99
 // RCS-ID:      $Id$
-// Copyright:   (c) 1999 David Webster
-// Licence:     wxWindows license
+// Copyright:   (c) 1999 Stefan Csomor
+// Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
-// ============================================================================
-// declarations
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// headers
-// ----------------------------------------------------------------------------
-
-#ifdef __GNUG__
-  #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/defs.h"
 
-#include "wx/log.h"
-#include "wx/dataobj.h"
 #include "wx/mstream.h"
-#include "wx/image.h"
-#include "wx/mac/private.h"
+#include "wx/metafile.h"
+#include "wx/tokenzr.h"
+
+#include "wx/mac/uma.h"
+
+#ifdef __DARWIN__
+    #include <QuickTime/QuickTime.h>
+#endif
 
-// ----------------------------------------------------------------------------
-// functions
-// ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
 // wxDataFormat
@@ -49,75 +44,166 @@ 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 = 'TEXT';
-    else if (m_type == wxDF_BITMAP || m_type == wxDF_METAFILE )
-        m_format = 'PICT';
-    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;
     }
 }
 
-wxDataFormatId wxDataFormat::GetType() const
+// 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
+
+wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
 {
-    return m_type;
+    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 )
 {
-    wxString sRet("");  // TODO: to name of ( m_format ) );
-    return sRet;
+    m_type = dataType;
+    if ( m_format != 0 )
+    {
+        CFRelease( (CFStringRef) m_format );
+        m_format = 0;
+    }
+
+    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;
+    return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
+}
 
-    if (m_format == 'TEXT')
+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 ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
+    {
         m_type = wxDF_TEXT;
-    else
-    if (m_format == 'PICT')
+    }
+    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 = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
+    }
 }
 
-void wxDataFormat::SetId( const wxChar* zId )
+void wxDataFormat::SetId( const wxString& zId )
 {
-    wxString                        tmp(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) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
+}
+
+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 ) );
 }
 
 //-------------------------------------------------------------------------
@@ -128,91 +214,403 @@ 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;
+    }
+
+    return found;
+}
 
-        // found?
-        return n < nFormatCount;
+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 = wxCFStringRef(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;
+}
+
+// ----------------------------------------------------------------------------
+// wxTextDataObject
+// ----------------------------------------------------------------------------
+
+#if wxUSE_UNICODE
+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 true;
+}
+
+size_t wxFileDataObject::GetDataSize() const
+{
+    wxCharBuffer buf;
+    size_t buffLength;
 
-    return nRes + 1;
+    GetFileNames( buf );
+    buffLength = strlen( buf );
+    // terminating 0
+    return buffLength + 1;
 }
 
-bool wxFileDataObject::SetData(
-  size_t                            WXUNUSED(nSize)
-, const void*                       pBuf
-)
+bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
 {
-    m_filenames.Empty();
+    wxString filenames;
 
-    wxString                        sFile( (const char *)pBuf);  /* char, not wxChar */
+#if wxUSE_UNICODE
+    filenames = wxString( (const char*)pBuf, *wxConvFileName );
+#else
+    filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
+#endif
 
-    AddFile(sFile);
+    m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
 
-    return TRUE;
+    return true;
 }
 
-void wxFileDataObject::AddFile(
-  const wxString&                   rFilename
-)
+void wxFileDataObject::AddFile( const wxString& rFilename )
 {
-    m_filenames.Add(rFilename);
+    m_filenames.Add( rFilename );
 }
 
 // ----------------------------------------------------------------------------
@@ -224,14 +622,15 @@ wxBitmapDataObject::wxBitmapDataObject()
     Init();
 }
 
-wxBitmapDataObject::wxBitmapDataObject(
-  const wxBitmap&                   rBitmap
-)
-: wxBitmapDataObjectBase(rBitmap)
+wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
+: wxBitmapDataObjectBase( rBitmap )
 {
     Init();
 
-    DoConvertToPng();
+    if (m_bitmap.Ok())
+    {
+               SetBitmap( rBitmap );
+    }
 }
 
 wxBitmapDataObject::~wxBitmapDataObject()
@@ -239,68 +638,116 @@ wxBitmapDataObject::~wxBitmapDataObject()
     Clear();
 }
 
-void wxBitmapDataObject::SetBitmap(
-  const wxBitmap&                   rBitmap
-)
+void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
 {
-    ClearAll();
-    wxBitmapDataObjectBase::SetBitmap(rBitmap);
-    DoConvertToPng();
+    Clear();
+    wxBitmapDataObjectBase::SetBitmap( rBitmap );
+    if (m_bitmap.Ok())
+    {
+        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);
+    }
 }
 
-bool wxBitmapDataObject::GetDataHere(
-  void*                             pBuf
-) const
+void wxBitmapDataObject::Init()
 {
-    if (!m_pngSize)
+    m_pictHandle = NULL;
+    m_pictCreated = false;
+}
+
+void wxBitmapDataObject::Clear()
+{
+    if (m_pictHandle != NULL)
     {
-        wxFAIL_MSG(wxT("attempt to copy empty bitmap failed"));
-        return FALSE;
+        DisposeHandle( (Handle) m_pictHandle );
+        m_pictHandle = NULL;
     }
-    memcpy(pBuf, m_pngData, m_pngSize);
-    return TRUE;
+    m_pictCreated = false;
 }
 
-bool wxBitmapDataObject::SetData(
-  size_t                            nSize
-, const void*                       pBuf
-)
+bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
 {
-    Clear();
-    m_pngSize = nSize;
-    m_pngData = malloc(m_pngSize);
+    if (m_pictHandle == NULL)
+    {
+        wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
+        return false;
+    }
 
-    memcpy(m_pngData, pBuf, m_pngSize);
+    if (pBuf == NULL)
+        return false;
 
-    wxMemoryInputStream             vMstream((char*)m_pngData, m_pngSize);
-    wxImage                         vImage;
-    wxPNGHandler                    vHandler;
+    memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
 
-    if (!vHandler.LoadFile(&vImage, vMstream))
-    {
-        return FALSE;
-    }
+    return true;
+}
 
-    m_bitmap = vImage.ConvertToBitmap();
-    return m_bitmap.Ok();
+size_t wxBitmapDataObject::GetDataSize() const
+{
+    if (m_pictHandle != NULL)
+        return GetHandleSize( (Handle)m_pictHandle );
+    else
+        return 0;
+}
+
+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;
 }
 
-void wxBitmapDataObject::DoConvertToPng()
+bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
 {
-    if (!m_bitmap.Ok())
-        return;
+    Clear();
 
-    wxImage                         vImage(m_bitmap);
-    wxPNGHandler                    vHandler;
-    wxCountingOutputStream          vCount;
+    if ((pBuf == NULL) || (nSize == 0))
+        return false;
 
-    vHandler.SaveFile(&vImage, vCount);
+    Handle picHandle = NewHandle( nSize );
+    memcpy( *picHandle, pBuf, nSize );
+    m_pictHandle = picHandle;
+    CGImageRef cgImageRef = 0;
 
-    m_pngSize = vCount.GetSize() + 100; // sometimes the size seems to vary ???
-    m_pngData = malloc(m_pngSize);
+    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 );
 
-    wxMemoryOutputStream            vMstream((char*) m_pngData, m_pngSize);
+    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;
+    }
 
-    vHandler.SaveFile(&vImage, vMstream );
+    return m_bitmap.Ok();
 }
 
+#endif