]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/carbon/dataobj.cpp
Fit modeless preferences dialog to its contents too.
[wxWidgets.git] / src / osx / carbon / dataobj.cpp
index 0a4cb0f0be65766be8fb09cd2050e679dd609bbf..e02e880b1a8e594d049abf41049f127672d3b743 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        src/mac/carbon/dataobj.cpp
+// Name:        src/osx/carbon/dataobj.cpp
 // Purpose:     implementation of wxDataObject class
 // Author:      Stefan Csomor
 // Modified by:
 #include "wx/mstream.h"
 #include "wx/metafile.h"
 #include "wx/tokenzr.h"
+#include "wx/filename.h"
 
-#include "wx/osx/uma.h"
+#include "wx/osx/private.h"
 
-#ifdef __DARWIN__
+#if wxOSX_USE_COCOA_OR_CARBON
     #include <QuickTime/QuickTime.h>
 #endif
 
-
 // ----------------------------------------------------------------------------
 // wxDataFormat
 // ----------------------------------------------------------------------------
@@ -121,22 +121,26 @@ void wxDataFormat::SetType( wxDataFormatId dataType )
     switch (m_type)
     {
     case wxDF_TEXT:
-        m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypePlainText );
         break;
 
     case wxDF_UNICODETEXT:
-        m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypeUTF16PlainText );
+        break;
+
+    case wxDF_HTML:
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypeHTML );
         break;
 
     case wxDF_BITMAP:
-        m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypeTIFF );
         break;
     case wxDF_METAFILE:
-        m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypePDF );
         break;
 
     case wxDF_FILENAME:
-        m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
+        m_format = (long) CFStringCreateCopy( NULL, kUTTypeFileURL );
         break;
 
     default:
@@ -158,27 +162,40 @@ void wxDataFormat::SetId( NativeFormat format )
         m_format = 0;
     }
     m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
-    if (  UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") )  ) 
+    if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeHTML ) )
+    {
+        m_type = wxDF_HTML;
+    }
+    if (  UTTypeConformsTo( (CFStringRef)format, kUTTypeUTF16PlainText ) )
     {
         m_type = wxDF_UNICODETEXT;
-    } 
-    else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
+    }
+    else if (  UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF16ExternalPlainText ) )
+    {
+        m_type = wxDF_UNICODETEXT;
+    }
+    else if (  UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF8PlainText ) )
+    {
+        m_type = wxDF_UNICODETEXT;
+    }
+    else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypePlainText ) )
     {
         m_type = wxDF_TEXT;
     }
-    else if (  UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") )  ) 
+    else if (  UTTypeConformsTo( (CFStringRef)format, kUTTypeImage ) )
     {
         m_type = wxDF_BITMAP;
     }
-    else if (  UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") )  ) 
+    else if (  UTTypeConformsTo( (CFStringRef)format, kUTTypePDF ) )
     {
         m_type = wxDF_METAFILE;
     }
-    else if (  UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") )  ) 
+    else if (  UTTypeConformsTo( (CFStringRef)format, kUTTypeFileURL ) ||
+             UTTypeConformsTo( (CFStringRef)format, kPasteboardTypeFileURLPromise))
     {
         m_type = wxDF_FILENAME;
     }
-    else 
+    else
     {
         m_type = wxDF_PRIVATE;
         m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
@@ -253,19 +270,37 @@ void wxDataObject::AddToPasteboard( void * pb, int itemID )
     for (size_t i = 0; i < GetFormatCount(); i++)
     {
         wxDataFormat thisFormat = array[ i ];
-    
-        // add four bytes at the end for data objs like text that 
+
+        // 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 );
+        if ( datasize == wxCONV_FAILED && thisFormat.GetType() == wxDF_TEXT)
+        {
+            // conversion to local text failed, so we must use unicode
+            // if wxDF_UNICODETEXT is already on the 'todo' list, skip this iteration
+            // otherwise force it
+            size_t j = 0;
+            for (j = 0; j < GetFormatCount(); j++)
+            {
+                if ( array[j].GetType() == wxDF_UNICODETEXT )
+                    break;
+            }
+            if ( j < GetFormatCount() )
+                continue;
+            
+            thisFormat.SetType(wxDF_UNICODETEXT);
+            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 ) )
+            if ( GetDataHere( thisFormat, buf ) )
             {
                 int counter = 1 ;
                 if ( thisFormat.GetType() == wxDF_FILENAME )
@@ -286,7 +321,7 @@ void wxDataObject::AddToPasteboard( void * pb, int itemID )
                         counter++;
                         fname = strtok (NULL,"\n");
                     }
-                    
+
                 }
                 else
                 {
@@ -325,24 +360,24 @@ bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataForm
             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;
@@ -359,13 +394,15 @@ bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataForm
 bool wxDataObject::GetFromPasteboard( void * pb )
 {
     PasteboardRef pasteboard = (PasteboardRef) pb;
-    size_t formatcount = GetFormatCount() + 1;
+
+    size_t formatcount = GetFormatCount(wxDataObject::Set);
     wxDataFormat *array = new wxDataFormat[ formatcount ];
-    array[0] = GetPreferredFormat();
-    GetAllFormats( &array[1] );
+    GetAllFormats(array, wxDataObject::Set);
+    
     ItemCount itemCount = 0;
     wxString filenamesPassed;
     bool transferred = false;
+    bool pastelocationset = false;
 
     // we synchronize here once again, so we don't mind which flags get returned
     PasteboardSynchronize( pasteboard );
@@ -391,7 +428,7 @@ bool wxDataObject::GetFromPasteboard( void * pb )
                 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
                 if ( err != noErr )
                     continue;
-                    
+
                 flavorCount = CFArrayGetCount( flavorTypeArray );
 
                 for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
@@ -399,26 +436,42 @@ bool wxDataObject::GetFromPasteboard( void * pb )
                     CFStringRef             flavorType;
                     CFDataRef               flavorData;
                     CFIndex                 flavorDataSize;
-         
+
                     flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
                                                                          flavorIndex );
 
-                    // avoid utf8 being treated closer to plain-text than unicode by forcing a conversion
-                    if ( UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text") ) )
-                    {
-                        flavorType = CFSTR("public.utf16-plain-text");
-                    }
                     wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
+
                     if ( dataFormat == flavorFormat )
                     {
+                        if ( UTTypeConformsTo( (CFStringRef)flavorType, kPasteboardTypeFileURLPromise) )
+                        {
+                            if ( !pastelocationset )
+                            {
+                                wxString tempdir = wxFileName::GetTempDir() + wxFILE_SEP_PATH + "wxtemp.XXXXXX";
+                                char* result = mkdtemp((char*)tempdir.fn_str().data());
+                                
+                                if (!result)
+                                    continue;
+                                
+                                wxCFRef<CFURLRef> dest(CFURLCreateFromFileSystemRepresentation(NULL,(const UInt8*)result,strlen(result),true));
+                                PasteboardSetPasteLocation(pasteboard, dest);
+                                pastelocationset = true;
+                           }
+                        }
+                        else if ( flavorFormat.GetType() != wxDF_PRIVATE )
+                        {
+                            // indicate the expected format for the type, benefiting from native conversions eg utf8 -> utf16
+                            flavorType = (CFStringRef) wxDataFormat( flavorFormat.GetType()).GetFormatId();
+                        }
+                        
                         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
+                                 // 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 );
@@ -437,7 +490,7 @@ bool wxDataObject::GetFromPasteboard( void * pb )
                                 {
                                     memset( buf, 0, flavorDataSize + 4 );
                                     memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
+
                                     if (dataFormat.GetType() == wxDF_TEXT)
                                         wxMacConvertNewlines10To13( (char*) buf );
                                     SetData( flavorFormat, flavorDataSize, buf );
@@ -472,7 +525,7 @@ bool wxDataObject::GetFromPasteboard( void * pb )
                 }
                 CFRelease( flavorTypeArray );
             }
-            if (filenamesPassed.length() > 0)
+            if ( !filenamesPassed.empty() )
             {
                 wxCharBuffer buf = filenamesPassed.fn_str();
                 SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
@@ -486,10 +539,9 @@ bool wxDataObject::GetFromPasteboard( void * pb )
 bool wxDataObject::HasDataInPasteboard( void * pb )
 {
     PasteboardRef pasteboard = (PasteboardRef) pb;
-    size_t formatcount = GetFormatCount() + 1;
+    size_t formatcount = GetFormatCount(wxDataObject::Set);
     wxDataFormat *array = new wxDataFormat[ formatcount ];
-    array[0] = GetPreferredFormat();
-    GetAllFormats( &array[1] );
+    GetAllFormats(array, wxDataObject::Set);
     ItemCount itemCount = 0;
     bool hasData = false;
 
@@ -517,20 +569,20 @@ bool wxDataObject::HasDataInPasteboard( void * pb )
                 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 )
+
+                    if ( dataFormat == flavorFormat ||
+                        (dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT) )
                     {
                         hasData = true;
                     }
@@ -542,6 +594,51 @@ bool wxDataObject::HasDataInPasteboard( void * pb )
     return hasData;
 }
 
+#if wxOSX_USE_COCOA
+
+void wxDataObject::AddSupportedTypes( void* cfarray)
+{
+    size_t nFormats = GetFormatCount(wxDataObject::Set);
+    wxDataFormat *array = new wxDataFormat[nFormats];
+    GetAllFormats(array, wxDataObject::Set);
+    
+    for (size_t i = 0; i < nFormats; i++)
+    {
+        wxDataFormat dataFormat = array[ i ];
+        
+        if ( dataFormat.GetType() == wxDF_UNICODETEXT || dataFormat.GetType() == wxDF_TEXT )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypeUTF16PlainText);
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypePlainText);
+        }
+        else if ( dataFormat.GetType() == wxDF_FILENAME )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypeFileURL);
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kPasteboardTypeFileURLPromise);
+        }
+        else if ( dataFormat.GetType() == wxDF_HTML )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypeHTML);
+        }
+        else if ( dataFormat.GetType() == wxDF_BITMAP )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypeTIFF);
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypePICT);
+        }
+        else if ( dataFormat.GetType() == wxDF_METAFILE )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, kUTTypePDF);
+        }
+        else if ( dataFormat.GetType() == wxDF_PRIVATE )
+        {
+            CFArrayAppendValue((CFMutableArrayRef)cfarray, (CFStringRef) dataFormat.GetFormatId());
+        }
+    }
+    delete[] array;
+}
+
+#endif
+
 // ----------------------------------------------------------------------------
 // wxTextDataObject
 // ----------------------------------------------------------------------------
@@ -550,8 +647,8 @@ bool wxDataObject::HasDataInPasteboard( void * pb )
 void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
                                      wxDataObjectBase::Direction WXUNUSED(dir)) const
 {
-    *formats++ = wxDataFormat( wxDF_TEXT );
-    *formats = wxDataFormat( wxDF_UNICODETEXT );
+    *formats++ = wxDataFormat(wxDF_UNICODETEXT);
+    *formats = wxDataFormat(wxDF_TEXT);
 }
 #endif
 
@@ -632,9 +729,9 @@ wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
 {
     Init();
 
-    if (m_bitmap.Ok())
+    if (m_bitmap.IsOk())
     {
-               SetBitmap( rBitmap );
+        SetBitmap( rBitmap );
     }
 }
 
@@ -647,7 +744,7 @@ void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
 {
     Clear();
     wxBitmapDataObjectBase::SetBitmap( rBitmap );
-    if (m_bitmap.Ok())
+    if (m_bitmap.IsOk())
     {
         CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
 
@@ -738,8 +835,8 @@ bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
     if ( source )
     {
         cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
+        CFRelease( source );
     }
-    CFRelease( source );
     CFRelease( data );
 
     if ( cgImageRef )
@@ -752,7 +849,7 @@ bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
         cgImageRef = NULL;
     }
 
-    return m_bitmap.Ok();
+    return m_bitmap.IsOk();
 }
 
 #endif