Enabled the persistent clipboard server.

diff --git a/windows/clipboard.c b/windows/clipboard.c
index 7122167..27fe04b 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -488,7 +488,7 @@
         TRACE("\tconverting from '%s' to '%s', %i chars\n",
                                           lpSource->Name, lpTarget->Name, size);
     
-        lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT, size);
+        lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
         lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
     
         if( lpstrT )
@@ -791,7 +791,8 @@
     }
    
     /* Convert between 32 -> 16 bit data, if necessary */
-    if( lpRender->hData32 && !lpRender->hData16 )
+    if( lpRender->hData32 && !lpRender->hData16
+        && CLIPBOARD_IsMemoryObject(wFormat) )
     {
       int size;
       if( lpRender->wFormatID == CF_METAFILEPICT )
@@ -857,7 +858,8 @@
     }
    
     /* Convert between 16 -> 32 bit data, if necessary */
-    if( lpRender->hData16 && !lpRender->hData32 )
+    if( lpRender->hData16 && !lpRender->hData32
+        && CLIPBOARD_IsMemoryObject(wFormat) )
     {
       int size;
       if( lpRender->wFormatID == CF_METAFILEPICT )
diff --git a/windows/user.c b/windows/user.c
index ff920b2..672783b 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -171,11 +171,6 @@
      * but does nothing);
      */
 
-    /*  TODO: 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.
-     */
-
     /* ModuleUnload() in "Internals" */
 
     hInstance = GetExePtr( hInstance );
diff --git a/windows/x11drv/Makefile.in b/windows/x11drv/Makefile.in
index afc90d3..8d54cf0 100644
--- a/windows/x11drv/Makefile.in
+++ b/windows/x11drv/Makefile.in
@@ -1,4 +1,4 @@
-DEFS      = @DLLFLAGS@ -D__WINE__
+DEFS      = @DLLFLAGS@ -D__WINE__ -DBINDIR="\"$(bindir)\""
 TOPSRCDIR = @top_srcdir@
 TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
@@ -23,8 +23,6 @@
 wineclipsrv: wineclipsrv.c
 	$(CC) $(ALLCFLAGS) -o wineclipsrv $(SRCDIR)/wineclipsrv.c $(X_LIBS) $(XLIB) $(LIBS)
 
-all: $(MODULE).o
-
 @MAKE_RULES@
 
 ### Dependencies:
diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
index 3db480b..fcdc4c9 100644
--- a/windows/x11drv/clipboard.c
+++ b/windows/x11drv/clipboard.c
@@ -49,13 +49,15 @@
 
 #ifndef X_DISPLAY_MISSING
 
+#include <errno.h>
 #include <X11/Xatom.h>
 #include <string.h>
+#include <unistd.h>
+
 #include "ts_xlib.h"
 
 #include "wine/winuser16.h"
 #include "clipboard.h"
-#include "debugtools.h"
 #include "message.h"
 #include "win.h"
 #include "windef.h"
@@ -63,6 +65,8 @@
 #include "bitmap.h"
 #include "commctrl.h"
 #include "heap.h"
+#include "options.h"
+#include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(clipboard)
 
@@ -76,13 +80,14 @@
 
 static char _CLIPBOARD[] = "CLIPBOARD";        /* CLIPBOARD atom name */
 static char FMT_PREFIX[] = "<WCF>";            /* Prefix for windows specific formats */
-static int    selectionAcquired = 0;           /* Contains the current selection masks */
+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 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 = NULL;      /* Synchronization object used to block until server is started */
 
 /*
  * Dynamic pointer arrays to manage destruction of Pixmap resources
@@ -206,6 +211,106 @@
 
 
 /**************************************************************************
+ *		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;
+
+    /* If persistant selection has been disabled in the .winerc Clipboard section,
+     * don't launch the server
+     */
+    if ( !PROFILE_GetWineIniInt("Clipboard", "PersistentSelection", 1) )
+        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.
+     */
+    selectionWindow = selectionPrevWindow;
+    if ( !fork() )
+    {
+        /* 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], clearSelection[8];
+
+        sprintf(selMask, "%d", selectionAcquired);
+
+        /* Build the debug class mask to pass to the server, by inheriting
+         * the settings for the clipboard debug channel.
+         */
+        dbgClasses |= __GET_DEBUGGING(__DBCL_FIXME, dbch_clipboard) ? 1 : 0;
+        dbgClasses |= __GET_DEBUGGING(__DBCL_ERR, dbch_clipboard) ? 2 : 0;
+        dbgClasses |= __GET_DEBUGGING(__DBCL_WARN, dbch_clipboard) ? 4 : 0;
+        dbgClasses |= __GET_DEBUGGING(__DBCL_TRACE, dbch_clipboard) ? 8 : 0;
+        sprintf(dbgClassMask, "%d", dbgClasses);
+
+        /* Get the clear selection preference */
+        sprintf(clearSelection, "%d",
+                PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0));
+            
+        /* Exec the clipboard server passing it the selection and debug class masks */
+        execl( BINDIR "/wineclipsvr", "wineclipsvr",
+               selMask, dbgClassMask, clearSelection, NULL );
+        execlp( "wineclipsvr", "wineclipsvr", selMask, dbgClassMask, clearSelection, NULL );
+        execl( "./windows/x11drv/wineclipsvr", "wineclipsvr",
+               selMask, dbgClassMask, clearSelection, NULL );
+
+        /* Exec Failed! */
+        perror("Could not start Wine clipboard server");
+        exit( 1 ); /* Exit the child process */
+    }
+
+    /* 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
+    {
+        /* Make the event object's handle global */
+        selectionClearEvent = ConvertToGlobalHandle(selectionClearEvent);
+        
+        /* Wait until we lose the selection, timing out after a minute */
+
+        TRACE("Waiting for clipboard server to acquire selection\n");
+
+        if ( WaitForSingleObject( selectionClearEvent, 60000 ) != WAIT_OBJECT_0 )
+            TRACE("Server could not acquire selection, or a time out occured!\n");
+        else
+            TRACE("Server successfully acquired selection\n");
+
+        /* Release the event */
+        CloseHandle(selectionClearEvent);
+        selectionClearEvent = NULL;
+    }
+
+    WIN_RestoreWndsLock(iWndsLocks);
+    
+    return TRUE;
+}
+
+
+/**************************************************************************
  *		X11DRV_CLIPBOARD_CacheDataFormats
  *
  * Caches the list of data formats available from the current selection.
@@ -567,14 +672,14 @@
  * Release an XA_PRIMARY or XA_CLIPBOARD selection that we own, in response
  * to a SelectionClear event.
  * This can occur in response to another client grabbing the X selection.
- * If the XA_CLIPBOARD selection is lost we relinquish XA_PRIMARY as well.
+ * If the XA_CLIPBOARD selection is lost, we relinquish XA_PRIMARY as well.
  */
 void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd)
 {
     Atom xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
+    int clearAllSelections = PROFILE_GetWineIniInt("Clipboard", "ClearAllSelections", 0);
     
-    /* w is the window that lost selection,
-     * 
+    /* w is the window that lost the selection
      * selectionPrevWindow is nonzero if CheckSelection() was called. 
      */
 
@@ -585,12 +690,15 @@
     {
 	if( w == selectionWindow || selectionPrevWindow == None)
 	{
-	    /* alright, we really lost it */
-
-            if ( selType == xaClipboard )  /* completely give up the selection */
+            /* 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) )
             {
-              TRACE("Lost CLIPBOARD selection\n");
-                
+              /* completely give up the selection */
+              TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
+
               /* We are completely giving up the selection.
                * Make sure we can open the windows clipboard first. */
               
@@ -607,24 +715,23 @@
                   return;
               }
 
-              selectionPrevWindow = selectionWindow;
+              /* 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;
               
-              /* Voluntarily give up the PRIMARY selection if we still own it */
-              if ( selectionAcquired & S_PRIMARY )
-              {
-                  XEvent xe;
-                  TRACE("Releasing XA_PRIMARY selection\n");
-                  
-                  TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime);
-
-                  /* Wait until SelectionClear is processed */
-                  if( selectionPrevWindow )
-                      while( !XCheckTypedWindowEvent( display, selectionPrevWindow,
-                                                      SelectionClear, &xe ) );
-              }
-
               /* Empty the windows clipboard.
                * We should pretend that we still own the selection BEFORE calling
                * EmptyClipboard() since otherwise this has the side effect of
@@ -633,12 +740,13 @@
                */
               selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
               EmptyClipboard();
-              selectionAcquired = S_NOSELECTION;
-              
               CloseClipboard();
 
               /* Give up ownership of the windows clipboard */
               CLIPBOARD_ReleaseOwner();
+
+              /* Reset the selection flags now that we are done */
+              selectionAcquired = S_NOSELECTION;
             }
             else if ( selType == XA_PRIMARY ) /* Give up only PRIMARY selection */
             {
@@ -664,6 +772,13 @@
         }
     }
 
