- use global atoms for the format ids
- add timeout when calling XCheckTypedWindowEvent
- fix broken IsClipboardFormatAvailable; it tried to do a trick with
  EnumClipboardFormats by making incorrect assumptions
- in X11DRV_IsClipboardFormatAvailable do a quick exit if no one owns
  the selection
- add 1 second *minimum* time lapse between XSelectionOwner calls
- sync clipboard ownership between different wine processes
- prevents apps from getting into wierd state where they thought they
  didn't own the selection but they did and as a result queried
  themselves for available selection data

diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index eea0cde..4fa8c3b 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -4,6 +4,7 @@
  * Copyright 1994 Martin Ayotte
  *	     1996 Alex Korobka
  *	     1999 Noel Borthwick
+ *           2003 Ulrich Czekalla for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -76,416 +77,1273 @@
 #include "win.h"
 #include "x11drv.h"
 #include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/server.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
 
+#define HGDIOBJ_32(handle16)  ((HGDIOBJ)(ULONG_PTR)(handle16))
+
 /* Maximum wait time for slection notify */
-#define MAXSELECTIONNOTIFYWAIT 5
+#define SELECTION_RETRIES 500  /* wait for .1 seconds */
+#define SELECTION_WAIT    1000 /* us */
+/* Minium seconds that must lapse between owner queries */
+#define OWNERQUERYLAPSETIME 1
 
 /* Selection masks */
-
 #define S_NOSELECTION    0
 #define S_PRIMARY        1
 #define S_CLIPBOARD      2
 
-/* X selection context info */
+#define _CLIPBOARD    "CLIPBOARD"              /* CLIPBOARD atom name */
+#define _TARGETS      "TARGETS"
+#define _MULTIPLE     "MULTIPLE"
+#define _SELECTIONDATA "SELECTION_DATA"
 
-static char _CLIPBOARD[] = "CLIPBOARD";        /* CLIPBOARD atom name */
-static char FMT_PREFIX[] = "<WCF>";            /* Prefix for windows specific formats */
+Atom xaClipboard = None;
+Atom xaTargets = None;
+Atom xaMultiple = None;
+Atom xaSelectionData = None;
+
 static int selectionAcquired = 0;              /* Contains the current selection masks */
 static Window selectionWindow = None;          /* The top level X window which owns the selection */
-static Window selectionPrevWindow = None;      /* The last X window that owned the selection */
+static BOOL clearAllSelections = FALSE;        /* Always lose all selections */
+static Atom selectionCacheSrc = XA_PRIMARY;    /* The selection source from which the clipboard cache was filled */
 static Window PrimarySelectionOwner = None;    /* The window which owns the primary selection */
 static Window ClipboardSelectionOwner = None;  /* The window which owns the clipboard selection */
-static unsigned long cSelectionTargets = 0;    /* Number of target formats reported by TARGETS selection */
-static Atom selectionCacheSrc = XA_PRIMARY;    /* The selection source from which the clipboard cache was filled */
-static HANDLE selectionClearEvent = 0;/* Synchronization object used to block until server is started */
 
-typedef struct tagPROPERTY
+INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
+void X11DRV_EmptyClipboard(void);
+void X11DRV_EndClipboardUpdate(void);
+HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
+HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
+HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes);
+HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes);
+HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes);
+HANDLE X11DRV_CLIPBOARD_ExportClipboardData(LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
+HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes);
+HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
+HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
+HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes);
+UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, LPCSTR PropertyName);
+static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop);
+static BOOL X11DRV_CLIPBOARD_RenderText(UINT wFormatID);
+static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData);
+static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void);
+static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo);
+static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat);
+static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData);
+static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out);
+static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID);
+static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData);
+
+/* Clipboard formats
+ * WARNING: This data ordering is dependent on the WINE_CLIPFORMAT structure
+ * declared in clipboard.h
+ */
+WINE_CLIPFORMAT ClipFormats[]  =
 {
-    struct tagPROPERTY *next;
-    Atom                atom;
-    Pixmap              pixmap;
-} PROPERTY;
+    { CF_TEXT, "WCF_TEXT",  0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, NULL, &ClipFormats[1]},
 
