xdnd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Cleaning up my src tree I realize I've had this sitting in my tree for
ages. This patch allows for such operations as dragging files from
Nautilus or Konqueror and dropping them into MS Word.

Changelog:
	Ulrich Czekalla ulrich.czekalla@xxxxxxxxxxx
	Initial implementation to support XDND protocol
Index: dlls/x11drv/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/Makefile.in,v
retrieving revision 1.33
diff -u -w -r1.33 Makefile.in
--- dlls/x11drv/Makefile.in	16 Oct 2003 00:21:42 -0000	1.33
+++ dlls/x11drv/Makefile.in	3 Nov 2003 15:52:28 -0000
@@ -35,6 +35,7 @@
 	winpos.c \
 	x11ddraw.c \
 	x11drv_main.c \
+	xdnd.c \
 	xrandr.c \
 	xrender.c \
 	xvidmode.c
Index: dlls/x11drv/event.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/event.c,v
retrieving revision 1.23
diff -u -w -r1.23 event.c
--- dlls/x11drv/event.c	5 Sep 2003 23:08:26 -0000	1.23
+++ dlls/x11drv/event.c	3 Nov 2003 15:52:30 -0000
@@ -1227,7 +1227,8 @@
         else if (event->data.l[0] == DndURL)
             EVENT_DropURLs(hWnd, event);
     }
-    else {
+    else if (!X11DRV_XDND_Event(hWnd, event))
+    {
 #if 0
       /* enable this if you want to see the message */
       unsigned char* p_data = NULL;
Index: dlls/x11drv/window.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/window.c,v
retrieving revision 1.60
diff -u -w -r1.60 window.c
--- dlls/x11drv/window.c	24 Oct 2003 04:21:46 -0000	1.60
+++ dlls/x11drv/window.c	3 Nov 2003 15:52:31 -0000
@@ -431,6 +431,9 @@
         XFree(wm_hints);
         wine_tsx11_unlock();
     }
+
+    /* Set XDND hints */
+    X11DRV_XDND_EnableDragDrop(win->hwndSelf, TRUE);
 }
 
 
@@ -686,6 +689,7 @@
     _kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
     netwmPid = XInternAtom( display, "_NET_WM_PID", False );
     netwmPing = XInternAtom( display, "_NET_WM_PING", False );
+    X11DRV_XDND_RegisterXDNDAtoms(display);
     wine_tsx11_unlock();
 
     whole_window_atom  = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.6
diff -u -w -r1.6 x11drv.h
--- dlls/x11drv/x11drv.h	16 Oct 2003 00:21:42 -0000	1.6
+++ dlls/x11drv/x11drv.h	3 Nov 2003 15:52:31 -0000
@@ -231,6 +231,10 @@
 extern void X11DRV_OpenGL_Init(Display *display);
 extern XVisualInfo *X11DRV_setup_opengl_visual(Display *display);
 
+extern void X11DRV_XDND_EnableDragDrop(HWND hWnd, BOOL enable);
+extern void X11DRV_XDND_RegisterXDNDAtoms(Display *display);
+extern int X11DRV_XDND_Event(HWND hWnd, XClientMessageEvent *event);
+
 /* exported dib functions for now */
 
 /* Additional info for DIB section objects */
