Damjan Jovanovic : winex11.drv: Added better support for the X file drag protocol.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jun 27 09:11:29 CDT 2007


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

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Wed Jun 27 09:50:35 2007 +0200

winex11.drv: Added better support for the X file drag protocol.

---

 dlls/winex11.drv/x11drv.h      |    1 +
 dlls/winex11.drv/x11drv_main.c |    3 +-
 dlls/winex11.drv/xdnd.c        |  178 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 180 insertions(+), 2 deletions(-)

diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 8de2e25..c542582 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -597,6 +597,7 @@ enum x11drv_atoms
     XATOM_text_plain,
     XATOM_text_rtf,
     XATOM_text_richtext,
+    XATOM_text_uri_list,
     NB_XATOMS
 };
 
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c
index 15a3624..e4c8a87 100644
--- a/dlls/winex11.drv/x11drv_main.c
+++ b/dlls/winex11.drv/x11drv_main.c
@@ -158,7 +158,8 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] =
     "text/html",
     "text/plain",
     "text/rtf",
-    "text/richtext"
+    "text/richtext",
+    "text/uri-list"
 };
 
 /***********************************************************************
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index f1d6d24..59410c5 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -2,6 +2,7 @@
  * XDND handler code
  *
  * Copyright 2003 Ulrich Czekalla
+ * Copyright 2007 Damjan Jovanovic
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,6 +27,7 @@
 # include <unistd.h>
 #endif
 #include <stdarg.h>
+#include <stdio.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -35,6 +37,7 @@
 #include "x11drv.h"
 #include "shlobj.h"  /* DROPFILES */
 
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(xdnd);
@@ -56,6 +59,7 @@ static LPXDNDDATA XDNDData = NULL;
 static POINT XDNDxy = { 0, 0 };
 
 static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, unsigned int len);
+static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len);
 static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len);
 static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len);
 static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int len);
@@ -64,6 +68,7 @@ static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
 static void X11DRV_XDND_SendDropFiles(HWND hwnd);
 static void X11DRV_XDND_FreeDragDropOp(void);
 static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len);
+static WCHAR* X11DRV_XDND_URIToDOS(char *encodedURI);
 static DROPFILES* X11DRV_XDND_BuildDropFiles(char* filename, unsigned int len, POINT pt);
 
 static CRITICAL_SECTION xdnd_cs;
@@ -333,7 +338,9 @@ static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int
     X11DRV_XDND_InsertXDNDData(property, property, xdata, len);
     count++;
 
-    if (property == x11drv_atom(text_plain))
+    if (property == x11drv_atom(text_uri_list))
+        count += X11DRV_XDND_DeconstructTextURIList(property, data, len);
+    else if (property == x11drv_atom(text_plain))
         count += X11DRV_XDND_DeconstructTextPlain(property, data, len);
     else if (property == x11drv_atom(text_html))
         count += X11DRV_XDND_DeconstructTextHTML(property, data, len);