-static PROPERTY *prop_head;
+    { CF_BITMAP, "WCF_BITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[0], &ClipFormats[2]},
 
+    { CF_METAFILEPICT, "WCF_METAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportMetaFilePict,
+        X11DRV_CLIPBOARD_ExportMetaFilePict, &ClipFormats[1], &ClipFormats[3]},
+
+    { CF_SYLK, "WCF_SYLK", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[2], &ClipFormats[4]},
+
+    { CF_DIF, "WCF_DIF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[3], &ClipFormats[5]},
+
+    { CF_TIFF, "WCF_TIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[4], &ClipFormats[6]},
+
+    { CF_OEMTEXT, "WCF_OEMTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[5], &ClipFormats[7]},
+
+    { CF_DIB, "WCF_DIB", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAPIXMAP,
+	X11DRV_CLIPBOARD_ExportXAPIXMAP, &ClipFormats[6], &ClipFormats[8]},
+
+    { CF_PALETTE, "WCF_PALETTE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[7], &ClipFormats[9]},
+
+    { CF_PENDATA, "WCF_PENDATA", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[8], &ClipFormats[10]},
+
+    { CF_RIFF, "WCF_RIFF", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[9], &ClipFormats[11]},
+
+    { CF_WAVE, "WCF_WAVE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[10], &ClipFormats[12]},
+
+    { CF_UNICODETEXT, "WCF_UNICODETEXT", XA_STRING, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportXAString,
+	X11DRV_CLIPBOARD_ExportXAString, &ClipFormats[11], &ClipFormats[13]},
+
+    { CF_ENHMETAFILE, "WCF_ENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportEnhMetaFile,
+        X11DRV_CLIPBOARD_ExportEnhMetaFile, &ClipFormats[12], &ClipFormats[14]},
+
+    { CF_HDROP, "WCF_HDROP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[13], &ClipFormats[15]},
+
+    { CF_LOCALE, "WCF_LOCALE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[14], &ClipFormats[16]},
+
+    { CF_DIBV5, "WCF_DIBV5", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[15], &ClipFormats[17]},
+
+    { CF_OWNERDISPLAY, "WCF_OWNERDISPLAY", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[16], &ClipFormats[18]},
+
+    { CF_DSPTEXT, "WCF_DSPTEXT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[17], &ClipFormats[19]},
+
+    { CF_DSPBITMAP, "WCF_DSPBITMAP", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[18], &ClipFormats[20]},
+
+    { CF_DSPMETAFILEPICT, "WCF_DSPMETAFILEPICT", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[19], &ClipFormats[21]},
+
+    { CF_DSPENHMETAFILE, "WCF_DSPENHMETAFILE", 0, CF_FLAG_BUILTINFMT, X11DRV_CLIPBOARD_ImportClipboardData,
+        X11DRV_CLIPBOARD_ExportClipboardData, &ClipFormats[20], NULL}
+};
+
+
+/* Maps X properties to Windows formats */
+PROPERTYFORMATMAP PropertyFormatMap[] =
+{ 
+    { "text/rtf", "Rich Text Format" },
+    /* Temporarily disable text/html because Evolution incorrectly pastes strings with extra nulls */
+    /*{ "text/html", "HTML Format" },*/
+    { "image/gif", "GIF" },
+};
+
+
+/* Maps equivalent X properties. It is assumed that lpszProperty must already 
+   be in ClipFormats or PropertyFormatMap. */
+PROPERTYALIASMAP PropertyAliasMap[] =
+{ 
+    /* lpszProperty, Alias */
+    { "text/rtf", 0, "text/richtext", 0 },
+};
+
+
+/*
+ * Cached clipboard data.
+ */
+static LPWINE_CLIPDATA ClipData = NULL;
+static UINT ClipDataCount = 0;
+
+/*
+ * Clipboard sequence number
+ */
+UINT wSeqNo = 0;
 
 /**************************************************************************
- *		X11DRV_CLIPBOARD_MapPropertyToFormat
- *
- *  Map an X selection property type atom name to a windows clipboard format ID
- */
-UINT X11DRV_CLIPBOARD_MapPropertyToFormat(char *itemFmtName)
-{
-    /*
-     * If the property name starts with FMT_PREFIX strip this off and
-     * get the ID for a custom Windows registered format with this name.
-     * We can also understand STRING, PIXMAP and BITMAP.
-     */
-    if ( NULL == itemFmtName )
-        return 0;
-    else if ( 0 == strncmp(itemFmtName, FMT_PREFIX, strlen(FMT_PREFIX)) )
-        return RegisterClipboardFormatA(itemFmtName + strlen(FMT_PREFIX));
-    else if ( 0 == strcmp(itemFmtName, "STRING") )
-        return CF_UNICODETEXT;
-    else if ( 0 == strcmp(itemFmtName, "PIXMAP")
-                ||  0 == strcmp(itemFmtName, "BITMAP") )
-    {
-        /*
-         * Return CF_DIB as first preference, if WINE is the selection owner
-         * and if CF_DIB exists in the cache.
-         * If wine dowsn't own the selection we always return CF_DIB
-         */
-        if ( !X11DRV_IsSelectionOwner() )
-            return CF_DIB;
-        else if ( CLIPBOARD_IsPresent(CF_DIB) )
-            return CF_DIB;
-        else
-            return CF_BITMAP;
-    }
-
-    WARN("\tNo mapping to Windows clipboard format for property %s\n", itemFmtName);
-    return 0;
-}
+ *                Internal Clipboard implementation methods
+ **************************************************************************/
 
 /**************************************************************************
- *		X11DRV_CLIPBOARD_MapFormatToProperty
- *
- *  Map a windows clipboard format ID to an X selection property atom
+ *		X11DRV_InitClipboard
  */
-Atom X11DRV_CLIPBOARD_MapFormatToProperty(UINT wFormat)
+BOOL X11DRV_InitClipboard(Display *display)
 {
-    Atom prop = None;
-
-    switch (wFormat)
-    {
-	/* We support only CF_UNICODETEXT, other formats are synthesized */
-        case CF_OEMTEXT:
-        case CF_TEXT:
-	    return None;
-
-        case CF_UNICODETEXT:
-            prop = XA_STRING;
-            break;
-
-        case CF_DIB:
-        case CF_BITMAP:
-        {
-            /*
-             * Request a PIXMAP, only if WINE is NOT the selection owner,
-             * AND the requested format is not in the cache.
-             */
-            if ( !X11DRV_IsSelectionOwner() && !CLIPBOARD_IsPresent(wFormat) )
-            {
-              prop = XA_PIXMAP;
-              break;
-            }
-            /* Fall through to the default case in order to use the native format */
-        }
-
-        default:
-        {
-            /*
-             * If an X atom is registered for this format, return that
-             * Otherwise register a new atom.
-             */
-            char str[256];
-            int plen = strlen(FMT_PREFIX);
-
-            strcpy(str, FMT_PREFIX);
-
-            if (CLIPBOARD_GetFormatName(wFormat, str + plen, sizeof(str) - plen))
-                prop = TSXInternAtom(thread_display(), str, False);
-
-            break;
-        }
-    }
-
-    if (prop == None)
-        TRACE("\tNo mapping to X property for Windows clipboard format %d(%s)\n",
-              wFormat, CLIPBOARD_GetFormatName(wFormat, NULL, 0));
-
-    return prop;
-}
-
-/**************************************************************************
- *	        X11DRV_CLIPBOARD_IsNativeProperty
- *
- *  Checks if a property is a native Wine property type
- */
-BOOL X11DRV_CLIPBOARD_IsNativeProperty(Atom prop)
-{
-    char *itemFmtName = TSXGetAtomName(thread_display(), prop);
-    BOOL bRet = FALSE;
-
-    if ( 0 == strncmp(itemFmtName, FMT_PREFIX, strlen(FMT_PREFIX)) )
-        bRet = TRUE;
-
-    TSXFree(itemFmtName);
-    return bRet;
-}
-
-
-/**************************************************************************
- *		X11DRV_CLIPBOARD_LaunchServer
- * Launches the clipboard server. This is called from X11DRV_CLIPBOARD_ResetOwner
- * when the selection can no longer be recyled to another top level window.
- * In order to make the selection persist after Wine shuts down a server
- * process is launched which services subsequent selection requests.
- */
-BOOL X11DRV_CLIPBOARD_LaunchServer()
-{
-    int iWndsLocks;
-    char clearSelection[8] = "0";
-    int persistent_selection = 1;
+    INT i;
     HKEY hkey;
-    int fd[2], err;
+    PROPERTYALIASMAP *lpalias;
+    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
 
-    /* If persistant selection has been disabled in the .winerc Clipboard section,
-     * don't launch the server
-     */
+    xaClipboard = TSXInternAtom( display, _CLIPBOARD, FALSE );
+    xaTargets = TSXInternAtom( display, _TARGETS, FALSE );
+    xaMultiple = TSXInternAtom(display, _MULTIPLE, False);
+    xaSelectionData = TSXInternAtom(display, _SELECTIONDATA, False);
+
     if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
     {
 	char buffer[20];
 	DWORD type, count = sizeof(buffer);
-	if(!RegQueryValueExA(hkey, "PersistentSelection", 0, &type, buffer, &count))
-	    persistent_selection = atoi(buffer);
-
-	/* Get the clear selection preference */
-	count = sizeof(clearSelection);
-	RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, clearSelection, &count);
-	RegCloseKey(hkey);
+	if(!RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, buffer, &count))
+	    clearAllSelections = atoi(buffer);
+        RegCloseKey(hkey);
     }
-    if ( !persistent_selection )
-        return FALSE;
 
-    /*  Start up persistant WINE X clipboard server process which will
-     *  take ownership of the X selection and continue to service selection
-     *  requests from other apps.
-     */
-
-    if(pipe(fd) == -1) return FALSE;
-    fcntl(fd[1], F_SETFD, 1); /* set close on exec */
-
-    selectionWindow = selectionPrevWindow;
-    if ( !fork() )
+    /* Register known formats */
+    while (lpFormat)
     {
-        /* NOTE: This code only executes in the context of the child process
-         * Do note make any Wine specific calls here.
-         */
-        int dbgClasses = 0;
-        char selMask[8], dbgClassMask[8];
+        if (!lpFormat->wFormatID)
+            lpFormat->wFormatID = GlobalAddAtomA(lpFormat->Name);
 
-	close(fd[0]);
-        sprintf(selMask, "%d", selectionAcquired);
+        if (!lpFormat->drvData)
+            lpFormat->drvData = TSXInternAtom(display, lpFormat->Name, False);
 
-        /* Build the debug class mask to pass to the server, by inheriting
-         * the settings for the clipboard debug channel.
-         */
-        dbgClasses |= FIXME_ON(clipboard) ? 1 : 0;
-        dbgClasses |= ERR_ON(clipboard) ? 2 : 0;
-        dbgClasses |= WARN_ON(clipboard) ? 4 : 0;
-        dbgClasses |= TRACE_ON(clipboard) ? 8 : 0;
-        sprintf(dbgClassMask, "%d", dbgClasses);
-
-        /* Exec the clipboard server passing it the selection and debug class masks */
-        execl( BINDIR "/wineclipsrv", "wineclipsrv",
-               selMask, dbgClassMask, clearSelection, NULL );
-        execlp( "wineclipsrv", "wineclipsrv", selMask, dbgClassMask, clearSelection, NULL );
-
-        /* Exec Failed! */
-        perror("Could not start Wine clipboard server");
-	write(fd[1], &err, sizeof(err));
-        _exit( 1 ); /* Exit the child process */
+	lpFormat = lpFormat->NextFormat;
     }
-    close(fd[1]);
 
-    if(read(fd[0], &err, sizeof(err)) > 0) { /* exec failed */
-        close(fd[0]);
-        return FALSE;
-    }
-    close(fd[0]);
+    /* Register known mapping between window formats and X properties */
+    for (i = 0; i < sizeof(PropertyFormatMap)/sizeof(PROPERTYFORMATMAP); i++)
+        X11DRV_CLIPBOARD_InsertClipboardFormat(PropertyFormatMap[i].lpszFormat, 
+            PropertyFormatMap[i].lpszProperty);
 
-    /* Wait until the clipboard server acquires the selection.
-     * We must release the windows lock to enable Wine to process
-     * selection messages in response to the servers requests.
-     */
-
-    iWndsLocks = WIN_SuspendWndsLock();
-
-    /* We must wait until the server finishes acquiring the selection,
-     * before proceeding, otherwise the window which owns the selection
-     * will be destroyed prematurely!
-     * Create a non-signalled, auto-reset event which will be set by
-     * X11DRV_CLIPBOARD_ReleaseSelection, and wait until this gets
-     * signalled before proceeding.
-     */
-
-    if ( !(selectionClearEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) )
-        ERR("Could not create wait object. Clipboard server won't start!\n");
-    else
+    /* Register known mapping between X properties */
+    for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PROPERTYALIASMAP); i++)
     {
-        /* Wait until we lose the selection, timing out after a minute */
-        DWORD start_time, timeout, elapsed, ret;
-
-        TRACE("Waiting for clipboard server to acquire selection\n");
-
-        timeout = 60000;
-        start_time = GetTickCount();
-        elapsed=0;
-        do
-        {
-            ret = MsgWaitForMultipleObjects( 1, &selectionClearEvent, FALSE, timeout - elapsed, QS_ALLINPUT );
-            if (ret != WAIT_OBJECT_0+1)
-                break;
-            elapsed = GetTickCount() - start_time;
-            if (elapsed > timeout)
-                break;
-        }
-        while (1);
-        if ( ret != WAIT_OBJECT_0 )
-            TRACE("Server could not acquire selection, or a timeout occurred!\n");
-        else
-            TRACE("Server successfully acquired selection\n");
-
-        /* Release the event */
-        CloseHandle(selectionClearEvent);
-        selectionClearEvent = 0;
+        lpalias = &PropertyAliasMap[i];
+        lpalias->drvDataProperty = TSXInternAtom(display, lpalias->lpszProperty, False);
+        lpalias->drvDataAlias = TSXInternAtom(display, lpalias->lpszAlias, False);
     }
 
-    WIN_RestoreWndsLock(iWndsLocks);
-
     return TRUE;
 }
 
 
 /**************************************************************************
- *		X11DRV_CLIPBOARD_CacheDataFormats
+ *                X11DRV_CLIPBOARD_LookupFormat
+ */
+LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupFormat(WORD wID)
+{
+    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
+
+    while(lpFormat)
+    {
+        if (lpFormat->wFormatID == wID) 
+            break;
+
+	lpFormat = lpFormat->NextFormat;
+    }
+
+    return lpFormat;
+}
+
+
+/**************************************************************************
+ *                X11DRV_CLIPBOARD_LookupProperty
+ */
+LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupProperty(UINT drvData)
+{
+    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
+
+    while(lpFormat)
+    {
+        if (lpFormat->drvData == drvData) 
+            break;
+
+	lpFormat = lpFormat->NextFormat;
+    }
+
+    return lpFormat;
+}
+
+
+/**************************************************************************
+ *                X11DRV_CLIPBOARD_LookupAliasProperty
+ */
+LPWINE_CLIPFORMAT X11DRV_CLIPBOARD_LookupAliasProperty(UINT drvDataAlias)
+{
+    unsigned int i;
+    LPWINE_CLIPFORMAT lpFormat = NULL;
+
+    for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PROPERTYALIASMAP); i++)
+    {
+        if (PropertyAliasMap[i].drvDataAlias == drvDataAlias)
+        {
+            lpFormat = X11DRV_CLIPBOARD_LookupProperty(PropertyAliasMap[i].drvDataProperty);
+            break;
+        }
+   }
+
+    return lpFormat;
+}
+
+
+/**************************************************************************
+ *                X11DRV_CLIPBOARD_LookupPropertyAlias
+ */
+UINT  X11DRV_CLIPBOARD_LookupPropertyAlias(UINT drvDataProperty)
+{
+    unsigned int i;
+    UINT alias = 0;
+
+    for (i = 0; i < sizeof(PropertyAliasMap)/sizeof(PROPERTYALIASMAP); i++)
+    {
+        if (PropertyAliasMap[i].drvDataProperty == drvDataProperty)
+        {
+            alias = PropertyAliasMap[i].drvDataAlias;
+            break;
+        }
+   }
+
+    return alias;
+}
+
+
+/**************************************************************************
+ *               X11DRV_CLIPBOARD_LookupData
+ */
+LPWINE_CLIPDATA X11DRV_CLIPBOARD_LookupData(DWORD wID)
+{
+    LPWINE_CLIPDATA lpData = ClipData;
+
+    if (lpData)
+    {
+        do
+        {
+            if (lpData->wFormatID == wID) 
+                break;
+
+	    lpData = lpData->NextData;
+        }
+        while(lpData != ClipData);
+
+        if (lpData->wFormatID != wID)
+            lpData = NULL;
+    }
+
+    return lpData;
+}
+
+
+/**************************************************************************
+ *		InsertClipboardFormat
+ */
+UINT X11DRV_CLIPBOARD_InsertClipboardFormat(LPCSTR FormatName, LPCSTR PropertyName)
+{
+    LPWINE_CLIPFORMAT lpFormat;
+    LPWINE_CLIPFORMAT lpNewFormat;
+   
+    /* allocate storage for new format entry */
+    lpNewFormat = (LPWINE_CLIPFORMAT) HeapAlloc(GetProcessHeap(), 
+        0, sizeof(WINE_CLIPFORMAT));
+
+    if(lpNewFormat == NULL) 
+    {
+        WARN("No more memory for a new format!\n");
+        return 0;
+    }
+
+    if (!(lpNewFormat->Name = HeapAlloc(GetProcessHeap(), 0, strlen(FormatName)+1)))
+    {
+        WARN("No more memory for the new format name!\n");
+        HeapFree(GetProcessHeap(), 0, lpNewFormat);
+        return 0;
+    }
+
+    strcpy(lpNewFormat->Name, FormatName);
+    lpNewFormat->wFlags = 0;
+    lpNewFormat->wFormatID = GlobalAddAtomA(lpNewFormat->Name);
+    lpNewFormat->drvData = TSXInternAtom(thread_display(), PropertyName, False);
+    lpNewFormat->lpDrvImportFunc = X11DRV_CLIPBOARD_ImportClipboardData;
+    lpNewFormat->lpDrvExportFunc = X11DRV_CLIPBOARD_ExportClipboardData;
+
+    /* Link Format */
+    lpFormat = ClipFormats;
+
+    while(lpFormat->NextFormat) /* Move to last entry */
+	lpFormat = lpFormat->NextFormat;
+
+    lpNewFormat->NextFormat = NULL;
+    lpFormat->NextFormat = lpNewFormat;
+    lpNewFormat->PrevFormat = lpFormat;
+
+    TRACE("Registering format(%d): %s drvData(%d): %s\n", 
+        lpNewFormat->wFormatID, 
+        FormatName,
+        lpNewFormat->drvData, 
+        PropertyName);
+
+    return lpNewFormat->wFormatID;
+}
+
+
+
+
+/**************************************************************************
+ *                      X11DRV_CLIPBOARD_GetClipboardInfo
+ */
+static BOOL X11DRV_CLIPBOARD_GetClipboardInfo(LPCLIPBOARDINFO cbInfo)
+{
+    BOOL bRet = FALSE;
+
+    SERVER_START_REQ( set_clipboard_info )
+    {
+        req->flags = 0;
+
+        if (wine_server_call_err( req ))
+        {
+            ERR("Failed to get clipboard owner.\n");
+        }
+        else
+        {
+            cbInfo->hWndOpen = reply->old_clipboard;
+            cbInfo->hWndOwner = reply->old_owner;
+            cbInfo->hWndViewer = reply->old_viewer;
+            cbInfo->seqno = reply->seqno;
+            cbInfo->flags = reply->flags;
+
+            bRet = TRUE;
+        }
+    }
+    SERVER_END_REQ;
+
+    return bRet;
+}
+
+
+/**************************************************************************
+ *	X11DRV_CLIPBOARD_ReleaseOwnership
+ */
+static BOOL X11DRV_CLIPBOARD_ReleaseOwnership(void)
+{
+    BOOL bRet = FALSE;
+
+    SERVER_START_REQ( set_clipboard_info )
+    {
+        req->flags = SET_CB_RELOWNER | SET_CB_SEQNO;
+
+        if (wine_server_call_err( req ))
+        {
+            ERR("Failed to set clipboard.\n");
+        }
+        else
+        {
+            bRet = TRUE;
+        }
+    }
+    SERVER_END_REQ;
+
+    return bRet;
+}
+
+
+
+/**************************************************************************
+ *                      X11DRV_CLIPBOARD_InsertClipboardData
+ *
+ * Caller *must* have the clipboard open and be the owner.
+ */
+static BOOL X11DRV_CLIPBOARD_InsertClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, DWORD flags)
+{
+    LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
+
+    TRACE("format=%d lpData=%p hData16=%08x hData32=%08x flags=0x%08lx\n", 
+        wFormat, lpData, hData16, (unsigned int)hData32, flags);
+
+    if (lpData)
+    {
+        X11DRV_CLIPBOARD_FreeData(lpData);
+
+        lpData->hData16 = hData16;  /* 0 is legal, see WM_RENDERFORMAT */
+        lpData->hData32 = hData32;
+    }
+    else
+    {
+        lpData = (LPWINE_CLIPDATA) HeapAlloc(GetProcessHeap(), 
+            0, sizeof(WINE_CLIPDATA));
+
+        lpData->wFormatID = wFormat;
+        lpData->hData16 = hData16;  /* 0 is legal, see WM_RENDERFORMAT */
+        lpData->hData32 = hData32;
+
+	if (ClipData)
+        {
+            LPWINE_CLIPDATA lpPrevData = ClipData->PrevData;
+
+            lpData->PrevData = lpPrevData;
+            lpData->NextData = ClipData;
+
+            lpPrevData->NextData = lpData;
+            ClipData->PrevData = lpData;
+        }
+        else
+        {
+            lpData->NextData = lpData;
+            lpData->PrevData = lpData;
+            ClipData = lpData;
+        }
+
+	ClipDataCount++;
+    }
+
+    lpData->wFlags = flags;
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *			X11DRV_CLIPBOARD_FreeData
+ *
+ * Free clipboard data handle.
+ */
+static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData)
+{
+    TRACE("%d\n", lpData->wFormatID);
+
+    if ((lpData->wFormatID >= CF_GDIOBJFIRST &&
+        lpData->wFormatID <= CF_GDIOBJLAST) || 
+        lpData->wFormatID == CF_BITMAP || 
+        lpData->wFormatID == CF_DIB || 
+        lpData->wFormatID == CF_PALETTE)
+    {
+      if (lpData->hData32)
+	DeleteObject(lpData->hData32);
+
+      if (lpData->hData16)
+	DeleteObject(HGDIOBJ_32(lpData->hData16));
+    }
+    else if (lpData->wFormatID == CF_METAFILEPICT)
+    {
+      if (lpData->hData32)
+      {
+        DeleteMetaFile(((METAFILEPICT *)GlobalLock( lpData->hData32 ))->hMF );
+        GlobalFree(lpData->hData32);
+
+	if (lpData->hData16)
+	  /* HMETAFILE16 and HMETAFILE32 are apparently the same thing,
+	     and a shallow copy is enough to share a METAFILEPICT
+	     structure between 16bit and 32bit clipboards.  The MetaFile
+	     should of course only be deleted once. */
+	  GlobalFree16(lpData->hData16);
+      }
+
+      if (lpData->hData16)
+      {
+        METAFILEPICT16* lpMetaPict = (METAFILEPICT16 *) GlobalLock16(lpData->hData16);
+
+        if (lpMetaPict)
+        {
+            DeleteMetaFile16(lpMetaPict->hMF);
+            lpMetaPict->hMF = 0;
+        }
+
+	GlobalFree16(lpData->hData16);
+      }
+    }
+    else if (lpData->wFormatID == CF_ENHMETAFILE)
+    {
+        if (lpData->hData32)
+            DeleteEnhMetaFile(lpData->hData32);
+    }
+    else if (lpData->wFormatID < CF_PRIVATEFIRST ||
+             lpData->wFormatID > CF_PRIVATELAST)
+    {
+      if (lpData->hData32)
+        GlobalFree(lpData->hData32);
+
+      if (lpData->hData16)
+	GlobalFree16(lpData->hData16);
+    }
+
+    lpData->hData16 = 0;
+    lpData->hData32 = 0;
+}
+
+
+/**************************************************************************
+ *			X11DRV_CLIPBOARD_UpdateCache
+ */
+static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo)
+{
+    BOOL bret = TRUE;
+
+    if (!X11DRV_CLIPBOARD_IsSelectionOwner())
+    {
+        if (!X11DRV_CLIPBOARD_GetClipboardInfo(lpcbinfo))
+        {
+            ERR("Failed to retrieve clipboard information.\n");
+            bret = FALSE;
+        }
+        else if (wSeqNo < lpcbinfo->seqno)
+        {
+            X11DRV_EmptyClipboard();
+
+            if (!X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo))
+            {
+                ERR("Failed to cache clipboard data owned by another process.\n");
+                bret = FALSE;
+            }
+            else
+            {
+                X11DRV_EndClipboardUpdate();
+            }
+
+            wSeqNo = lpcbinfo->seqno;
+        }
+    }
+
+    return bret;
+}
+
+
+/**************************************************************************
+ *			X11DRV_CLIPBOARD_RenderFormat
+ */
+static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData)
+{
+    BOOL bret = TRUE;
+
+    TRACE(" 0x%04x hData32(0x%08x) hData16(0x%08x)\n", 
+        lpData->wFormatID, (unsigned int)lpData->hData32, lpData->hData16);
+
+    if (lpData->hData32 || lpData->hData16)
+        return bret; /* Already rendered */
+
+    if (!X11DRV_CLIPBOARD_IsSelectionOwner())
+    {
+        if (!X11DRV_CLIPBOARD_ReadClipboardData(lpData->wFormatID))
+        {
+            ERR("Failed to cache clipboard data owned by another process. Format=%d\n", 
+                lpData->wFormatID);
+            bret = FALSE;
+        }
+    }
+    else
+    {
+        if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
+            bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData);
+        else
+        {
+            CLIPBOARDINFO cbInfo;
+
+            if (X11DRV_CLIPBOARD_GetClipboardInfo(&cbInfo) &&
+                cbInfo.hWndOwner)
+            {
+                /* Send a WM_RENDERFORMAT message to notify the owner to render the
+                 * data requested into the clipboard.
+                 */
+                TRACE("Sending WM_RENDERFORMAT message to hwnd(%p)\n", cbInfo.hWndOwner);
+                SendMessageW(cbInfo.hWndOwner, WM_RENDERFORMAT, (WPARAM)lpData->wFormatID, 0);
+
+	        if (!lpData->hData32 && !lpData->hData16)
+                    bret = FALSE;
+            }
+            else
+            {
+                ERR("hWndClipOwner is lost!\n");
+                bret = FALSE;
+            }
+        }
+    }
+
+    return bret;
+}
+
+
+/**************************************************************************
+ *                      CLIPBOARD_ConvertText
+ * Returns number of required/converted characters - not bytes!
+ */
+static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size,
+				 WORD dst_fmt, void *dst, INT dst_size)
+{
+    UINT cp;
+
+    if(src_fmt == CF_UNICODETEXT)
+    {
+	switch(dst_fmt)
+	{
+	case CF_TEXT:
+	    cp = CP_ACP;
+	    break;
+	case CF_OEMTEXT:
+	    cp = CP_OEMCP;
+	    break;
+	default:
+	    return 0;
+	}
+	return WideCharToMultiByte(cp, 0, src, src_size, dst, dst_size, NULL, NULL);
+    }
+
+    if(dst_fmt == CF_UNICODETEXT)
+    {
+	switch(src_fmt)
+	{
+	case CF_TEXT:
+	    cp = CP_ACP;
+	    break;
+	case CF_OEMTEXT:
+	    cp = CP_OEMCP;
+	    break;
+	default:
+	    return 0;
+	}
+	return MultiByteToWideChar(cp, 0, src, src_size, dst, dst_size);
+    }
+
+    if(!dst_size) return src_size;
+
+    if(dst_size > src_size) dst_size = src_size;
+
+    if(src_fmt == CF_TEXT )
+	CharToOemBuffA(src, dst, dst_size);
+    else
+	OemToCharBuffA(src, dst, dst_size);
+
+    return dst_size;
+}
+
+
+/**************************************************************************
+ *                      X11DRV_CLIPBOARD_RenderSynthesizedFormat
+ */
+static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData)
+{
+    BOOL bret = FALSE;
+
+    if (lpData->wFlags & CF_FLAG_SYNTHESIZED)
+    {
+        UINT wFormatID = lpData->wFormatID;
+
+        if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
+            bret = X11DRV_CLIPBOARD_RenderText(wFormatID);
+        else 
+        {
+            switch (wFormatID)
+	    {
+                case CF_ENHMETAFILE:
+                case CF_METAFILEPICT:
+                case CF_DIB:
+                case CF_BITMAP:
+		    FIXME("Synthesizing wFormatID(0x%08x) not implemented\n", wFormatID);
+                    break;
+
+                default:
+		    FIXME("Called to synthesize unknown format\n");
+                    break;
+            }
+        }
+
+        lpData->wFlags &= ~CF_FLAG_SYNTHESIZED;
+    }
+
+    return bret;
+}
+
+
+/**************************************************************************
+ *                      X11DRV_CLIPBOARD_RenderText
+ *
+ * Renders text to the clipboard buffer converting between UNIX and DOS formats.
+ *
+ * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
+ *
+ */
+static BOOL X11DRV_CLIPBOARD_RenderText(UINT wFormatID)
+{
+    LPCSTR lpstrS;
+    LPSTR  lpstrT;
+    HANDLE hData32;
+    INT src_chars, dst_chars, alloc_size;
+    LPWINE_CLIPDATA lpSource = NULL;
+
+    TRACE(" %d\n", wFormatID);
+
+    if (X11DRV_CLIPBOARD_LookupData(wFormatID))
+        return TRUE;
+
+    if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)))
+    {
+        TRACE("UNICODETEXT -> %d\n", wFormatID);
+    }
+    else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)))
+    {
+        TRACE("TEXT -> %d\n", wFormatID);
+    }
+    else if ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)))
+    {
+        TRACE("OEMTEXT -> %d\n", wFormatID);
+    }
+
+    if (!lpSource)
+        return FALSE;
+
+    /* First render the source text format */
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpSource))
+        return FALSE;
+
+    if (lpSource->hData32)
+    {
+        lpstrS = (LPSTR)GlobalLock(lpSource->hData32);
+    }
+    else
+    {
+        lpstrS = (LPSTR)GlobalLock16(lpSource->hData16);
+    }
+
+    if (!lpstrS)
+        return FALSE;
+
+    /* Text always NULL terminated */
+    if(lpSource->wFormatID == CF_UNICODETEXT)
+        src_chars = strlenW((LPCWSTR)lpstrS) + 1;
+    else
+        src_chars = strlen(lpstrS) + 1;
+
+    /* Calculate number of characters in the destination buffer */
+    dst_chars = CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, 
+        src_chars, wFormatID, NULL, 0);
+
+    if (!dst_chars)
+        return FALSE;
+
+    TRACE("Converting from '%d' to '%d', %i chars\n",
+    	lpSource->wFormatID, wFormatID, src_chars);
+
+    /* Convert characters to bytes */
+    if(wFormatID == CF_UNICODETEXT)
+        alloc_size = dst_chars * sizeof(WCHAR);
+    else
+        alloc_size = dst_chars;
+
+    hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | 
+        GMEM_DDESHARE, alloc_size);
+
+    lpstrT = (LPSTR)GlobalLock(hData32);
+
+    if (lpstrT)
+    {
+        CLIPBOARD_ConvertText(lpSource->wFormatID, lpstrS, src_chars,
+            wFormatID, lpstrT, dst_chars);
+        GlobalUnlock(hData32);
+    }
+
+    /* Unlock source */
+    if (lpSource->hData32)
+        GlobalUnlock(lpSource->hData32);
+    else
+        GlobalUnlock16(lpSource->hData16);
+
+    return X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, hData32, 0);
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ImportXAString
+ *
+ *  Import XA_STRING, converting the string to CF_UNICODE.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportXAString(LPBYTE lpdata, UINT cBytes)
+{
+    LPSTR lpstr;
+    UINT i, inlcount = 0;
+    HANDLE hUnicodeText = 0;
+
+    for (i = 0; i <= cBytes; i++)
+    {
+        if (lpdata[i] == '\n')
+            inlcount++;
+    }
+
+    if ((lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes + inlcount + 1)))
+    {
+        UINT count;
+        UINT text_cp = CP_ACP;
+
+        for (i = 0, inlcount = 0; i <= cBytes; i++)
+        {
+            if (lpdata[i] == '\n')
+                lpstr[inlcount++] = '\r';
+
+            lpstr[inlcount++] = lpdata[i];
+        }
+
+        GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTUNIXCODEPAGE | 
+            LOCALE_RETURN_NUMBER, (WCHAR *)&text_cp, (sizeof(UINT)/sizeof(WCHAR)));
+
+	count = MultiByteToWideChar(text_cp, 0, lpstr, -1, NULL, 0);
+	hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
+
+	if(hUnicodeText)
+	{
+            WCHAR *textW = GlobalLock(hUnicodeText);
+            MultiByteToWideChar(text_cp, 0, lpstr, -1, textW, count);
+            GlobalUnlock(hUnicodeText);
+        }
+
+        HeapFree(GetProcessHeap(), 0, lpstr);
+    }
+
+    return hUnicodeText;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ImportXAPIXMAP
+ *
+ *  Import XA_PIXMAP, converting the image to CF_DIB.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(LPBYTE lpdata, UINT cBytes)
+{
+    HANDLE hTargetImage = 0;  /* Handle to store the converted DIB */
+    Pixmap *pPixmap = (Pixmap *) lpdata;
+    HWND hwnd = GetOpenClipboardWindow();
+    HDC hdc = GetDC(hwnd);
+
+    hTargetImage = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc, TRUE);
+
+    ReleaseDC(hwnd, hdc);
+
+    return hTargetImage;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ImportMetaFilePict
+ *
+ *  Import MetaFilePict.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(LPBYTE lpdata, UINT cBytes)
+{
+    return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
+}
+
+
+/**************************************************************************
+ *		X11DRV_ImportEnhMetaFile
+ *
+ *  Import EnhMetaFile.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes)
+{
+    return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata, (LPDWORD)&cBytes, FALSE);
+}
+
+
+/**************************************************************************
+ *		X11DRV_ImportClipbordaData
+ *
+ *  Generic import clipboard data routine.
+ */
+HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes)
+{
+    LPVOID lpClipData;
+    HANDLE hClipData = 0;
+
+    if (cBytes)
+    {
+        /* Turn on the DDESHARE flag to enable shared 32 bit memory */
+        hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
+        if ((lpClipData = GlobalLock(hClipData)))
+        {
+            memcpy(lpClipData, lpdata, cBytes);
+            GlobalUnlock(hClipData);
+        }
+        else
+            hClipData = 0;
+    }
+
+    return hClipData;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ExportClipboardData
+ *
+ *  Generic export clipboard data routine.
+ */
+HANDLE X11DRV_CLIPBOARD_ExportClipboardData(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
+{
+    LPVOID lpClipData;
+    UINT cBytes = 0;
+    HANDLE hClipData = 0;
+
+    *lpBytes = 0; /* Assume failure */
+
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpData))
+        ERR("Failed to export %d format\n", lpData->wFormatID);
+    else
+    {
+        cBytes = GlobalSize(lpData->hData32);
+
+        hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes);
+
+        if ((lpClipData = GlobalLock(hClipData)))
+        {
+            LPVOID lpdata = GlobalLock(lpData->hData32);
+
+            memcpy(lpClipData, lpdata, cBytes);
+	    *lpBytes = cBytes;
+
+            GlobalUnlock(lpData->hData32);
+            GlobalUnlock(hClipData);
+        }
+    }
+
+    return hClipData;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ExportXAString
+ *
+ *  Export CF_UNICODE converting the string to XA_STRING
+ */
+HANDLE X11DRV_CLIPBOARD_ExportXAString(LPWINE_CLIPDATA lpData, LPDWORD lpBytes)
+{
+    INT i, j;
+    UINT size;
+    LPWSTR uni_text;
+    LPSTR text, lpstr;
+    UINT text_cp = CP_ACP;
+
+    *lpBytes = 0; /* Assume return has zero bytes */
+
+    GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTUNIXCODEPAGE | 
+        LOCALE_RETURN_NUMBER, (WCHAR *)&text_cp, (sizeof(UINT)/sizeof(WCHAR)));
+
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpData))
+    {
+        ERR("Failed to export %d format\n", lpData->wFormatID);
+        return 0;
+    }
+
+    uni_text = GlobalLock(lpData->hData32);
+
+    size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
+
+    text = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!text)
+       return None;
+    WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
+
+    /* remove carriage returns */
+
+    lpstr = (char*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size-- );
+    if(lpstr == NULL) return None;
+    for(i = 0,j = 0; i < size && text[i]; i++ )
+    {
+        if( text[i] == '\r' &&
+            (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
+        lpstr[j++] = text[i];
+    }
+    lpstr[j]='\0';
+
+    *lpBytes = j; /* Number of bytes in string */
+
+    HeapFree(GetProcessHeap(), 0, text);
+    GlobalUnlock(lpData->hData32);
+
+    return lpstr;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ExportXAPIXMAP
+ *
+ *  Export CF_DIB to XA_PIXMAP.
+ */
+HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
+{
+    HDC hdc;
+    Pixmap pixmap;
+
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
+    {
+        ERR("Failed to export %d format\n", lpdata->wFormatID);
+        return 0;
+    }
+
+    hdc = GetDC(0);
+
+    /* For convert from packed DIB to Pixmap */
+    pixmap = X11DRV_DIB_CreatePixmapFromDIB(lpdata, hdc);
+    *lpBytes = 4; /* pixmap is a 32bit value */
+
+    ReleaseDC(0, hdc);
+
+    return (HANDLE) pixmap;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ExportMetaFilePict
+ *
+ *  Export MetaFilePict.
+ */
+HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
+{
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
+    {
+        ERR("Failed to export %d format\n", lpdata->wFormatID);
+        return 0;
+    }
+
+    return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata->hData32, 
+        lpBytes, TRUE);
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_ExportEnhMetaFile
+ *
+ *  Export EnhMetaFile.
+ */
+HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(LPWINE_CLIPDATA lpdata, LPDWORD lpBytes)
+{
+    if (!X11DRV_CLIPBOARD_RenderFormat(lpdata))
+    {
+        ERR("Failed to export %d format\n", lpdata->wFormatID);
+        return 0;
+    }
+
+    return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata->hData32, 
+        lpBytes, TRUE);
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_QueryTargets
+ */
+static BOOL X11DRV_CLIPBOARD_QueryTargets(Display *display, Window w, Atom selection, XEvent *xe)
+{
+    INT i;
+    Bool res;
+
+    wine_tsx11_lock();
+    XConvertSelection(display, selection, xaTargets, xaSelectionData, w, CurrentTime);
+    wine_tsx11_unlock();
+
+    /*
+     * Wait until SelectionNotify is received
+     */
+    for (i = 0; i < SELECTION_RETRIES; i++)
+    {
+        wine_tsx11_lock();
+        res = XCheckTypedWindowEvent(display, w, SelectionNotify, xe);
+        wine_tsx11_unlock();
+        if (res && xe->xselection.selection == selection) break;
+
+        usleep(SELECTION_WAIT);
+    }
+
+    /* Verify that the selection returned a valid TARGETS property */
+    if ((xe->xselection.target != xaTargets) || (xe->xselection.property == None))
+    {
+        /* Selection owner failed to respond or we missed the SelectionNotify */
+        WARN("Failed to retrieve TARGETS for selection %ld.\n", selection);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *		X11DRV_CLIPBOARD_QueryAvailableData
  *
  * Caches the list of data formats available from the current selection.
  * This queries the selection owner for the TARGETS property and saves all
  * reported property types.
  */
-int X11DRV_CLIPBOARD_CacheDataFormats( Atom SelectionName )
+static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo)
 {
     Display *display = thread_display();
-    HWND           hWnd = 0;
-    HWND           hWndClipWindow = GetOpenClipboardWindow();
     XEvent         xe;
-    Atom           aTargets;
     Atom           atype=AnyPropertyType;
     int		   aformat;
     unsigned long  remain;
     Atom*	   targetList=NULL;
     Window         w;
-    Window         ownerSelection = 0;
-    time_t         maxtm;
+    HWND           hWndClipWindow; 
+    unsigned long  cSelectionTargets = 0;
 
-    TRACE("enter\n");
-    /*
-     * Empty the clipboard cache
-     */
-    CLIPBOARD_EmptyCache(TRUE);
+    if (selectionAcquired & (S_PRIMARY | S_CLIPBOARD))
+    {
+        ERR("Received request to cache selection but process is owner=(%08x)\n", 
+            (unsigned) selectionWindow);
 
-    cSelectionTargets = 0;
-    selectionCacheSrc = SelectionName;
+        selectionAcquired  = S_NOSELECTION;
 
-    hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
+        if (TSXGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
+	    selectionAcquired |= S_PRIMARY;
 
-    ownerSelection = TSXGetSelectionOwner(display, SelectionName);
-    if ( !hWnd || (ownerSelection == None) )
-        return cSelectionTargets;
+        if (TSXGetSelectionOwner(display,xaClipboard) == selectionWindow)
+	    selectionAcquired |= S_CLIPBOARD;
+
+        if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
+        {
+            WARN("Lost selection but process didn't process SelectClear\n");
+            selectionWindow = None;
+        }
+	else
+	{
+            return 0; /* Prevent self request */
+	}
+    }
+
+    if (lpcbinfo->flags & CB_OWNER)
+        hWndClipWindow = lpcbinfo->hWndOwner;
+    else if (lpcbinfo->flags & CB_OPEN)
+        hWndClipWindow = lpcbinfo->hWndOpen;
+    else
+        hWndClipWindow = GetActiveWindow();
+
+    if (!hWndClipWindow)
+    {
+        WARN("No window available to retrieve selection!n");
+        return 0;
+    }
+
+    w = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
 
     /*
      * Query the selection owner for the TARGETS property
      */
-    w = X11DRV_get_whole_window( GetAncestor(hWnd,GA_ROOT) );
-
-    aTargets = TSXInternAtom(display, "TARGETS", False);
-
-    TRACE("Requesting TARGETS selection for '%s' (owner=%08x)...\n",
-          TSXGetAtomName(display, selectionCacheSrc), (unsigned)ownerSelection );
-    wine_tsx11_lock();
-    XConvertSelection(display, selectionCacheSrc, aTargets,
-                    TSXInternAtom(display, "SELECTION_DATA", False),
-                    w, CurrentTime);
-
-    /*
-     * Wait until SelectionNotify is received
-     */
-    maxtm = time(NULL) + MAXSELECTIONNOTIFYWAIT; /* Timeout after a maximum wait */
-    while( maxtm - time(NULL) > 0 )
-    {
-       if( XCheckTypedWindowEvent(display, w, SelectionNotify, &xe) )
-           if( xe.xselection.selection == selectionCacheSrc )
-               break;
-    }
-    wine_tsx11_unlock();
-
-    /* Verify that the selection returned a valid TARGETS property */
-    if ( (xe.xselection.target != aTargets)
-          || (xe.xselection.property == None) )
-    {
-        TRACE("\tExit, could not retrieve TARGETS\n");
-        return cSelectionTargets;
-    }
+    if (X11DRV_CLIPBOARD_QueryTargets(display, w, XA_PRIMARY, &xe))
+        selectionCacheSrc = XA_PRIMARY;
+    else if (X11DRV_CLIPBOARD_QueryTargets(display, w, xaClipboard, &xe))
+        selectionCacheSrc = xaClipboard;
+    else
+        return 0;
 
     /* Read the TARGETS property contents */
     if(TSXGetWindowProperty(display, xe.xselection.requestor, xe.xselection.property,
-                            0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat,
-                            &cSelectionTargets, &remain, (unsigned char**)&targetList) != Success)
-        TRACE("\tCouldn't read TARGETS property\n");
+        0, 0x3FFF, True, AnyPropertyType/*XA_ATOM*/, &atype, &aformat, &cSelectionTargets, 
+        &remain, (unsigned char**)&targetList) != Success)
+    {
+        WARN("Failed to read TARGETS property\n");
+    }
     else
     {
-       TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
+       TRACE("Type %s,Format %d,nItems %ld, Remain %ld\n",
              TSXGetAtomName(display,atype),aformat,cSelectionTargets, remain);
        /*
         * The TARGETS property should have returned us a list of atoms
         * corresponding to each selection target format supported.
         */
-       if( (atype == XA_ATOM || atype == aTargets) && aformat == 32 )
+       if ((atype == XA_ATOM || atype == xaTargets) && aformat == 32)
        {
-          int i;
-          LPWINE_CLIPFORMAT lpFormat;
+          INT i;
 
           /* Cache these formats in the clipboard cache */
-
           for (i = 0; i < cSelectionTargets; i++)
           {
-              char *itemFmtName = TSXGetAtomName(display, targetList[i]);
-              UINT wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
+              LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]);
 
-              /*
-               * If the clipboard format maps to a Windows format, simply store
-               * the atom identifier and record its availablity status
-               * in the clipboard cache.
-               */
-              if (wFormat)
+              if (!lpFormat)
+                  lpFormat = X11DRV_CLIPBOARD_LookupAliasProperty(targetList[i]);
+
+              if (!lpFormat)
               {
-                  lpFormat = CLIPBOARD_LookupFormat( wFormat );
+                  LPSTR lpName = TSXGetAtomName(display, targetList[i]); 
+                  X11DRV_RegisterClipboardFormat(lpName);
 
-                  /* Don't replace if the property already cached is a native format,
-                   * or if a PIXMAP is being replaced by a BITMAP.
-                   */
-                  if (lpFormat->wDataPresent &&
-                        ( X11DRV_CLIPBOARD_IsNativeProperty(lpFormat->drvData)
-                          || (lpFormat->drvData == XA_PIXMAP && targetList[i] == XA_BITMAP) )
-                     )
+                  lpFormat = X11DRV_CLIPBOARD_LookupProperty(targetList[i]);
+
+		  if (!lpFormat)
                   {
-                      TRACE("\tAtom# %d: '%s' --> FormatID(%d) %s (Skipped)\n",
-                            i, itemFmtName, wFormat, lpFormat->Name);
+                      ERR("Failed to cache %s property\n", lpName);
+                      continue;
                   }
-                  else
-                  {
-                      lpFormat->wDataPresent = 1;
-                      lpFormat->drvData = targetList[i];
-                      TRACE("\tAtom# %d: '%s' --> FormatID(%d) %s\n",
-                            i, itemFmtName, wFormat, lpFormat->Name);
-                  }
+
+                  TSXFree(lpName);
               }
 
-              TSXFree(itemFmtName);
+              TRACE("Atom#%d Property(%d): --> FormatID(%d) %s\n",
+                  i, lpFormat->drvData, lpFormat->wFormatID, lpFormat->Name);
+
+              X11DRV_CLIPBOARD_InsertClipboardData(lpFormat->wFormatID, 0, 0, 0);
           }
        }
 
@@ -496,6 +1354,109 @@
     return cSelectionTargets;
 }
 
+
+/**************************************************************************
+ *	X11DRV_CLIPBOARD_ReadClipboardData
+ *
+ * This method is invoked only when we DO NOT own the X selection
+ *
+ * We always get the data from the selection client each time,
+ * since we have no way of determining if the data in our cache is stale.
+ */
+static BOOL X11DRV_CLIPBOARD_ReadClipboardData(UINT wFormat)
+{
+    Display *display = thread_display();
+    BOOL bRet = FALSE;
+    Bool res;
+
+    HWND hWndClipWindow = GetOpenClipboardWindow();
+    HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
+
+    LPWINE_CLIPFORMAT lpFormat;
+
+    TRACE("%d\n", wFormat);
+
+    if (!selectionAcquired)
+    {
+        Window w = X11DRV_get_whole_window(GetAncestor(hWnd, GA_ROOT));
+        if(!w)
+        {
+            FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow);
+            return FALSE;
+        }
+
+        lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
+
+        if (lpFormat->drvData)
+        {
+    	    DWORD i;
+	    UINT alias;
+            XEvent xe;
+
+            TRACE("Requesting %s selection (%d) from win(%08x)\n", 
+                lpFormat->Name, lpFormat->drvData, (UINT)selectionCacheSrc);
+
+            wine_tsx11_lock();
+            XConvertSelection(display, selectionCacheSrc, lpFormat->drvData,
+                              xaSelectionData, w, CurrentTime);
+            wine_tsx11_unlock();
+
+            /* wait until SelectionNotify is received */
+            for (i = 0; i < SELECTION_RETRIES; i++)
+            {
+                wine_tsx11_lock();
+                res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
+                wine_tsx11_unlock();
+                if (res && xe.xselection.selection == selectionCacheSrc) break;
+
+                usleep(SELECTION_WAIT);
+            }
+
+            /* If the property wasn't available check for aliases */
+	    if (xe.xselection.property == None &&
+                (alias = X11DRV_CLIPBOARD_LookupPropertyAlias(lpFormat->drvData)))
+	    {
+                wine_tsx11_lock();
+                XConvertSelection(display, selectionCacheSrc, alias,
+                                  xaSelectionData, w, CurrentTime);
+                wine_tsx11_unlock();
+
+                /* wait until SelectionNotify is received */
+                for (i = 0; i < SELECTION_RETRIES; i++)
+                {
+                    wine_tsx11_lock();
+                    res = XCheckTypedWindowEvent(display, w, SelectionNotify, &xe);
+                    wine_tsx11_unlock();
+                    if (res && xe.xselection.selection == selectionCacheSrc) break;
+
+                    usleep(SELECTION_WAIT);
+                }
+	    }
+
+            /* Verify that the selection returned a valid TARGETS property */
+            if (xe.xselection.property != None)
+            {
+                /*
+                 *  Read the contents of the X selection property 
+                 *  into WINE's clipboard cache converting the 
+                 *  selection to be compatible if possible.
+                 */
+                bRet = X11DRV_CLIPBOARD_ReadSelection(lpFormat, xe.xselection.requestor, 
+                    xe.xselection.property);
+            }
+        }
+    }
+    else
+    {
+        ERR("Received request to cache selection data but process is owner\n");
+    }
+
+    TRACE("Returning %d\n", bRet);
+
+    return bRet;
+}
+
+
 /**************************************************************************
  *		X11DRV_CLIPBOARD_ReadSelection
  *  Reads the contents of the X selection property into the WINE clipboard cache
@@ -504,7 +1465,7 @@
  *  This method is invoked only to read the contents of a the selection owned
  *  by an external application. i.e. when we do not own the X selection.
  */
-static BOOL X11DRV_CLIPBOARD_ReadSelection(UINT wFormat, Window w, Atom prop, Atom reqType)
+static BOOL X11DRV_CLIPBOARD_ReadSelection(LPWINE_CLIPFORMAT lpData, Window w, Atom prop)
 {
     Display *display = thread_display();
     Atom	      atype=AnyPropertyType;
@@ -513,236 +1474,153 @@
     long              lRequestLength,bwc;
     unsigned char*    val;
     unsigned char*    buffer;
-    LPWINE_CLIPFORMAT lpFormat;
     BOOL              bRet = FALSE;
-    HWND              hWndClipWindow = GetOpenClipboardWindow();
-
 
     if(prop == None)
         return bRet;
 
-    TRACE("Reading X selection...\n");
-
-    TRACE("\tretrieving property %s from window %ld into %s\n",
-          TSXGetAtomName(display,reqType), (long)w, TSXGetAtomName(display,prop) );
+    TRACE("Reading X selection type %s\n", lpData->Name);
 
     /*
      * First request a zero length in order to figure out the request size.
      */
-    if(TSXGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType/*reqType*/,
-                            &atype, &aformat, &nitems, &itemSize, &val) != Success)
+    if(TSXGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
+        &atype, &aformat, &nitems, &itemSize, &val) != Success)
     {
-        WARN("\tcouldn't get property size\n");
+        WARN("Failed to get property size\n");
         return bRet;
     }
 
     /* Free zero length return data if any */
-    if ( val )
+    if (val)
     {
        TSXFree(val);
        val = NULL;
     }
 
-    TRACE("\tretrieving %ld bytes...\n", itemSize * aformat/8);
+    TRACE("Retrieving %ld bytes\n", itemSize * aformat/8);
+
     lRequestLength = (itemSize * aformat/8)/4  + 1;
+    bwc = aformat/8;
 
-   bwc = aformat/8;
-   /* we want to read the property, but not it too large of chunks or
-      we could hang the cause problems. Lets go for 4k blocks */
-
-    if(TSXGetWindowProperty(display,w,prop,0,4096,False,
-                            AnyPropertyType/*reqType*/,
-                            &atype, &aformat, &nitems, &remain, &buffer)
-        != Success)
+    /* Read property in 4K blocks */
+    if (TSXGetWindowProperty(display,w,prop,0,4096,False, AnyPropertyType/*reqType*/, 
+        &atype, &aformat, &nitems, &remain, &buffer) != Success)
     {
-        WARN("\tcouldn't read property\n");
+        WARN("Failed to read property\n");
         return bRet;
     }
-   val = (char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
-                          nitems*bwc);
-   memcpy(val,buffer,nitems*bwc);
-   TSXFree(buffer);
 
-   for (total = nitems*bwc,val_cnt=0; remain;)
-   {
+    val = (char*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nitems*bwc);
+    memcpy(val,buffer,nitems*bwc);
+
+    TSXFree(buffer);
+
+    for (total = nitems*bwc, val_cnt = 0; remain;)
+    {
        val_cnt +=nitems*bwc;
-       TSXGetWindowProperty(display, w, prop,
-                          (total / 4), 4096, False,
-                          AnyPropertyType, &atype,
-                          &aformat, &nitems, &remain,
-                          &buffer);
+       if (TSXGetWindowProperty(display, w, prop, (total / 4), 4096, False,
+           AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
+       {
+           WARN("Failed to read property\n");
+           HeapFree(GetProcessHeap(), 0, val);
+           return bRet;
+       }
 
        total += nitems*bwc;
        HeapReAlloc(GetProcessHeap(),0,val, total);
        memcpy(&val[val_cnt], buffer, nitems*(aformat/8));
        TSXFree(buffer);
-   }
-   nitems = total;
-
-    /*
-     * Translate the X property into the appropriate Windows clipboard
-     * format, if possible.
-     */
-    if ( (reqType == XA_STRING)
-         && (atype == XA_STRING) && (aformat == 8) )
-    /* convert Unix text to CF_UNICODETEXT */
-    {
-      int 	   i,inlcount = 0;
-      char*      lpstr;
-
-      for(i=0; i <= nitems; i++)
-          if( val[i] == '\n' ) inlcount++;
-
-      if( (lpstr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nitems + inlcount + 1)) )
-      {
-	  static UINT text_cp = (UINT)-1;
-	  UINT count;
-	  HANDLE hUnicodeText;
-
-          for(i=0,inlcount=0; i <= nitems; i++)
-          {
-             if( val[i] == '\n' ) lpstr[inlcount++]='\r';
-             lpstr[inlcount++]=val[i];
-          }
-
-	  if(text_cp == (UINT)-1)
-	  {
-	      HKEY hkey;
-	      /* default value */
-	      text_cp = CP_ACP;
-	      if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
-	      {
-	          char buf[20];
-		  DWORD type, count = sizeof(buf);
-		  if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
-		      text_cp = atoi(buf);
-		  RegCloseKey(hkey);
-	      }
-	  }
-
-	  count = MultiByteToWideChar(text_cp, 0, lpstr, -1, NULL, 0);
-	  hUnicodeText = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, count * sizeof(WCHAR));
-	  if(hUnicodeText)
-	  {
-	      WCHAR *textW = GlobalLock(hUnicodeText);
-	      MultiByteToWideChar(text_cp, 0, lpstr, -1, textW, count);
-	      GlobalUnlock(hUnicodeText);
-	      if (!SetClipboardData(CF_UNICODETEXT, hUnicodeText))
-	      {
-                  ERR("Not SET! Need to free our own block\n");
-                  GlobalFree(hUnicodeText);
-              }
-	      bRet = TRUE;
-	  }
-	  HeapFree(GetProcessHeap(), 0, lpstr);
-      }
-    }
-    else if ( reqType == XA_PIXMAP || reqType == XA_BITMAP ) /* treat PIXMAP as CF_DIB or CF_BITMAP */
-    {
-      /* Get the first pixmap handle passed to us */
-      Pixmap *pPixmap = (Pixmap *)val;
-      HANDLE hTargetImage = 0;  /* Handle to store the converted bitmap or DIB */
-
-      if (aformat != 32 || nitems < 1 || atype != XA_PIXMAP
-          || (wFormat != CF_BITMAP && wFormat != CF_DIB))
-      {
-          WARN("\tUnimplemented format conversion request\n");
-          goto END;
-      }
-
-      if ( wFormat == CF_BITMAP )
-      {
-        /* For CF_BITMAP requests we must return an HBITMAP */
-        hTargetImage = X11DRV_BITMAP_CreateBitmapFromPixmap(*pPixmap, TRUE);
-      }
-      else if (wFormat == CF_DIB)
-      {
-        HWND hwnd = GetOpenClipboardWindow();
-        HDC hdc = GetDC(hwnd);
-
-        /* For CF_DIB requests we must return an HGLOBAL storing a packed DIB */
-        hTargetImage = X11DRV_DIB_CreateDIBFromPixmap(*pPixmap, hdc, TRUE);
-
-        ReleaseDC(hwnd, hdc);
-      }
-
-      if (!hTargetImage)
-      {
-          WARN("PIXMAP conversion failed!\n" );
-          goto END;
-      }
-
-      /* Delete previous clipboard data */
-      lpFormat = CLIPBOARD_LookupFormat(wFormat);
-      if (lpFormat->wDataPresent && (lpFormat->hData16 || lpFormat->hData32))
-          CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
-
-      /* Update the clipboard record */
-      lpFormat->wDataPresent = 1;
-      lpFormat->hData32 = hTargetImage;
-      lpFormat->hData16 = 0;
-
-      bRet = TRUE;
     }
 
-    /* For native properties simply copy the X data without conversion */
-    else if (X11DRV_CLIPBOARD_IsNativeProperty(reqType)) /* <WCF>* */
-    {
-      HANDLE hClipData = 0;
-      void*  lpClipData;
-      int cBytes = nitems * aformat/8;
+    bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, 0, lpData->lpDrvImportFunc(val, total), 0);
 
-      if( cBytes )
-      {
-          if (wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE)
-          {
-              hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, (HANDLE)val, cBytes, FALSE);
-          }
-          else
-          {
-              /* Turn on the DDESHARE flag to enable shared 32 bit memory */
-              hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cBytes );
-              if( (lpClipData = GlobalLock(hClipData)) )
-              {
-                  memcpy(lpClipData, val, cBytes);
-                  GlobalUnlock(hClipData);
-              }
-              else
-                  hClipData = 0;
-          }
-      }
-
-      if( hClipData )
-      {
-          /* delete previous clipboard record if any */
-          lpFormat = CLIPBOARD_LookupFormat(wFormat);
-          if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32)
-              CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow));
-
-          /* Update the clipboard record */
-          lpFormat->wDataPresent = 1;
-          lpFormat->hData32 = hClipData;
-          lpFormat->hData16 = 0;
-
-          bRet = TRUE;
-      }
-    }
-    else
-    {
-        WARN("\tUnimplemented format conversion request\n");
-        goto END;
-    }
-
-END:
     /* Delete the property on the window now that we are done
      * This will send a PropertyNotify event to the selection owner. */
     TSXDeleteProperty(display,w,prop);
 
     /* Free the retrieved property data */
     HeapFree(GetProcessHeap(),0,val);
+
     return bRet;
 }
 
+
+/**************************************************************************
+ *		CLIPBOARD_SerializeMetafile
+ */
+static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out)
+{
+    HANDLE h = 0;
+
+    TRACE(" wFormat=%d hdata=%08x out=%d\n", wformat, (unsigned int) hdata, out);
+
+    if (out) /* Serialize out, caller should free memory */
+    {
+        *lpcbytes = 0; /* Assume failure */
+
+        if (wformat == CF_METAFILEPICT)
+        {
+            LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
+            int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
+
+            h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
+            if (h)
+            {
+                char *pdata = GlobalLock(h);
+
+                memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
+                GetMetaFileBitsEx(lpmfp->hMF, size, pdata + sizeof(METAFILEPICT));
+
+                *lpcbytes = size + sizeof(METAFILEPICT);
+
+                GlobalUnlock(h);
+            }
+
+            GlobalUnlock(hdata);
+        }
+        else if (wformat == CF_ENHMETAFILE)
+        {
+            int size = GetEnhMetaFileBits(hdata, 0, NULL);
+
+            h = GlobalAlloc(0, size);
+            if (h)
+            {
+                LPVOID pdata = GlobalLock(h);
+
+                GetEnhMetaFileBits(hdata, size, pdata);
+                *lpcbytes = size;
+
+                GlobalUnlock(h);
+            }
+        }
+    }
+    else
+    {
+        if (wformat == CF_METAFILEPICT)
+        {
+            h = GlobalAlloc(0, sizeof(METAFILEPICT));
+            if (h)
+            {
+                LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
+
+                memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
+                pmfp->hMF = SetMetaFileBitsEx(*lpcbytes - sizeof(METAFILEPICT),
+                                              (char *)hdata + sizeof(METAFILEPICT));
+
+                GlobalUnlock(h);
+            }
+        }
+        else if (wformat == CF_ENHMETAFILE)
+        {
+            h = SetEnhMetaFileBits(*lpcbytes, (LPVOID)hdata);
+        }
+    }
+
+    return h;
+}
+
+
 /**************************************************************************
  *		X11DRV_CLIPBOARD_ReleaseSelection
  *
@@ -754,87 +1632,92 @@
 void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
 {
     Display *display = thread_display();
-    Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
-    int clearAllSelections = 0;
-    HKEY hkey;
-
-    if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Clipboard", &hkey))
-    {
-	char buffer[20];
-	DWORD type, count = sizeof(buffer);
-	if(!RegQueryValueExA(hkey, "ClearAllSelections", 0, &type, buffer, &count))
-	    clearAllSelections = atoi(buffer);
-        RegCloseKey(hkey);
-    }
 
     /* w is the window that lost the selection
-     * selectionPrevWindow is nonzero if CheckSelection() was called.
      */
+    TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n",
+	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionAcquired);
 
-    TRACE("\tevent->window = %08x (sw = %08x, spw=%08x)\n",
-	  (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow );
-
-    if( selectionAcquired )
+    if (selectionAcquired)
     {
-	if( w == selectionWindow || selectionPrevWindow == None)
-	{
+	if (w == selectionWindow)
+        {
             /* If we're losing the CLIPBOARD selection, or if the preferences in .winerc
              * dictate that *all* selections should be cleared on loss of a selection,
              * we must give up all the selections we own.
              */
-            if ( clearAllSelections || (selType == xaClipboard) )
+            if (clearAllSelections || (selType == xaClipboard))
             {
-              /* completely give up the selection */
-              TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
+                CLIPBOARDINFO cbinfo;
 
-              /* We are completely giving up the selection.
-               * Make sure we can open the windows clipboard first. */
+                /* completely give up the selection */
+                TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
 
-              if ( !OpenClipboard(hwnd) )
-              {
-                  /*
-                   * We can't empty the clipboard if we cant open it so abandon.
-                   * Wine will think that it still owns the selection but this is
-                   * safer than losing the selection without properly emptying
-                   * the clipboard. Perhaps we should forcibly re-assert ownership
-                   * of the CLIPBOARD selection in this case...
-                   */
-                  ERR("\tClipboard is busy. Could not give up selection!\n");
-                  return;
-              }
-
-              /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
-              if ( (selType == xaClipboard)
-                   && (selectionAcquired & S_PRIMARY) )
-              {
-                  XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
-              }
-
-              /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD  */
-              if ( (selType == XA_PRIMARY)
-                   && (selectionAcquired & S_CLIPBOARD) )
-              {
-                  XSetSelectionOwner(display, xaClipboard, None, CurrentTime);
-              }
-
-              selectionWindow = None;
-              PrimarySelectionOwner = ClipboardSelectionOwner = 0;
-
-              /* Empty the windows clipboard.
-               * We should pretend that we still own the selection BEFORE calling
-               * EmptyClipboard() since otherwise this has the side effect of
-               * triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
-               * to be re-acquired by us!
+              /* We are completely giving up the selection. There is a
+               * potential race condition where the apps that now owns
+	       * the selection has already grabbed both selections. In
+	       * this case, if we clear any selection we may clear the
+	       * new owners selection. To prevent this common case we
+	       * try to open the clipboard. If we can't, we assume it
+	       * was a wine apps that took it and has taken both selectons.
+	       * In this case, don't bother releasing the other selection.
+	       * Otherwise only release the selection if we still own it.
                */
-              selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
-              EmptyClipboard();
-              CloseClipboard();
+                X11DRV_CLIPBOARD_GetClipboardInfo(&cbinfo);
 
-              /* Give up ownership of the windows clipboard */
-              CLIPBOARD_ReleaseOwner();
+                if (cbinfo.flags & CB_OWNER)
+                {
+                    /* Since we're still the owner, this wasn't initiated by 
+		       another Wine process */
+                    if (OpenClipboard(hwnd))
+                    {
+                      /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
+                      if ((selType == xaClipboard) && (selectionAcquired & S_PRIMARY))
+                      {
+		          TRACE("Lost clipboard. Check if we need to release PRIMARY\n");
+                          if (selectionWindow == TSXGetSelectionOwner(display,XA_PRIMARY))
+                          {
+		             TRACE("We still own PRIMARY. Releasing PRIMARY.\n");
+                             XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
+                          }
+		          else
+		             TRACE("We no longer own PRIMARY\n");
+                      }
 
-              /* Reset the selection flags now that we are done */
-              selectionAcquired = S_NOSELECTION;
+                      /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD  */
+                      if ((selType == XA_PRIMARY) && (selectionAcquired & S_CLIPBOARD))
+                      {
+		          TRACE("Lost PRIMARY. Check if we need to release CLIPBOARD\n");
+                          if (selectionWindow == TSXGetSelectionOwner(display,xaClipboard))
+                          {
+		              TRACE("We still own CLIPBOARD. Releasing CLIPBOARD.\n");
+                              XSetSelectionOwner(display, xaClipboard, None, CurrentTime);
+                          }
+		          else
+		              TRACE("We no longer own CLIPBOARD\n");
+                      }
+
+                      /* Destroy private objects */
+                      SendMessageW(cbinfo.hWndOwner, WM_DESTROYCLIPBOARD, 0, 0);
+   
+                      /* Give up ownership of the windows clipboard */
+                      X11DRV_CLIPBOARD_ReleaseOwnership();
+
+                      CloseClipboard();
+                    }
+                }
+	        else
+                {
+                    TRACE("Lost selection to other Wine process.\n");
+                }
+
+                selectionWindow = None;
+                PrimarySelectionOwner = ClipboardSelectionOwner = 0;
+
+                X11DRV_EmptyClipboard();
+
+                /* Reset the selection flags now that we are done */
+                selectionAcquired = S_NOSELECTION;
             }
             else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
             {
@@ -842,94 +1725,92 @@
                 PrimarySelectionOwner = 0;
                 selectionAcquired &= ~S_PRIMARY;  /* clear S_PRIMARY mask */
             }
-
-            cSelectionTargets = 0;
 	}
-        /* but we'll keep existing data for internal use */
-	else if( w == selectionPrevWindow )
-	{
-            Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
-
-	    w = TSXGetSelectionOwner(display, XA_PRIMARY);
-	    if( w == None )
-		TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
-
-	    w = TSXGetSelectionOwner(display, xaClipboard);
-	    if( w == None )
-		TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
-        }
     }
-
-    /* Signal to a selectionClearEvent listener if the selection is completely lost */
-    if (selectionClearEvent && !selectionAcquired)
-    {
-        TRACE("Lost all selections, signalling to selectionClearEvent listener\n");
-        SetEvent(selectionClearEvent);
-    }
-
-    selectionPrevWindow = None;
 }
 
+
 /**************************************************************************
- *		ReleaseClipboard (X11DRV.@)
- *  Voluntarily release all currently owned X selections
+ *		IsSelectionOwner (X11DRV.@)
+ *
+ * Returns: TRUE if the selection is owned by this process, FALSE otherwise
  */
-void X11DRV_ReleaseClipboard(void)
+static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void)
 {
-    Display *display = thread_display();
-    if( selectionAcquired )
-    {
-	XEvent xe;
-        Window savePrevWindow = selectionWindow;
-        Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
-        BOOL bHasPrimarySelection = selectionAcquired & S_PRIMARY;
-
-	selectionAcquired   = S_NOSELECTION;
-	selectionPrevWindow = selectionWindow;
-	selectionWindow     = None;
-
-	TRACE("\tgiving up selection (spw = %08x)\n",
-	     (unsigned)selectionPrevWindow);
-
-        wine_tsx11_lock();
-
-        TRACE("Releasing CLIPBOARD selection\n");
-        XSetSelectionOwner(display, xaClipboard, None, CurrentTime);
-	if( selectionPrevWindow )
-	    while( !XCheckTypedWindowEvent( display, selectionPrevWindow,
-                                            SelectionClear, &xe ) );
-
-        if ( bHasPrimarySelection )
-        {
-            TRACE("Releasing XA_PRIMARY selection\n");
-            selectionPrevWindow = savePrevWindow; /* May be cleared in X11DRV_CLIPBOARD_ReleaseSelection */
-            XSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
-
-            if( selectionPrevWindow )
-                while( !XCheckTypedWindowEvent( display, selectionPrevWindow,
-                                                SelectionClear, &xe ) );
-        }
-        wine_tsx11_unlock();
-    }
-
-    /* Get rid of any Pixmap resources we may still have */
-    while (prop_head)
-    {
-        PROPERTY *prop = prop_head;
-        prop_head = prop->next;
-        XFreePixmap( gdi_display, prop->pixmap );
-        HeapFree( GetProcessHeap(), 0, prop );
-    }
+    return selectionAcquired;
 }
 
