+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;
+}
+