+    /* 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;
 }
 
@@ -996,21 +1111,6 @@
     TRACE("clipboard owner = %04x, selection window = %08x\n",
           hWndClipOwner, (unsigned)selectionWindow);
 
-#if(0)
-    /* Check if all formats are already in the clipboard cache */
-    if( !CLIPBOARD_IsCacheRendered() )
-    {
-	SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L);
-
-	/* check if all formats were rendered */
-        if ( !CLIPBOARD_IsCacheRendered() )
-        {
-	    ERR("\tCould not render all formats\n");
-            CLIPBOARD_ReleaseOwner();
-        }
-    }
-#endif
-    
     /* now try to salvage current selection from being destroyed by X */
 
     TRACE("\tchecking %08x\n", (unsigned) XWnd);
@@ -1041,7 +1141,10 @@
             TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime);
         
         TSXSetSelectionOwner(display, xaClipboard, selectionWindow, CurrentTime);
-        
+
+        /* Restore the selection masks */
+        selectionAcquired = saveSelectionState;
+
         /* Lose the selection if something went wrong */
         if ( ( (saveSelectionState & S_PRIMARY) &&
                (TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow) )
@@ -1053,7 +1156,6 @@
         else
         {
             /* Update selection state */
-            selectionAcquired = saveSelectionState;
             if (saveSelectionState & S_PRIMARY)
                PrimarySelectionOwner = selectionWindow;
             
@@ -1069,26 +1171,33 @@
 END:
     if (bLostSelection)
     {
-       /* 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!
-        */
+      /* Launch the clipboard server if the selection can no longer be recyled
+       * to another top level window. */
+  
+      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(NULL);
+         selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
+         EmptyClipboard();
+         
+         CloseClipboard();
+   
+         /* Give up ownership of the windows clipboard */
+         CLIPBOARD_ReleaseOwner();
+      }
 
-       TRACE("\tLost the selection! Emptying the clipboard...\n");
-    
-       OpenClipboard(NULL);
-       selectionAcquired = (S_PRIMARY | S_CLIPBOARD);
-       EmptyClipboard();
-       selectionAcquired = S_NOSELECTION;
-       
-       CloseClipboard();
- 
-       /* Give up ownership of the windows clipboard */
-       CLIPBOARD_ReleaseOwner();
-       ClipboardSelectionOwner = PrimarySelectionOwner = 0;
-       selectionWindow = 0;
+      selectionAcquired = S_NOSELECTION;
+      ClipboardSelectionOwner = PrimarySelectionOwner = 0;
+      selectionWindow = 0;
     }
 }
 
diff --git a/windows/x11drv/wineclipsrv.c b/windows/x11drv/wineclipsrv.c
index 63276f7..97ff7a7 100644
--- a/windows/x11drv/wineclipsrv.c
+++ b/windows/x11drv/wineclipsrv.c
@@ -3,50 +3,123 @@
  *
  *      Copyright 1999  Noel Borthwick
  *
+ * USAGE:
+ *       wineclipsrv [selection_mask] [debugClass_mask] [clearAllSelections]
+ *
+ * The optional selection-mask argument is a bit mask of the selection
+ * types to be acquired. Currently two selections are supported:
+ *   1. PRIMARY (mask value 1)
+ *   2. CLIPBOARD (mask value 2).
+ *
+ * debugClass_mask is a bit mask of all debugging classes for which messages
+ * are to be output. The standard Wine debug class set FIXME(1), ERR(2),
+ * WARN(4) and TRACE(8) are supported.
+ *
+ * If clearAllSelections == 1 *all* selections are lost whenever a SelectionClear
+ * event is received.
+ *
+ * If no arguments are supplied the server aquires all selections. (mask value 3)
+ * and defaults to output of only FIXME(1) and ERR(2) messages. The default for
+ * clearAllSelections is 0.
+ *
  * NOTES:
- *    This file contains the implementation for the Clipboard server
+ *
+ *    The Wine Clipboard Server is a standalone XLib application whose 
+ * purpose is to manage the X selection when Wine exits.
+ * The server itself is started automatically with the appropriate
+ * selection masks, whenever Wine exits after acquiring the PRIMARY and/or
+ * CLIPBOARD selection. (See X11DRV_CLIPBOARD_ResetOwner)
+ * When the server starts, it first proceeds to capture the selection data from
+ * Wine and then takes over the selection ownership. It does this by querying
+ * the current selection owner(of the specified selections) for the TARGETS
+ * selection target. It then proceeds to cache all the formats exposed by
+ * TARGETS. If the selection does not support the TARGETS target, or if no
+ * target formats are exposed, the server simply exits.
+ * Once the cache has been filled, the server then actually acquires ownership
+ * of the respective selection and begins fielding selection requests.
+ * Selection requests are serviced from the cache. If a selection is lost the
+ * server flushes its internal cache, destroying all data previously saved.
+ * Once ALL selections have been lost the server terminates.
  *
  * TODO:
- *
  */
+
+#include <stdio.h>
+#include <stdlib.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xos.h>
 #include <X11/Xatom.h>
-#include <stdio.h>
 
-/*  Lightweight debug definitions */
+/*
+ *  Lightweight debug definitions for Wine Clipboard Server.
+ *  The standard FIXME, ERR, WARN & TRACE classes are supported
+ *  without debug channels.
+ *  The standard defines NO_TRACE_MSGS and NO_DEBUG_MSGS will compile out
+ *  TRACE, WARN and ERR and FIXME message displays.
+ */
 
-#define __DPRINTF(dbname) (printf("%s:%s:%s ", dbname, progname, __FUNCTION__),0) ? 0 : printf
+/* Internal definitions (do not use these directly) */
+
+enum __DEBUG_CLASS { __DBCL_FIXME, __DBCL_ERR, __DBCL_WARN, __DBCL_TRACE, __DBCL_COUNT };
+
+extern char __debug_msg_enabled[__DBCL_COUNT];
+
+extern const char * const debug_cl_name[__DBCL_COUNT];
+
+#define DEBUG_CLASS_COUNT __DBCL_COUNT
+
+#define __GET_DEBUGGING(dbcl)    (__debug_msg_enabled[(dbcl)])
+#define __SET_DEBUGGING(dbcl,on) (__debug_msg_enabled[(dbcl)] = (on))
+
+
+#define __DPRINTF(dbcl) \
+    (!__GET_DEBUGGING(dbcl) || \
+    (printf("%s:%s:%s ", debug_cl_name[(dbcl)], progname, __FUNCTION__),0)) \
+    ? 0 : printf
+
 #define __DUMMY_DPRINTF 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
 
+/* use configure to allow user to compile out debugging messages */
 #ifndef NO_TRACE_MSGS
-  #define TRACE        __DPRINTF("TRACE")
+  #define TRACE        __DPRINTF(__DBCL_TRACE)
 #else
   #define TRACE        __DUMMY_DPRINTF
 #endif /* NO_TRACE_MSGS */
 
 #ifndef NO_DEBUG_MSGS
-  #define WARN         __DPRINTF("WARN")
-  #define FIXME        __DPRINTF("FIXME")
+  #define WARN         __DPRINTF(__DBCL_WARN)
+  #define FIXME        __DPRINTF(__DBCL_FIXME)
 #else
   #define WARN         __DUMMY_DPRINTF
   #define FIXME        __DUMMY_DPRINTF
 #endif /* NO_DEBUG_MSGS */
 
-#define ERR        __DPRINTF("ERROR")
+/* define error macro regardless of what is configured */
+#define ERR        __DPRINTF(__DBCL_ERR)
 
 
 #define TRUE 1
 #define FALSE 0
 typedef int BOOL;
 
+/* Internal definitions for debugging messages(do not use these directly) */
+const char * const debug_cl_name[] = { "fixme", "err", "warn", "trace" };
+char __debug_msg_enabled[DEBUG_CLASS_COUNT] = {1, 1, 0, 0};
+
+
 /* Selection masks */
 
 #define S_NOSELECTION    0
 #define S_PRIMARY        1
 #define S_CLIPBOARD      2
 
+/* Debugging class masks */
+
+#define C_FIXME          1
+#define C_ERR            2
+#define C_WARN           4
+#define C_TRACE          8
 
 /*
  * Global variables 
@@ -62,10 +135,10 @@
 
 /* X selection context info */
 static char _CLIPBOARD[] = "CLIPBOARD";        /* CLIPBOARD atom name */