+
+/**************************************************************************
+ *                X11DRV Clipboard Exports
+ **************************************************************************/
+
+
+/**************************************************************************
+ *		RegisterClipboardFormat (X11DRV.@)
+ *
+ * Registers a custom X clipboard format
+ * Returns: Format id or 0 on failure
+ */
+INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName)
+{
+    LPWINE_CLIPFORMAT lpFormat = ClipFormats;
+
+    if (FormatName == NULL) 
+        return 0;
+
+    TRACE("('%s') !\n", FormatName);
+
+    /* walk format chain to see if it's already registered */
+    while(TRUE)
+    {
+	if ( !strcasecmp(lpFormat->Name, FormatName) && 
+	     (lpFormat->wFlags & CF_FLAG_BUILTINFMT) == 0)
+	     return lpFormat->wFormatID;
+
+        if (!lpFormat->NextFormat)
+            break;
+
+	lpFormat = lpFormat->NextFormat;
+    }
+
+    return X11DRV_CLIPBOARD_InsertClipboardFormat(FormatName, FormatName);
+}
+
+
+/**************************************************************************
+ *		X11DRV_GetClipboardFormatName
+ */
+INT X11DRV_GetClipboardFormatName(UINT wFormat, LPSTR retStr, INT maxlen)
+{
+    INT len = 0;
+    LPWINE_CLIPFORMAT lpFormat = X11DRV_CLIPBOARD_LookupFormat(wFormat);
+
+    TRACE("(%04X, %p, %d) !\n", wFormat, retStr, maxlen);
+
+    if (!lpFormat || (lpFormat->wFlags & CF_FLAG_BUILTINFMT))
+    {
+        TRACE("Unknown format 0x%08x!\n", wFormat);
+        SetLastError(ERROR_INVALID_PARAMETER);
+    }
+    else
+    {
+        strncpy(retStr, lpFormat->Name, maxlen - 1);
+        retStr[maxlen - 1] = 0;
+
+        len = strlen(retStr);
+    }
+
+    return len;
+}
+
+
 /**************************************************************************
  *		AcquireClipboard (X11DRV.@)
  */