@@ -343,6 +350,92 @@ static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int
 
 
 /**************************************************************************
+ * X11DRV_XDND_DeconstructTextURIList
+ *
+ * Interpret text/uri-list data and add records to <dndfmt> linked list
+ */
+static int X11DRV_XDND_DeconstructTextURIList(int property, void* data, int len)
+{
+    char *uriList = (char*) data;
+    char *uri;
+    WCHAR *path;
+
+    char *out = NULL;
+    int size = 0;
+    int capacity = 4096;
+
+    int count = 0;
+    int start = 0;
+    int end = 0;
+
+    out = HeapAlloc(GetProcessHeap(), 0, capacity);
+    if (out == NULL)
+        return 0;
+
+    while (end < len)
+    {
+        while (end < len && uriList[end] != '\r')
+            ++end;
+        if (end == len)
+            break;
+        if (uriList[end+1] != '\n')
+        {
+            WARN("URI list line doesn't end in \\r\\n\n");
+            break;
+        }
+
+        uri = HeapAlloc(GetProcessHeap(), 0, end - start + 1);
+        if (uri == NULL)
+            break;
+        lstrcpynA(uri, &uriList[start], end - start + 1);
+        path = X11DRV_XDND_URIToDOS(uri);
+        TRACE("converted URI %s to DOS path %s\n", debugstr_a(uri), debugstr_w(path));
+        HeapFree(GetProcessHeap(), 0, uri);
+
+        if (path)
+        {
+            int pathSize = strlenW(path) + 1;
+            if (pathSize > capacity-size)
+            {
+                capacity = 2*capacity + pathSize;
+                out = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, out, capacity + 1);
+                if (out == NULL)
+                    goto done;
+            }
+            WideCharToMultiByte(CP_ACP, 0, path, -1, &out[size], pathSize, 0, 0);
+            size += pathSize;
+        done:
+            HeapFree(GetProcessHeap(), 0, path);
+            if (out == NULL)
+                break;
+        }
+
+        start = end + 2;
+        end = start;
+    }
+    if (out && end == len)
+    {
+        DROPFILES *dropFiles;
+        dropFiles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DROPFILES) + size + 1);
+        if (dropFiles)
+        {
+            dropFiles->pFiles = sizeof(DROPFILES);
+            dropFiles->pt.x = XDNDxy.x;
+            dropFiles->pt.y = XDNDxy.y;
+            dropFiles->fNC = 0;
+            dropFiles->fWide = FALSE;
+            out[size] = '\0';
+            memcpy(((char*)dropFiles) + dropFiles->pFiles, out, size + 1);
+            X11DRV_XDND_InsertXDNDData(property, CF_HDROP, dropFiles, sizeof(DROPFILES) + size + 1);
+            count = 1;
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, out);
+    return count;
+}
+
+
+/**************************************************************************
  * X11DRV_XDND_DeconstructTextPlain
  *
  * Interpret text/plain Data and add records to <dndfmt> linked list
@@ -566,3 +659,86 @@ static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len)
 
     return lines;
 }
+
+
+/**************************************************************************
+ * X11DRV_XDND_URIToDOS
+ */
+static WCHAR* X11DRV_XDND_URIToDOS(char *encodedURI)
+{
+    WCHAR *ret = NULL;
+    int i;
+    int j = 0;
+    char *uri = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(encodedURI) + 1);
+    if (uri == NULL)
+        return NULL;
+    for (i = 0; encodedURI[i]; ++i)
+    {
+        if (encodedURI[i] == '%')
+        { 
+            if (encodedURI[i+1] && encodedURI[i+2])
+            {
+                char buffer[3];
+                int number;
+                buffer[0] = encodedURI[i+1];
+                buffer[1] = encodedURI[i+2];
+                buffer[2] = '\0';
+                sscanf(buffer, "%x", &number);
+                uri[j++] = number;
+                i += 2;
+            }
+            else
+            {
+                WARN("invalid URI encoding in %s\n", debugstr_a(encodedURI));
+                HeapFree(GetProcessHeap(), 0, uri);
+                return NULL;
+            }
+        }
+        else
+            uri[j++] = encodedURI[i];
+    }
+
+    /* Read http://www.freedesktop.org/wiki/Draganddropwarts and cry... */
+    if (strncmp(uri, "file:/", 6) == 0)
+    {
+        if (uri[6] == '/')
+        {
+            if (uri[7] == '/')
+            {
+                /* file:///path/to/file (nautilus, thunar) */
+                ret = wine_get_dos_file_name(&uri[7]);
+            }
+            else if (uri[7])
+            {
+                /* file://hostname/path/to/file (X file drag spec) */
+                char hostname[256];
+                char *path = strchr(&uri[7], '/');
+                if (path)
+                {
+                    *path = '\0';
+                    if (strcmp(&uri[7], "localhost") == 0)
+                    {
+                        *path = '/';
+                        ret = wine_get_dos_file_name(path);
+                    }
+                    else if (gethostname(hostname, sizeof(hostname)) == 0)
+                    {
+                        if (strcmp(hostname, &uri[7]) == 0)
+                        {
+                            *path = '/';
+                            ret = wine_get_dos_file_name(path);
+                        }
+                    }
+                }
+            }
+        }
+        else if (uri[6])
+        {
+            /* file:/path/to/file (konqueror) */
+            ret = wine_get_dos_file_name(&uri[5]);
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, uri);
+    return ret;
+}
+




More information about the wine-cvs mailing list