-static char FMT_PREFIX[] = "<WCF>";            /* Prefix for windows specific formats */
 static int  g_selectionToAcquire = 0;          /* Masks for the selection to be acquired */
 static int  g_selectionAcquired = 0;           /* Contains the current selection masks */
-
+static int  g_clearAllSelections = 0;          /* If TRUE *all* selections are lost on SelectionClear */
+    
 /* Selection cache */
 typedef struct tag_CACHEENTRY
 {
@@ -119,7 +192,6 @@
 void main(int argc, char **argv)
 {
     XEvent event;
-    unsigned int width, height;	/* window size */
 
     if ( !Init(argc, argv) )
         exit(0);
@@ -130,6 +202,8 @@
      */
     if ( AcquireSelection() == S_NOSELECTION )
         TerminateServer(0);
+
+    TRACE("Clipboard server running...\n");
     
     /* Start an X event loop */
     while (1)
@@ -243,8 +317,23 @@
         g_selectionToAcquire = atoi(argv[1]);
     else
         g_selectionToAcquire = S_PRIMARY | S_CLIPBOARD;
+
+    /* Set the debugging class state from the command line argument */
+    if (argc > 2)
+    {
+        int dbgClasses = atoi(argv[2]);
         
-    TRACE("Clipboard server running...\n");
+        __SET_DEBUGGING(__DBCL_FIXME, dbgClasses & C_FIXME);
+        __SET_DEBUGGING(__DBCL_ERR, dbgClasses & C_ERR);
+        __SET_DEBUGGING(__DBCL_WARN, dbgClasses & C_WARN);
+        __SET_DEBUGGING(__DBCL_TRACE, dbgClasses & C_TRACE);
+    }
+        
+    /* Set the "ClearSelections" state from the command line argument */
+    if (argc > 3)
+        g_clearAllSelections = atoi(argv[3]);
+    
+    return TRUE;
 }
 
 
@@ -287,27 +376,39 @@
     {
         TRACE("Acquiring PRIMARY selection...\n");
         g_cPrimaryTargets = CacheDataFormats( XA_PRIMARY, &g_pPrimaryCache );
-        if (g_cPrimaryTargets)
-            XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime);
-        else
-            TRACE("No PRIMARY targets - ownership not acquired.\n");
+        TRACE("Cached %ld formats...\n", g_cPrimaryTargets);
     }
     if (g_selectionToAcquire & S_CLIPBOARD)
     {
         TRACE("Acquiring CLIPBOARD selection...\n");
         g_cClipboardTargets = CacheDataFormats( xaClipboard, &g_pClipboardCache );
-        
-        if (g_cClipboardTargets)
-            XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime);
-        else
-            TRACE("No CLIPBOARD targets - ownership not acquired.\n");
+        TRACE("Cached %ld formats...\n", g_cClipboardTargets);
     }
 
-    /* Remember the acquired selections */
-    if( XGetSelectionOwner(g_display,XA_PRIMARY) == g_win )
+    /*
+     * Now that we have cached the data, we proceed to acquire the selections
+     */
+    if (g_cPrimaryTargets)
+    {
+        /* Acquire the PRIMARY selection */
+        while (XGetSelectionOwner(g_display,XA_PRIMARY) != g_win)
+            XSetSelectionOwner(g_display, XA_PRIMARY, g_win, CurrentTime);
+        
         g_selectionAcquired |= S_PRIMARY;
-    if( XGetSelectionOwner(g_display,xaClipboard) == g_win )
+    }
+    else
+        TRACE("No PRIMARY targets - ownership not acquired.\n");
+    
+    if (g_cClipboardTargets)
+    {
+        /* Acquire the CLIPBOARD selection */
+        while (XGetSelectionOwner(g_display,xaClipboard) != g_win)
+            XSetSelectionOwner(g_display, xaClipboard, g_win, CurrentTime);
+
         g_selectionAcquired |= S_CLIPBOARD;
+    }
+    else
+        TRACE("No CLIPBOARD targets - ownership not acquired.\n");
 
     return g_selectionAcquired;
 }
@@ -398,7 +499,7 @@
               
               /* Populate the cache entry */
               if (!FillCacheEntry( SelectionSrc, targetList[i], &((*ppCache)[i])))
-                  ERR("Failed to fill cache entry!");
+                  ERR("Failed to fill cache entry!\n");
 
               XFree(itemFmtName);
           }
@@ -453,8 +554,11 @@
     reqType = xe.xselection.target;
     
     if(prop == None)
+    {
+        TRACE("\tOwner failed to convert selection!\n");
         return bRet;
-
+    }
+       
     TRACE("\tretrieving property %s from window %ld into %s\n",
           XGetAtomName(g_display,reqType), (long)w, XGetAtomName(g_display,prop) );
 
@@ -600,7 +704,7 @@
             }
             else
             {
-                TRACE("Freeing %s (0x%x)...\n",
+                TRACE("Freeing %s (%p)...\n",
                       XGetAtomName(g_display, pCache[i].target), pCache[i].pData);
             
                 /* Free the cached data item (allocated by X) */
@@ -621,8 +725,10 @@
  */
 void EVENT_ProcessEvent( XEvent *event )
 {
-//  TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
-
+  /*
+  TRACE(" event %s for Window %08lx\n", event_names[event->type], event->xany.window );
+  */
+    
   switch (event->type)
   {
       case Expose:
@@ -652,7 +758,7 @@
           break;
         
       case PropertyNotify:
-          EVENT_PropertyNotify( (XPropertyEvent *)event );
+          // EVENT_PropertyNotify( (XPropertyEvent *)event );
           break;
 
       default: /* ignore all other events */
@@ -771,7 +877,6 @@
   XSelectionEvent result;
   Atom 	          rprop = None;
   Window          request = event->requestor;
-  BOOL            couldOpen = FALSE;
   Atom            xaMultiple = XInternAtom(g_display, "MULTIPLE", False);
   PCACHEENTRY     pCacheEntry = NULL;
   void            *pData = NULL;
@@ -803,7 +908,7 @@
   }
 
   /* Update the X property */
-  TRACE("\tUpdating property %s...", XGetAtomName(g_display, rprop));
+  TRACE("\tUpdating property %s...\n", XGetAtomName(g_display, rprop));
 
   /* If we have a request for a pixmap, return a duplicate */
   
@@ -853,17 +958,36 @@
     
   TRACE("()\n");
 
-  if (event->selection == XA_PRIMARY)
+  /* 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 ( g_clearAllSelections || (event->selection == xaClipboard) )
   {
-      g_selectionAcquired &= ~S_PRIMARY;     /* Clear the PRIMARY flag */
+      TRACE("Lost CLIPBOARD (+PRIMARY) selection\n");
+      
+      /* We really lost CLIPBOARD but want to voluntarily lose PRIMARY */
+      if ( (event->selection == xaClipboard)
+           && (g_selectionAcquired & S_PRIMARY) )
+      {
+          XSetSelectionOwner(g_display, XA_PRIMARY, None, CurrentTime);
+      }
+      
+      /* We really lost PRIMARY but want to voluntarily lose CLIPBOARD  */
+      if ( (event->selection == XA_PRIMARY)
+           && (g_selectionAcquired & S_CLIPBOARD) )
+      {
+          XSetSelectionOwner(g_display, xaClipboard, None, CurrentTime);
+      }
+      
+      g_selectionAcquired = S_NOSELECTION;   /* Clear the selection masks */
+  }
+  else if (event->selection == XA_PRIMARY)
+  {
       TRACE("Lost PRIMARY selection...\n");
+      g_selectionAcquired &= ~S_PRIMARY;     /* Clear the PRIMARY flag */
   }
-  else if (event->selection == xaClipboard)
-  {
-      g_selectionAcquired &= ~S_CLIPBOARD;   /* Clear the CLIPBOARD flag */
-      TRACE("Lost CLIPBOARD selection...\n");
-  }
-  
+
   /* Once we lose all our selections we have nothing more to do */
   if (g_selectionAcquired == S_NOSELECTION)
       TerminateServer(1);
@@ -915,7 +1039,7 @@
     unsigned border_width; /* Unused */
     unsigned int depth, width, height;
 
-    TRACE("\t() Pixmap=%ul\n", pixmap);
+    TRACE("\t() Pixmap=%ld\n", (long)pixmap);
           
     /* Get the Pixmap dimensions and bit depth */
     if ( 0 == XGetGeometry(g_display, pixmap, &root, &x, &y, &width, &height,
@@ -933,7 +1057,7 @@
 
     XDestroyImage(xi);
     
-    TRACE("\t() New Pixmap=%ul\n", newPixmap);
+    TRACE("\t() New Pixmap=%ld\n", (long)newPixmap);
     return newPixmap;
 }