-void X11DRV_AcquireClipboard(void)
+void X11DRV_AcquireClipboard(HWND hWndClipWindow)
 {
     Display *display = thread_display();
-    Window       owner;
-    HWND         hWndClipWindow = GetOpenClipboardWindow();
 
     /*
      * Acquire X selection if we don't already own it.
@@ -943,24 +1824,22 @@
      * re-cycled to another top level X window in X11DRV_CLIPBOARD_ResetOwner.
      *
      */
-
-    if ( !(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)) )
+    if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
     {
-        Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
-        owner = X11DRV_get_whole_window( GetAncestor( hWndClipWindow, GA_ROOT ) );
+        Window owner = X11DRV_get_whole_window(GetAncestor(hWndClipWindow, GA_ROOT));
 
         /* Grab PRIMARY selection if not owned */
-        if ( !(selectionAcquired & S_PRIMARY) )
+        if (!(selectionAcquired & S_PRIMARY))
             TSXSetSelectionOwner(display, XA_PRIMARY, owner, CurrentTime);
 
         /* Grab CLIPBOARD selection if not owned */
-        if ( !(selectionAcquired & S_CLIPBOARD) )
+        if (!(selectionAcquired & S_CLIPBOARD))
             TSXSetSelectionOwner(display, xaClipboard, owner, CurrentTime);
 
-        if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner )
+        if (TSXGetSelectionOwner(display,XA_PRIMARY) == owner)
 	    selectionAcquired |= S_PRIMARY;
 
-        if( TSXGetSelectionOwner(display,xaClipboard) == owner)
+        if (TSXGetSelectionOwner(display,xaClipboard) == owner)
 	    selectionAcquired |= S_CLIPBOARD;
 
         if (selectionAcquired)
@@ -969,197 +1848,236 @@
 	    TRACE("Grabbed X selection, owner=(%08x)\n", (unsigned) owner);
         }
     }
+    else
+    {
+        WARN("Received request to acquire selection but process is already owner=(%08x)\n", (unsigned) selectionWindow);
+
+        selectionAcquired  = S_NOSELECTION;
+
+        if (TSXGetSelectionOwner(display,XA_PRIMARY) == selectionWindow)
+	    selectionAcquired |= S_PRIMARY;
+
+        if (TSXGetSelectionOwner(display,xaClipboard) == selectionWindow)
+	    selectionAcquired |= S_CLIPBOARD;
+
+        if (!(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)))
+	{
+            WARN("Lost selection but process didn't process SelectClear\n");
+            selectionWindow = None;
+	}
+    }
 }
 
+
 /**************************************************************************
- *		IsClipboardFormatAvailable (X11DRV.@)
- *
- * Checks if the specified format is available in the current selection
- * Only invoked when WINE is not the selection owner
+ *	X11DRV_EmptyClipboard
+ */
+void X11DRV_EmptyClipboard(void)
+{
+    if (ClipData)
+    {
+        LPWINE_CLIPDATA lpData;
+        LPWINE_CLIPDATA lpNext = ClipData;
+
+        do
+        {
+            lpData = lpNext;
+            lpNext = lpData->NextData;
+            lpData->PrevData->NextData = lpData->NextData;
+            lpData->NextData->PrevData = lpData->PrevData;
+            X11DRV_CLIPBOARD_FreeData(lpData);
+            HeapFree(GetProcessHeap(), 0, lpData);
+        } while (lpNext != lpData);
+    }
+
+    TRACE(" %d entries deleted from cache.\n", ClipDataCount);
+
+    ClipData = NULL;
+    ClipDataCount = 0;
+}
+
+
+
+/**************************************************************************
+ *		X11DRV_SetClipboardData
+ */
+BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32)
+{
+    BOOL bResult = FALSE;
+
+    if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
+        bResult = TRUE;
+
+    return bResult;
+}
+
+
+/**************************************************************************
+ *		CountClipboardFormats
+ */
+INT X11DRV_CountClipboardFormats(void)
+{
+    CLIPBOARDINFO cbinfo;
+
+    X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
+
+    TRACE(" count=%d\n", ClipDataCount);
+
+    return ClipDataCount;
+}
+
+
+/**************************************************************************
+ *		X11DRV_EnumClipboardFormats
+ */
+UINT X11DRV_EnumClipboardFormats(UINT wFormat)
+{
+    CLIPBOARDINFO cbinfo;
+    UINT wNextFormat = 0;
+
+    TRACE("(%04X)\n", wFormat);
+
+    X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
+
+    if (!wFormat)
+    {
+        if (ClipData)
+            wNextFormat = ClipData->wFormatID;
+    }
+    else
+    {
+        LPWINE_CLIPDATA lpData = X11DRV_CLIPBOARD_LookupData(wFormat);
+
+	if (lpData && lpData->NextData != ClipData)
+            wNextFormat = lpData->NextData->wFormatID;
+    }
+
+    return wNextFormat;
+}
+
+
+/**************************************************************************
+ *		X11DRV_IsClipboardFormatAvailable
  */
 BOOL X11DRV_IsClipboardFormatAvailable(UINT wFormat)
 {
-    Display *display = thread_display();
-    Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
-    Window ownerPrimary = TSXGetSelectionOwner(display,XA_PRIMARY);
-    Window ownerClipboard = TSXGetSelectionOwner(display,xaClipboard);
+    BOOL bRet = FALSE;
+    CLIPBOARDINFO cbinfo;
 
-    TRACE("enter for %d\n", wFormat);
+    TRACE("(%04X)\n", wFormat);
 
-    /*
-     * If the selection has not been previously cached, or the selection has changed,
-     * try and cache the list of available selection targets from the current selection.
-     */
-    if ( !cSelectionTargets || (PrimarySelectionOwner != ownerPrimary)
-                         || (ClipboardSelectionOwner != ownerClipboard) )
-    {
-        /*
-         * First try caching the CLIPBOARD selection.
-         * If unavailable try PRIMARY.
-         */
-        if ( X11DRV_CLIPBOARD_CacheDataFormats(xaClipboard) == 0 )
-        {
-            X11DRV_CLIPBOARD_CacheDataFormats(XA_PRIMARY);
-        }
+    X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
 
-        ClipboardSelectionOwner = ownerClipboard;
-        PrimarySelectionOwner = ownerPrimary;
-    }
+    if (wFormat != 0 && X11DRV_CLIPBOARD_LookupData(wFormat))
+        bRet = TRUE;
 
-    /* Exit if there is no selection */
-    if ( !ownerClipboard && !ownerPrimary )
-    {
-	TRACE("There is no selection owner\n");
-        return FALSE;
-    }
-
-    /* Check if the format is available in the clipboard cache */
-    if ( CLIPBOARD_IsPresent(wFormat) )
-        return TRUE;
-
-    /*
-     * Many X client apps (such as XTerminal) don't support being queried
-     * for the "TARGETS" target atom. To handle such clients we must actually
-     * try to convert the selection to the requested type.
-     */
-    if ( !cSelectionTargets )
-        return X11DRV_GetClipboardData( wFormat );
-
-    TRACE("There is no selection\n");
-    return FALSE;
-}
-
-/**************************************************************************
- *		RegisterClipboardFormat (X11DRV.@)
- *
- * Registers a custom X clipboard format
- * Returns: Format id or 0 on failure
- */
-INT X11DRV_RegisterClipboardFormat( LPCSTR FormatName )
-{
-    Display *display = thread_display();
-    Atom prop = None;
-    char str[256];
-
-    /*
-     * If an X atom is registered for this format, return that
-     * Otherwise register a new atom.
-     */
-    if (FormatName)
-    {
-        /* Add a WINE specific prefix to the format */
-        strcpy(str, FMT_PREFIX);
-        strncat(str, FormatName, sizeof(str) - strlen(FMT_PREFIX));
-        prop = TSXInternAtom(display, str, False);
-    }
-
-    return prop;
-}
-
-/**************************************************************************
- *		IsSelectionOwner (X11DRV.@)
- *
- * Returns: TRUE - We(WINE) own the selection, FALSE - Selection not owned by us
- */
-BOOL X11DRV_IsSelectionOwner(void)
-{
-    return selectionAcquired;
-}
-
-/**************************************************************************
- *		SetClipboardData (X11DRV.@)
- *
- * We don't need to do anything special here since the clipboard code
- * maintains the cache.
- *
- */
-void X11DRV_SetClipboardData(UINT wFormat)
-{
-    /* Make sure we have acquired the X selection */
-    X11DRV_AcquireClipboard();
-}
-
-/**************************************************************************
- *		GetClipboardData (X11DRV.@)
- *
- * This method is invoked only when we DO NOT own the X selection
- *
- * NOTE: Clipboard driver get requests only for CF_UNICODETEXT data.
- * We always get the data from the selection client each time,
- * since we have no way of determining if the data in our cache is stale.
- */
-BOOL X11DRV_GetClipboardData(UINT wFormat)
-{
-    Display *display = thread_display();
-    BOOL bRet = selectionAcquired;
-    HWND hWndClipWindow = GetOpenClipboardWindow();
-    HWND hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow();
-    LPWINE_CLIPFORMAT lpFormat;
-
-    TRACE("%d\n", wFormat);
-
-    if (!selectionAcquired)
-    {
-        XEvent xe;
-        Atom propRequest;
-        Window w = X11DRV_get_whole_window( GetAncestor( hWnd, GA_ROOT ));
-        if(!w)
-        {
-            FIXME("No parent win found %p %p\n", hWnd, hWndClipWindow);
-            return FALSE;
-        }
-
-        /* Map the format ID requested to an X selection property.
-         * If the format is in the cache, use the atom associated
-         * with it.
-         */
-
-        lpFormat = CLIPBOARD_LookupFormat( wFormat );
-        if (lpFormat && lpFormat->wDataPresent && lpFormat->drvData)
-            propRequest = (Atom)lpFormat->drvData;
-        else
-            propRequest = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat);
-
-        if (propRequest)
-        {
-            TRACE("Requesting %s selection from %s...\n",
-                  TSXGetAtomName(display, propRequest),
-                  TSXGetAtomName(display, selectionCacheSrc) );
-            wine_tsx11_lock();
-            XConvertSelection(display, selectionCacheSrc, propRequest,
-                            TSXInternAtom(display, "SELECTION_DATA", False),
-                            w, CurrentTime);
-
-            /* wait until SelectionNotify is received */
-
-            while( TRUE )
-            {
-               if( XCheckTypedWindowEvent(display, w, SelectionNotify, &xe) )
-                   if( xe.xselection.selection == selectionCacheSrc )
-                       break;
-            }
-            wine_tsx11_unlock();
-
-            /*
-             *  Read the contents of the X selection property into WINE's
-             *  clipboard cache converting the selection to be compatible if possible.
-             */
-            bRet = X11DRV_CLIPBOARD_ReadSelection( wFormat,
-                                                   xe.xselection.requestor,
-                                                   xe.xselection.property,
-                                                   xe.xselection.target);
-        }
-        else
-            bRet = FALSE;
-
-        TRACE("\tpresent %s = %i\n", CLIPBOARD_GetFormatName(wFormat, NULL, 0), bRet );
-    }
-
-    TRACE("Returning %d\n", bRet);
+    TRACE("(%04X)- ret(%d)\n", wFormat, bRet);
 
     return bRet;
 }
 
+
+/**************************************************************************
+ *		GetClipboardData (USER.142)
+ */
+BOOL X11DRV_GetClipboardData(UINT wFormat, HANDLE16* phData16, HANDLE* phData32)
+{
+    CLIPBOARDINFO cbinfo;
+    LPWINE_CLIPDATA lpRender;
+
+    TRACE("(%04X)\n", wFormat);
+
+    X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
+
+    if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)))
+    {
+        if ( !lpRender->hData32 )
+            X11DRV_CLIPBOARD_RenderFormat(lpRender);
+
+        /* Convert between 32 -> 16 bit data, if necessary */
+        if (lpRender->hData32 && !lpRender->hData16)
+        {
+            int size;
+
+            if (lpRender->wFormatID == CF_METAFILEPICT)
+                size = sizeof(METAFILEPICT16);
+            else
+                size = GlobalSize(lpRender->hData32);
+
+            lpRender->hData16 = GlobalAlloc16(GMEM_ZEROINIT, size);
+
+            if (!lpRender->hData16)
+                ERR("(%04X) -- not enough memory in 16b heap\n", wFormat);
+            else
+            {
+                if (lpRender->wFormatID == CF_METAFILEPICT)
+                {
+                    FIXME("\timplement function CopyMetaFilePict32to16\n");
+                    FIXME("\tin the appropriate file.\n");
+  #ifdef SOMEONE_IMPLEMENTED_ME
+                    CopyMetaFilePict32to16(GlobalLock16(lpRender->hData16),
+                        GlobalLock(lpRender->hData32));
+  #endif
+                }
+                else
+                {
+                    memcpy(GlobalLock16(lpRender->hData16),
+                        GlobalLock(lpRender->hData32), size);
+                }
+
+                GlobalUnlock16(lpRender->hData16);
+                GlobalUnlock(lpRender->hData32);
+            }
+        }
+
+        /* Convert between 32 -> 16 bit data, if necessary */
+        if (lpRender->hData16 && !lpRender->hData32)
+        {
+            int size;
+
+            if (lpRender->wFormatID == CF_METAFILEPICT)
+                size = sizeof(METAFILEPICT16);
+            else
+                size = GlobalSize(lpRender->hData32);
+
+            lpRender->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | 
+                GMEM_DDESHARE, size);
+
+            if (lpRender->wFormatID == CF_METAFILEPICT)
+            {
+                FIXME("\timplement function CopyMetaFilePict16to32\n");
+                FIXME("\tin the appropriate file.\n");
+#ifdef SOMEONE_IMPLEMENTED_ME
+                CopyMetaFilePict16to32(GlobalLock16(lpRender->hData32),
+                    GlobalLock(lpRender->hData16));
+#endif
+            }
+            else
+            {
+                memcpy(GlobalLock(lpRender->hData32),
+                    GlobalLock16(lpRender->hData16), size);
+            }
+
+            GlobalUnlock(lpRender->hData32);
+            GlobalUnlock16(lpRender->hData16);
+        }
+
+        if (phData16)
+            *phData16 = lpRender->hData16;
+
+        if (phData32)
+            *phData32 = lpRender->hData32;
+
+        TRACE(" returning hData16(%04x) hData32(%04x) (type %d)\n", 
+            lpRender->hData16, (unsigned int) lpRender->hData32, lpRender->wFormatID);
+
+        return lpRender->hData16 || lpRender->hData32;
+    }
+
+    return 0;
+}
+
+
 /**************************************************************************
  *		ResetSelectionOwner (X11DRV.@)
  *
@@ -1175,50 +2093,51 @@
     HWND hWndClipOwner = 0;
     HWND tmp;
     Window XWnd = X11DRV_get_whole_window(hwnd);
-    Atom xaClipboard;
     BOOL bLostSelection = FALSE;
+    Window selectionPrevWindow;
 
     /* There is nothing to do if we don't own the selection,
      * or if the X window which currently owns the selecion is different
      * from the one passed in.
      */
-    if ( !selectionAcquired || XWnd != selectionWindow
+    if (!selectionAcquired || XWnd != selectionWindow
          || selectionWindow == None )
        return;
 
-    if ( (bFooBar && XWnd) || (!bFooBar && !XWnd) )
+    if ((bFooBar && XWnd) || (!bFooBar && !XWnd))
        return;
 
     hWndClipOwner = GetClipboardOwner();
-    xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
 
     TRACE("clipboard owner = %p, selection window = %08x\n",
           hWndClipOwner, (unsigned)selectionWindow);
 
     /* now try to salvage current selection from being destroyed by X */
-
-    TRACE("\tchecking %08x\n", (unsigned) XWnd);
+    TRACE("checking %08x\n", (unsigned) XWnd);
 
     selectionPrevWindow = selectionWindow;
     selectionWindow = None;
 
-    if (!(tmp = GetWindow( hwnd, GW_HWNDNEXT ))) tmp = GetWindow( hwnd, GW_HWNDFIRST );
-    if (tmp && tmp != hwnd) selectionWindow = X11DRV_get_whole_window(tmp);
+    if (!(tmp = GetWindow(hwnd, GW_HWNDNEXT)))
+        tmp = GetWindow(hwnd, GW_HWNDFIRST);
 
-    if( selectionWindow != None )
+    if (tmp && tmp != hwnd) 
+        selectionWindow = X11DRV_get_whole_window(tmp);
+
+    if (selectionWindow != None)
     {
         /* We must pretend that we don't own the selection while making the switch
          * since a SelectionClear event will be sent to the last owner.
          * If there is no owner X11DRV_CLIPBOARD_ReleaseSelection will do nothing.
          */
         int saveSelectionState = selectionAcquired;
-        selectionAcquired = False;
+        selectionAcquired = S_NOSELECTION;
 
         TRACE("\tswitching selection from %08x to %08x\n",
                     (unsigned)selectionPrevWindow, (unsigned)selectionWindow);
 
         /* Assume ownership for the PRIMARY and CLIPBOARD selection */
-        if ( saveSelectionState & S_PRIMARY )
+        if (saveSelectionState & S_PRIMARY)
             TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
 
         TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
@@ -1227,12 +2146,11 @@
         selectionAcquired = saveSelectionState;
 
         /* Lose the selection if something went wrong */
-        if ( ( (saveSelectionState & S_PRIMARY) &&
-               (TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow) )
-             || (TSXGetSelectionOwner(display, xaClipboard) != selectionWindow) )
+        if (((saveSelectionState & S_PRIMARY) &&
+           (TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow)) || 
+           (TSXGetSelectionOwner(display, xaClipboard) != selectionWindow))
         {
             bLostSelection = TRUE;
-            goto END;
         }
         else
         {
@@ -1246,167 +2164,93 @@
     else
     {
         bLostSelection = TRUE;
-        goto END;
     }
 
-END:
     if (bLostSelection)
     {
-      /* Launch the clipboard server if the selection can no longer be recyled
-       * to another top level window. */
+        TRACE("Lost the selection!\n");
 
-      if ( !X11DRV_CLIPBOARD_LaunchServer() )
-      {
-         /* Empty the windows clipboard if the server was not launched.
-          * We should pretend that we still own the selection BEFORE calling
-          * EmptyClipboard() since otherwise this has the side effect of
-          * triggering X11DRV_CLIPBOARD_Acquire() and causing the X selection
-          * to be re-acquired by us!
-          */
-
-         TRACE("\tLost the selection! Emptying the clipboard...\n");
-
-         OpenClipboard( 0 );
-         selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
-         EmptyClipboard();
-
-         CloseClipboard();
-
-         /* Give up ownership of the windows clipboard */
-         CLIPBOARD_ReleaseOwner();
-      }
-
-      selectionAcquired = S_NOSELECTION;
-      ClipboardSelectionOwner = PrimarySelectionOwner = 0;
-      selectionWindow = 0;
+        X11DRV_CLIPBOARD_ReleaseOwnership();
+        selectionAcquired = S_NOSELECTION;
+        ClipboardSelectionOwner = PrimarySelectionOwner = 0;
+        selectionWindow = 0;
     }
 }
 
-/**************************************************************************
- *		X11DRV_CLIPBOARD_RegisterPixmapResource
- * Registers a Pixmap resource which is to be associated with a property Atom.
- * When the property is destroyed we also destroy the Pixmap through the
- * PropertyNotify event.
- */
-BOOL X11DRV_CLIPBOARD_RegisterPixmapResource( Atom property, Pixmap pixmap )
-{
-    PROPERTY *prop = HeapAlloc( GetProcessHeap(), 0, sizeof(*prop) );
-    if (!prop) return FALSE;
-    prop->atom = property;
-    prop->pixmap = pixmap;
-    prop->next = prop_head;
-    prop_head = prop;
-    return TRUE;
-}
-
-/**************************************************************************
- *		X11DRV_CLIPBOARD_FreeResources
- *
- * Called from EVENT_PropertyNotify() to give us a chance to destroy
- * any resources associated with this property.
- */
-void X11DRV_CLIPBOARD_FreeResources( Atom property )
-{
-    /* Do a simple linear search to see if we have a Pixmap resource
-     * associated with this property and release it.
-     */
-    PROPERTY **prop = &prop_head;
-
-    while (*prop)
-    {
-        if ((*prop)->atom == property)
-        {
-            PROPERTY *next = (*prop)->next;
-            XFreePixmap( gdi_display, (*prop)->pixmap );
-            HeapFree( GetProcessHeap(), 0, *prop );
-            *prop = next;
-        }
-        else prop = &(*prop)->next;
-    }
-}
-
-/**************************************************************************
- *		X11DRV_GetClipboardFormatName
- */
-BOOL X11DRV_GetClipboardFormatName( UINT wFormat, LPSTR retStr, UINT maxlen )
-{
-    BOOL bRet = FALSE;
-    char *itemFmtName = TSXGetAtomName(thread_display(), wFormat);
-    INT prefixlen = strlen(FMT_PREFIX);
-
-    if ( 0 == strncmp(itemFmtName, FMT_PREFIX, prefixlen ) )
-    {
-        strncpy(retStr, itemFmtName + prefixlen, maxlen);
-        bRet = TRUE;
-    }
-
-    TSXFree(itemFmtName);
-
-    return bRet;
-}
-
 
 /**************************************************************************
- *		CLIPBOARD_SerializeMetafile
+ *                      X11DRV_CLIPBOARD_SynthesizeData
  */
-HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, INT cbytes, BOOL out)
+static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID)
 {
-    HANDLE h = 0;
+    BOOL bsyn = TRUE;
+    LPWINE_CLIPDATA lpSource = NULL;
 
-    if (out) /* Serialize out, caller should free memory */
+    TRACE(" %d\n", wFormatID);
+
+    /* Don't need to synthesize if it already exists */
+    if (X11DRV_CLIPBOARD_LookupData(wFormatID))
+        return TRUE;
+
+    if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT)
     {
-        if (wformat == CF_METAFILEPICT)
-        {
-            LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(hdata);
-            int size = GetMetaFileBitsEx(lpmfp->hMF, 0, NULL);
-
-            h = GlobalAlloc(0, size + sizeof(METAFILEPICT));
-            if (h)
-            {
-                METAFILEPICT *pdata = GlobalLock(h);
-
-                memcpy(pdata, lpmfp, sizeof(METAFILEPICT));
-                GetMetaFileBitsEx(lpmfp->hMF, size, pdata + 1);
-
-                GlobalUnlock(h);
-            }
-
-            GlobalUnlock(hdata);
-        }
-        else if (wformat == CF_ENHMETAFILE)
-        {
-            int size = GetEnhMetaFileBits(hdata, 0, NULL);
-
-            h = GlobalAlloc(0, size);
-            if (h)
-            {
-                LPVOID pdata = GlobalLock(h);
-                GetEnhMetaFileBits(hdata, size, pdata);
-                GlobalUnlock(h);
-            }
-        }
+        bsyn = ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_UNICODETEXT)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
+            ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_TEXT)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED) ||
+            ((lpSource = X11DRV_CLIPBOARD_LookupData(CF_OEMTEXT)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED);
     }
-    else
+    else if (wFormatID == CF_ENHMETAFILE)
     {
-        if (wformat == CF_METAFILEPICT)
-        {
-            h = GlobalAlloc(0, sizeof(METAFILEPICT));
-            if (h)
-            {
-                LPMETAFILEPICT pmfp = (LPMETAFILEPICT) GlobalLock(h);
-
-                memcpy(pmfp, (LPVOID)hdata, sizeof(METAFILEPICT));
-                pmfp->hMF = SetMetaFileBitsEx(cbytes - sizeof(METAFILEPICT),
-                                              (char *)hdata + sizeof(METAFILEPICT));
-
-                GlobalUnlock(h);
-            }
-        }
-        else if (wformat == CF_ENHMETAFILE)
-        {
-            h = SetEnhMetaFileBits(cbytes, (LPVOID)hdata);
-        }
+        bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
+    }
+    else if (wFormatID == CF_METAFILEPICT)
+    {
+        bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_METAFILEPICT)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
+    }
+    else if (wFormatID == CF_DIB)
+    {
+        bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_BITMAP)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
+    }
+    else if (wFormatID == CF_BITMAP)
+    {
+        bsyn = (lpSource = X11DRV_CLIPBOARD_LookupData(CF_DIB)) &&
+            ~lpSource->wFlags & CF_FLAG_SYNTHESIZED;
     }
 
-    return h;
+    if (bsyn)
+        X11DRV_CLIPBOARD_InsertClipboardData(wFormatID, 0, 0, CF_FLAG_SYNTHESIZED);
+
+    return bsyn;
+}
+
+
+
+/**************************************************************************
+ *              X11DRV_EndClipboardUpdate
+ * TODO:
+ *  Add locale if it hasn't already been added
+ */
+void X11DRV_EndClipboardUpdate(void)
+{
+    INT count = ClipDataCount;
+
+    /* Do Unicode <-> Text <-> OEM mapping */
+    X11DRV_CLIPBOARD_SynthesizeData(CF_UNICODETEXT);
+    X11DRV_CLIPBOARD_SynthesizeData(CF_TEXT);
+    X11DRV_CLIPBOARD_SynthesizeData(CF_OEMTEXT);
+
+    /* Enhmetafile <-> MetafilePict mapping */
+    X11DRV_CLIPBOARD_SynthesizeData(CF_ENHMETAFILE);
+    X11DRV_CLIPBOARD_SynthesizeData(CF_METAFILEPICT);
+
+    /* DIB <-> Bitmap mapping */
+    X11DRV_CLIPBOARD_SynthesizeData(CF_DIB);
+    X11DRV_CLIPBOARD_SynthesizeData(CF_BITMAP);
+
+    TRACE("%d formats added to cached data\n", ClipDataCount - count);
 }