--- /dev/null	2003-01-30 05:24:37.000000000 -0500
+++ dlls/x11drv/xdnd.c	2003-10-30 23:15:35.000000000 -0500
@@ -0,0 +1,667 @@
+/*
+ * XDND handler code
+ *
+ * Copyright 2003 Ulrich Czekalla
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "ts_xlib.h"
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "wownt32.h"
+
+#include "x11drv.h"
+#include "win.h"
+#include "shlobj.h"  /* DROPFILES */
+#include "file.h"    /* DOSFILENAME */
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(xdnd);
+
+Atom dndVersion = 4;
+Atom XDNDAwareAtom = None;
+Atom XDNDEnterAtom = None;
+Atom XDNDPositionAtom = None;
+Atom XDNDStatusAtom = None;
+Atom XDNDLeaveAtom = None;
+Atom XDNDDropAtom = None;
+Atom XDNDFinishedAtom = None;
+Atom XDNDActionCopyAtom = None;
+Atom XDNDActionMoveAtom = None;
+Atom XDNDActionLinkAtom = None;
+Atom XDNDActionAskAtom = None;
+Atom XDNDActionPrivateAtom = None;
+Atom XDNDSelectionAtom = None;
+Atom XDNDTargetAtom = None;
+Atom MimeTextPlainAtom = None;
+Atom MimeTextHTMLAtom = None;
+Atom MimeTextRTFAtom = None;
+Atom XDNDTypeListAtom = None;
+
+#define XDNDAwareAtomName "XdndAware"
+#define XDNDEnterAtomName "XdndEnter"
+#define XDNDPositionAtomName "XdndPosition"
+#define XDNDStatusAtomName "XdndStatus"
+#define XDNDLeaveAtomName "XdndLeave"
+#define XDNDFinishedAtomName "XdndLeave"
+#define XDNDDropAtomName "XdndDrop"
+#define XDNDActionCopyAtomName "XdndActionCopy"
+#define XDNDActionMoveAtomName "XdndActionMove"
+#define XDNDActionLinkAtomName "XdndActionLink"
+#define XDNDActionAskAtomName "XdndActionAsk"
+#define XDNDActionPrivateAtomName "XdndActionPrivate"
+#define XDNDSelectionAtomName "XdndSelection"
+#define XDNDTargetAtomName "XdndTarget"
+#define MimeTextPlainAtomName "text/plain"
+#define MimeTextHTMLAtomName "text/html"
+#define MimeTextRTFAtomName "text/rtf"
+#define XDNDTypeListAtomName "XdndTypeList"
+
+/* Maximum wait time for selection notify */
+#define SELECTION_RETRIES 500  /* wait for .1 seconds */
+#define SELECTION_WAIT    1000 /* us */
+
+typedef struct tagXDNDDATA
+{
+    int cf_win;
+    Atom cf_xdnd;
+    void *data;
+    unsigned int size;
+    struct tagXDNDDATA *next;
+} XDNDDATA, *LPXDNDDATA;
+
+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_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);
+static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
+    Atom *types, unsigned long *count);
+static void X11DRV_XDND_SendDropFiles(WND *pWnd);
+static void X11DRV_XDND_FreeDragDropOp();
+static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len);
+static DROPFILES* X11DRV_XDND_BuildDropFiles(char* filename, unsigned int len, POINT pt);
+
+static CRITICAL_SECTION xdnd_cs;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &xdnd_cs,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { 0, (DWORD)(__FILE__ ": xdnd_cs") }
+};
+static CRITICAL_SECTION xdnd_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+/********************************************************************
+ * X11DRV_XDND_RegisterXDNDAtoms
+ *
+ * Register XDND specific Atoms.
+ */
+void X11DRV_XDND_RegisterXDNDAtoms(Display *display)
+{
+    XDNDAwareAtom = XInternAtom( display, XDNDAwareAtomName, False );
+    XDNDEnterAtom = XInternAtom( display, XDNDEnterAtomName, False );
+    XDNDPositionAtom = XInternAtom( display, XDNDPositionAtomName, False );
+    XDNDStatusAtom = XInternAtom( display, XDNDStatusAtomName, False );
+    XDNDLeaveAtom = XInternAtom( display, XDNDLeaveAtomName, False );
+    XDNDDropAtom = XInternAtom( display, XDNDDropAtomName, False );
+    XDNDFinishedAtom =XInternAtom( display, XDNDFinishedAtomName, False );
+    XDNDActionCopyAtom = XInternAtom( display, XDNDActionCopyAtomName, False );
+    XDNDActionMoveAtom = XInternAtom( display, XDNDActionMoveAtomName, False );
+    XDNDActionLinkAtom = XInternAtom( display, XDNDActionLinkAtomName, False );
+    XDNDActionAskAtom = XInternAtom( display, XDNDActionAskAtomName, False );
+    XDNDActionPrivateAtom = XInternAtom( display, XDNDActionPrivateAtomName, False );
+    XDNDSelectionAtom = XInternAtom( display, XDNDSelectionAtomName, False);
+    XDNDTargetAtom = XInternAtom( display, XDNDTargetAtomName, False );
+    XDNDTypeListAtom = XInternAtom( display, XDNDTypeListAtomName, False );
+    MimeTextPlainAtom = XInternAtom( display, MimeTextPlainAtomName, False );
+    MimeTextHTMLAtom = XInternAtom( display, MimeTextHTMLAtomName, False );
+    MimeTextRTFAtom = XInternAtom( display, MimeTextRTFAtomName, False );
+}
+
+
+/********************************************************************
+ * X11DRV_XDND_EnableDragDrop
+ *
+ * Announce window is XDND aware.
+ */
+void X11DRV_XDND_EnableDragDrop(HWND hWnd, BOOL enable)
+{
+    WND* pWnd;
+    HWND top = 0;
+    HWND next = hWnd;
+    Display *display = thread_display();
+
+    /* Only register top-level windows */
+    while (next && next != GetDesktopWindow())
+    {
+        top = next;
+        next = GetParent(top);
+    }
+
+    pWnd = WIN_FindWndPtr(top);
+
+    if (pWnd != NULL)
+    {
+        TRACE("hwnd(%p) xwin(0x%08lx) enable(%d)\n", next, get_whole_window(pWnd), enable);
+
+        XChangeProperty( display, get_whole_window(pWnd), XDNDAwareAtom, XA_ATOM,
+            32, PropModeReplace, (unsigned char*)&dndVersion, 1);
+
+        WIN_ReleaseWndPtr(pWnd);
+    }
+    else
+        WARN("Enable XDND failed: 0x%p\n", hWnd);
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_Event
+ *
+ * Entry point for X11 XDND events. Returns FALSE if event is not handled.
+ */
+int X11DRV_XDND_Event(HWND hWnd, XClientMessageEvent *event)
+{
+    int isXDNDMsg = 1;
+
+    TRACE("0x%p\n", hWnd);
+
+    if (event->message_type == XDNDEnterAtom)
+    {
+        Atom *xdndtypes;
+        unsigned long count = 0;
+
+        TRACE("XDNDEnter: ver(%ld) check-XdndTypeList(%ld) data=%ld,%ld,%ld,%ld,%ld\n",
+            (event->data.l[1] & 0xFF000000) >> 24, (event->data.l[1] & 1),
+             event->data.l[0], event->data.l[1], event->data.l[2],
+             event->data.l[3], event->data.l[4]);
+
+        /* If the source supports more than 3 data types we retrieve
+         * the entire list. */
+        if (event->data.l[1] & 1)
+        {
+            Atom acttype;
+            int actfmt;
+            unsigned long bytesret;
+
+            /* Request supported formats from source window */
+            TSXGetWindowProperty(event->display, event->data.l[0], XDNDTypeListAtom, 
+                0, 65535, FALSE, AnyPropertyType, &acttype, &actfmt, &count, 
+                &bytesret, (unsigned char**)&xdndtypes);
+        }
+        else
+        {
+            count = 3;
+            xdndtypes = &event->data.l[2];
+        }
+
+        if (TRACE_ON(xdnd))
+        {
+            unsigned int i = 0;
+
+            for (; i < count; i++)
+            {
+                if (xdndtypes[i] != 0)
+                {
+                    char * pn = TSXGetAtomName(event->display, xdndtypes[i]);
+                    TRACE("XDNDEnterAtom %ld: %s\n", xdndtypes[i], pn);
+                    TSXFree(pn);
+                }
+            }
+        }
+
+        /* Do a one-time data read and cache results */
+        X11DRV_XDND_ResolveProperty(event->display, event->window,
+            event->data.l[1], xdndtypes, &count);
+
+        if (event->data.l[1] & 1)
+            XFree(xdndtypes);
+    }
+    else if (event->message_type == XDNDPositionAtom)
+    {
+        XClientMessageEvent e;
+        int accept = 0; /* Assume we're not accepting */
+
+        XDNDxy.x = event->data.l[2] >> 16;
+        XDNDxy.y = event->data.l[2] & 0xFFFF;
+
+        WND *pWnd = WIN_FindWndPtr(hWnd);
+
+	/* FIXME: Notify OLE of DragEnter. Result determines if we accept */
+
+        if ((pWnd != NULL) && (pWnd->dwExStyle & WS_EX_ACCEPTFILES))
+            accept = 1;
+
+        WIN_ReleaseWndPtr(pWnd);
+
+        TRACE("XDNDPosition. action req: %ld accept(%d) at x(%ld),y(%ld)\n",
+                 event->data.l[4], accept, XDNDxy.x, XDNDxy.y);
+
+        /*
+         * Let source know if we're accepting the drop by
+         * sending a status message.
+         */
+        e.type = ClientMessage;
+        e.display = event->display;
+        e.window = event->data.l[0];
+        e.message_type = XDNDStatusAtom;
+        e.format = 32;
+        e.data.l[0] = event->window;
+        e.data.l[1] = accept;
+        e.data.l[2] = 0; /* Empty Rect */
+        e.data.l[3] = 0; /* Empty Rect */
+        if (accept)
+            e.data.l[4] = event->data.l[4];
+        else
+            e.data.l[4] = None;
+        TSXSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e);
+
+	/* FIXME: if drag accepted notify OLE of DragOver */
+    }
+    else if (event->message_type == XDNDDropAtom)
+    {
+        WND *pWnd;
+        XClientMessageEvent e;
+
+        TRACE("XDNDDrop\n");
+
+        pWnd = WIN_FindWndPtr(hWnd);
+
+        /* If we have a HDROP type we send a WM_ACCEPTFILES.*/
+        if (pWnd != NULL)
+        {
+            if (pWnd->dwExStyle & WS_EX_ACCEPTFILES)
+                X11DRV_XDND_SendDropFiles(pWnd);
+            WIN_ReleaseWndPtr(pWnd);
+        }
+
+	/* FIXME: Notify OLE of Drop */
+        X11DRV_XDND_FreeDragDropOp();
+
+        /* Tell the target we are finished. */
+        bzero(&e, sizeof(e));
+        e.type = ClientMessage;
+        e.display = event->display;
+        e.window = event->data.l[0];
+        e.message_type = XDNDFinishedAtom;
+        e.format = 32;
+        e.data.l[0] = event->window;
+        TSXSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e);
+    }
+    else if (event->message_type == XDNDLeaveAtom)
+    {
+        TRACE("DND Operation canceled\n");
+
+        X11DRV_XDND_FreeDragDropOp();
+
+	/* FIXME: Notify OLE of DragLeave */
+    }
+    else /* Not an XDND message */
+        isXDNDMsg = 0;
+
+    return isXDNDMsg;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_ResolveProperty
+ *
+ * Resolve all MIME types to windows clipboard formats. All data is cached.
+ */
+static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
+    	Atom *types, unsigned long *count)
+{
+    unsigned int i, j;
+    BOOL res;
+    XEvent xe;
+    Atom acttype;
+    int actfmt;
+    unsigned long bytesret, icount;
+    int entries = 0;
+    unsigned char* data = NULL;
+
+    TRACE("count(%ld)\n", *count);
+
+    X11DRV_XDND_FreeDragDropOp(); /* Clear previously cached data */
+
+    for (i = 0; i < *count; i++)
+    {
+        TRACE("requesting atom %ld from xwin %ld\n", types[i], xwin);
+
+        if (types[i] == 0)
+            continue;
+
+        wine_tsx11_lock();
+        XConvertSelection(display, XDNDSelectionAtom, types[i], XDNDTargetAtom, xwin, /*tm*/CurrentTime);
+        wine_tsx11_unlock();
+
+        /*
+         * Wait for SelectionNotify
+         */
+        for (j = 0; j < SELECTION_RETRIES; j++)
+        {
+            wine_tsx11_lock();
+            res = XCheckTypedWindowEvent(display, xwin, SelectionNotify, &xe);
+            wine_tsx11_unlock();
+            if (res && xe.xselection.selection == XDNDSelectionAtom) break;
+
+            usleep(SELECTION_WAIT);
+        }
+
+        if (xe.xselection.property == None)
+            continue;
+
+        wine_tsx11_lock();
+        XGetWindowProperty(display, xwin, XDNDTargetAtom, 0, 65535, FALSE,
+            AnyPropertyType, &acttype, &actfmt, &icount, &bytesret, &data);
+        wine_tsx11_unlock();
+
+        entries += X11DRV_XDND_MapFormat(types[i], data, icount * (actfmt / 8));
+        TSXFree(data);
+    }
+
+    *count = entries;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_InsertXDNDData
+ *
+ * Cache available XDND property
+ */
+static void X11DRV_XDND_InsertXDNDData(int property, int format, void* data, unsigned int len)
+{
+    LPXDNDDATA current = (LPXDNDDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(XDNDDATA));
+
+    if (current)
+    {
+        EnterCriticalSection(&xdnd_cs);
+        current->next = XDNDData;
+        current->cf_xdnd = property;
+        current->cf_win = format;
+        current->data = data;
+        current->size = len;
+        XDNDData = current;
+        LeaveCriticalSection(&xdnd_cs);
+    }
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_MapFormat
+ *
+ * Map XDND MIME format to windows clipboard format.
+ */
+static int X11DRV_XDND_MapFormat(unsigned int property, unsigned char *data, int len)
+{
+    void* xdata;
+    int count = 0;
+
+    TRACE("%d: %s\n", property, data);
+
+    /* Always include the raw type */
+    xdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+    memcpy(xdata, data, len);
+    X11DRV_XDND_InsertXDNDData(property, property, xdata, len);
+    count++;
+
+    if (property == MimeTextPlainAtom)
+        count += X11DRV_XDND_DeconstructTextPlain(property, data, len);
+    else if (property == MimeTextHTMLAtom)
+        count += X11DRV_XDND_DeconstructTextHTML(property, data, len);
+
+    return count;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_DeconstructTextPlain
+ *
+ * Interpret text/plain Data and add records to <dndfmt> linked list
+ */
+static int X11DRV_XDND_DeconstructTextPlain(int property, void* data, int len)
+{
+    char *p = (char*) data;
+    char* dostext;
+    int count = 0;
+
+    /* Always suppply plain text */
+    X11DRV_XDND_UnixToDos(&dostext, (char*)data, len);
+    X11DRV_XDND_InsertXDNDData(property, CF_TEXT, dostext, strlen(dostext));
+    count++;
+
+    TRACE("CF_TEXT (%d): %s\n", CF_TEXT, dostext);
+
+    /* Check for additional mappings */
+    while (*p != '\0' && *p != ':') /* Advance to end of protocol */
+        p++;
+
+    if (*p == ':')
+    {
+        if (!strncasecmp(data, "http", 4))
+        {
+            X11DRV_XDND_InsertXDNDData(property, RegisterClipboardFormatA("UniformResourceLocator"),
+                strdup(dostext), strlen(dostext));
+                count++;
+
+            TRACE("UniformResourceLocator: %s\n", dostext);
+        }
+        else if (!strncasecmp(data, "file", 4))
+        {
+            DROPFILES* pdf;
+
+            pdf = X11DRV_XDND_BuildDropFiles(p+1, len - 5, XDNDxy);
+            if (pdf)
+            {
+                unsigned int size = HeapSize(GetProcessHeap(), 0, pdf);
+
+                X11DRV_XDND_InsertXDNDData(property, CF_HDROP, pdf, size);
+                count++;
+            }
+
+            TRACE("CF_HDROP: %p\n", pdf);
+        }
+    }
+
+    return count;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_DeconstructTextHTML
+ *
+ * Interpret text/html data and add records to <dndfmt> linked list
+ */
+static int X11DRV_XDND_DeconstructTextHTML(int property, void* data, int len)
+{
+    char* dostext;
+
+    X11DRV_XDND_UnixToDos(&dostext, data, len);
+
+    X11DRV_XDND_InsertXDNDData(property,
+        RegisterClipboardFormatA("UniformResourceLocator"), dostext, strlen(dostext));
+
+    TRACE("UniformResourceLocator: %s\n", dostext);
+
+    return 1;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_SendDropFiles
+ */
+static void X11DRV_XDND_SendDropFiles(WND *pWnd)
+{
+    LPXDNDDATA current;
+
+    EnterCriticalSection(&xdnd_cs);
+
+    current = XDNDData;
+
+    /* Find CF_HDROP type if any */
+    while (current != NULL)
+    {
+        if (current->cf_win == CF_HDROP)
+            break;
+        current = current->next;
+    }
+
+    if (current != NULL)
+    {
+        DROPFILES *lpDrop = (DROPFILES*) current->data;
+
+        if (lpDrop)
+        {
+            lpDrop->pt.x = XDNDxy.x;
+            lpDrop->pt.y = XDNDxy.y;
+
+            TRACE("Sending WM_DROPFILES: hWnd(0x%p) %p(%s)\n", pWnd->hwndSelf,
+                ((char*)lpDrop) + lpDrop->pFiles, ((char*)lpDrop) + lpDrop->pFiles);
+
+            PostMessageA(pWnd->hwndSelf, WM_DROPFILES, (WPARAM)lpDrop, 0L);
+        }
+    }
+
+    LeaveCriticalSection(&xdnd_cs);
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_FreeDragDropOp
+ */
+static void X11DRV_XDND_FreeDragDropOp()
+{
+    LPXDNDDATA next;
+    LPXDNDDATA current;
+
+    TRACE("\n");
+
+    EnterCriticalSection(&xdnd_cs);
+
+    current = XDNDData;
+
+    /** Free data cache */
+    while (current != NULL)
+    {
+    	next = current->next;
+    	HeapFree(GetProcessHeap(), 0, current);
+    	current = next;
+    }
+
+    XDNDData = NULL;
+    XDNDxy.x = XDNDxy.y = 0;
+
+    LeaveCriticalSection(&xdnd_cs);
+}
+
+
+
+/**************************************************************************
+ * X11DRV_XDND_BuildDropFiles
+ */
+static DROPFILES* X11DRV_XDND_BuildDropFiles(char* filename, unsigned int len, POINT pt)
+{
+    char* pfn;
+    int pathlen;
+    char path[MAX_PATH];
+    DROPFILES *lpDrop = NULL;
+
+    /* Advance to last starting slash */
+    pfn = filename + 1;
+    while (*pfn && (*pfn == '\\' || *pfn =='/'))
+    {
+        pfn++;
+        filename++;
+    }
+
+    /* Remove any trailing \r or \n */
+    while (*pfn)
+    {
+        if (*pfn == '\r' || *pfn == '\n')
+        {
+            *pfn = 0;
+            break;
+        }
+        pfn++;
+    }
+
+    TRACE("%s\n", filename);
+
+    pathlen = GetLongPathNameA(filename, path, MAX_PATH);
+    if (pathlen)
+    {
+        lpDrop = (DROPFILES*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            sizeof(DROPFILES) + pathlen + 1);
+
+        lpDrop->pFiles = sizeof(DROPFILES);
+        lpDrop->pt.x = pt.x;
+        lpDrop->pt.y = pt.y;
+        lpDrop->fNC = 0;
+        lpDrop->fWide = FALSE;
+
+        strcpy(((char*)lpDrop)+lpDrop->pFiles, path);
+    }
+
+    TRACE("resolved %s\n", lpDrop ? filename : NULL);
+
+    return lpDrop;
+}
+
+
+/**************************************************************************
+ * X11DRV_XDND_UnixToDos
+ */
+static unsigned int X11DRV_XDND_UnixToDos(char** lpdest, char* lpsrc, int len)
+{
+    int i;
+    unsigned int destlen, lines;
+
+    for (i = 0, lines = 0; i <= len; i++)
+    {
+        if (lpsrc[i] == '\n')
+            lines++;
+    }
+
+    destlen = len + lines + 1;
+
+    if (lpdest)
+    {
+        char* lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, destlen);
+    	for (i = 0, lines = 0; i <= len; i++)
+    	{
+            if (lpsrc[i] == '\n')
+                lpstr[++lines + i] = '\r';
+            lpstr[lines + i] = lpsrc[i];
+    	}
+
+    	*lpdest = lpstr;
+    }
+
+    return lines;
+}

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux