Ken Thomases : winemac: Add support for CF_HDROP clipboard format, mapped to/from Cocoa's NSFilenamesPboardType.

Alexandre Julliard julliard at winehq.org
Thu Mar 14 14:55:05 CDT 2013


Module: wine
Branch: master
Commit: bff19b173904392e6c64fdfa78df5695e591d41e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=bff19b173904392e6c64fdfa78df5695e591d41e

Author: Ken Thomases <ken at codeweavers.com>
Date:   Wed Mar 13 16:52:50 2013 -0500

winemac: Add support for CF_HDROP clipboard format, mapped to/from Cocoa's NSFilenamesPboardType.

---

 dlls/winemac.drv/clipboard.c |  218 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 218 insertions(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c
index 5829ca2..2219df6 100644
--- a/dlls/winemac.drv/clipboard.c
+++ b/dlls/winemac.drv/clipboard.c
@@ -26,6 +26,8 @@
 
 #include "macdrv.h"
 #include "winuser.h"
+#include "shellapi.h"
+#include "shlobj.h"
 #include "wine/list.h"
 #include "wine/server.h"
 #include "wine/unicode.h"
@@ -70,6 +72,7 @@ typedef struct
 static HANDLE import_clipboard_data(CFDataRef data);
 static HANDLE import_bmp_to_bitmap(CFDataRef data);
 static HANDLE import_bmp_to_dib(CFDataRef data);
+static HANDLE import_nsfilenames_to_hdrop(CFDataRef data);
 static HANDLE import_oemtext_to_text(CFDataRef data);
 static HANDLE import_oemtext_to_unicodetext(CFDataRef data);
 static HANDLE import_text_to_oemtext(CFDataRef data);
@@ -83,6 +86,7 @@ static HANDLE import_utf8_to_unicodetext(CFDataRef data);
 static CFDataRef export_clipboard_data(HANDLE data);
 static CFDataRef export_bitmap_to_bmp(HANDLE data);
 static CFDataRef export_dib_to_bmp(HANDLE data);
+static CFDataRef export_hdrop_to_filenames(HANDLE data);
 static CFDataRef export_oemtext_to_utf8(HANDLE data);
 static CFDataRef export_text_to_utf8(HANDLE data);
 static CFDataRef export_unicodetext_to_utf8(HANDLE data);
@@ -181,6 +185,9 @@ static const struct
 
     { CF_BITMAP,            CFSTR("org.winehq.builtin.bitmap"),             import_bmp_to_bitmap,           export_bitmap_to_bmp,       FALSE },
     { CF_BITMAP,            CFSTR("com.microsoft.bmp"),                     import_bmp_to_bitmap,           export_bitmap_to_bmp,       TRUE },
+
+    { CF_HDROP,             CFSTR("org.winehq.builtin.hdrop"),              import_clipboard_data,          export_clipboard_data,      FALSE },
+    { CF_HDROP,             CFSTR("NSFilenamesPboardType"),                 import_nsfilenames_to_hdrop,    export_hdrop_to_filenames,  TRUE },
 };
 
 static const WCHAR wszRichTextFormat[] = {'R','i','c','h',' ','T','e','x','t',' ','F','o','r','m','a','t',0};
@@ -671,6 +678,124 @@ static HANDLE import_bmp_to_dib(CFDataRef data)
 
 
 /**************************************************************************
+ *              import_nsfilenames_to_hdrop
+ *
+ *  Import NSFilenamesPboardType data, converting the property-list-
+ *  serialized array of path strings to CF_HDROP.
+ */
+static HANDLE import_nsfilenames_to_hdrop(CFDataRef data)
+{
+    HDROP hdrop = NULL;
+    CFArrayRef names;
+    CFIndex count, i;
+    size_t len;
+    char *buffer = NULL;
+    WCHAR **paths = NULL;
+    DROPFILES* dropfiles;
+    UniChar* p;
+
+    TRACE("data %s\n", debugstr_cf(data));
+
+    names = (CFArrayRef)CFPropertyListCreateWithData(NULL, data, kCFPropertyListImmutable,
+                                                     NULL, NULL);
+    if (!names || CFGetTypeID(names) != CFArrayGetTypeID())
+    {
+        WARN("failed to interpret data as a CFArray\n");
+        goto done;
+    }
+
+    count = CFArrayGetCount(names);
+
+    len = 0;
+    for (i = 0; i < count; i++)
+    {
+        CFIndex this_len;
+        CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
+        TRACE("    %s\n", debugstr_cf(name));
+        if (CFGetTypeID(name) != CFStringGetTypeID())
+        {
+            WARN("non-string in array\n");
+            goto done;
+        }
+
+        this_len = CFStringGetMaximumSizeOfFileSystemRepresentation(name);
+        if (this_len > len)
+            len = this_len;
+    }
+
+    buffer = HeapAlloc(GetProcessHeap(), 0, len);
+    if (!buffer)
+    {
+        WARN("failed to allocate buffer for file-system representations\n");
+        goto done;
+    }
+
+    paths = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(paths[0]));
+    if (!paths)
+    {
+        WARN("failed to allocate array of DOS paths\n");
+        goto done;
+    }
+
+    for (i = 0; i < count; i++)
+    {
+        CFStringRef name = (CFStringRef)CFArrayGetValueAtIndex(names, i);
+        if (!CFStringGetFileSystemRepresentation(name, buffer, len))
+        {
+            WARN("failed to get file-system representation for %s\n", debugstr_cf(name));
+            goto done;
+        }
+        paths[i] = wine_get_dos_file_name(buffer);
+        if (!paths[i])
+        {
+            WARN("failed to get DOS path for %s\n", debugstr_a(buffer));
+            goto done;
+        }
+    }
+
+    len = 1; /* for the terminating null */
+    for (i = 0; i < count; i++)
+        len += strlenW(paths[i]) + 1;
+
+    hdrop = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(*dropfiles) + len * sizeof(WCHAR));
+    if (!hdrop || !(dropfiles = GlobalLock(hdrop)))
+    {
+        WARN("failed to allocate HDROP\n");
+        GlobalFree(hdrop);
+        hdrop = NULL;
+        goto done;
+    }
+
+    dropfiles->pFiles   = sizeof(*dropfiles);
+    dropfiles->pt.x     = 0;
+    dropfiles->pt.y     = 0;
+    dropfiles->fNC      = FALSE;
+    dropfiles->fWide    = TRUE;
+
+    p = (WCHAR*)(dropfiles + 1);
+    for (i = 0; i < count; i++)
+    {
+        strcpyW(p, paths[i]);
+        p += strlenW(p) + 1;
+    }
+    *p = 0;
+
+    GlobalUnlock(hdrop);
+
+done:
+    if (paths)
+    {
+        for (i = 0; i < count; i++)
+            HeapFree(GetProcessHeap(), 0, paths[i]);
+        HeapFree(GetProcessHeap(), 0, paths);
+    }
+    HeapFree(GetProcessHeap(), 0, buffer);
+    if (names) CFRelease(names);
+    return hdrop;
+}
+
+
+/**************************************************************************
  *              import_oemtext_to_text
  *
  *  Import CF_OEMTEXT data, converting the string to CF_TEXT.
@@ -924,6 +1049,99 @@ static CFDataRef export_dib_to_bmp(HANDLE data)
 
 
 /**************************************************************************
+ *              export_hdrop_to_filenames
+ *
+ *  Export CF_HDROP to NSFilenamesPboardType data, which is a CFArray of
+ *  CFStrings (holding Unix paths) which is serialized as a property list.
+ */
+static CFDataRef export_hdrop_to_filenames(HANDLE data)
+{
+    CFDataRef ret = NULL;
+    DROPFILES *dropfiles;
+    CFMutableArrayRef filenames = NULL;
+    void *p;
+    WCHAR *buffer = NULL;
+    size_t buffer_len = 0;
+
+    TRACE("data %p\n", data);
+
+    if (!(dropfiles = GlobalLock(data)))
+    {
+        WARN("failed to lock data %p\n", data);
+        goto done;
+    }
+
+    filenames = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+    if (!filenames)
+    {
+        WARN("failed to create filenames array\n");
+        goto done;
+    }
+
+    p = (char*)dropfiles + dropfiles->pFiles;
+    while (dropfiles->fWide ? *(WCHAR*)p : *(char*)p)
+    {
+        char *unixname;
+        CFStringRef filename;
+
+        TRACE("    %s\n", dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
+
+        if (dropfiles->fWide)
+            unixname = wine_get_unix_file_name(p);
+        else
+        {
+            int len = MultiByteToWideChar(CP_ACP, 0, p, -1, NULL, 0);
+            if (len)
+            {
+                if (len > buffer_len)
+                {
+                    HeapFree(GetProcessHeap(), 0, buffer);
+                    buffer_len = len * 2;
+                    buffer = HeapAlloc(GetProcessHeap(), 0, buffer_len * sizeof(*buffer));
+                }
+
+                MultiByteToWideChar(CP_ACP, 0, p, -1, buffer, buffer_len);
+                unixname = wine_get_unix_file_name(buffer);
+            }
+            else
+                unixname = NULL;
+        }
+        if (!unixname)
+        {
+            WARN("failed to convert DOS path to Unix: %s\n",
+                 dropfiles->fWide ? debugstr_w(p) : debugstr_a(p));
+            goto done;
+        }
+
+        if (dropfiles->fWide)
+            p = (WCHAR*)p + strlenW(p) + 1;
+        else
+            p = (char*)p + strlen(p) + 1;
+
+        filename = CFStringCreateWithFileSystemRepresentation(NULL, unixname);
+        HeapFree(GetProcessHeap(), 0, unixname);
+        if (!filename)
+        {
+            WARN("failed to create CFString from Unix path %s\n", debugstr_a(unixname));
+            goto done;
+        }
+
+        CFArrayAppendValue(filenames, filename);
+        CFRelease(filename);
+    }
+
+    ret = CFPropertyListCreateData(NULL, filenames, kCFPropertyListXMLFormat_v1_0, 0, NULL);
+
+done:
+    HeapFree(GetProcessHeap(), 0, buffer);
+    GlobalUnlock(data);
+    if (filenames) CFRelease(filenames);
+    TRACE(" -> %s\n", debugstr_cf(ret));
+    return ret;
+}
+
+
+/**************************************************************************
  *              export_oemtext_to_utf8
  *
  *  Export CF_OEMTEXT to UTF-8.




More information about the wine-cvs mailing list