xserver: Branch 'master' - 31 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Sep 29 13:06:46 PDT 2014


 configure.ac                        |    3 
 hw/xwin/InitInput.c                 |    1 
 hw/xwin/InitOutput.c                |   38 -
 hw/xwin/Makefile.am                 |   15 
 hw/xwin/win.h                       |    2 
 hw/xwin/winclipboard.h              |  126 -----
 hw/xwin/winclipboard/Makefile.am    |   25 +
 hw/xwin/winclipboard/debug.c        |   52 ++
 hw/xwin/winclipboard/internal.h     |  109 ++++
 hw/xwin/winclipboard/textconv.c     |  151 ++++++
 hw/xwin/winclipboard/thread.c       |  498 ++++++++++++++++++++
 hw/xwin/winclipboard/winclipboard.h |   36 +
 hw/xwin/winclipboard/wndproc.c      |  531 ++++++++++++++++++++++
 hw/xwin/winclipboard/xevents.c      |  862 ++++++++++++++++++++++++++++++++++++
 hw/xwin/winclipboard/xwinclip.c     |  127 +++++
 hw/xwin/winclipboard/xwinclip.man   |   61 ++
 hw/xwin/winclipboardinit.c          |  150 +++---
 hw/xwin/winclipboardtextconv.c      |  147 ------
 hw/xwin/winclipboardthread.c        |  468 -------------------
 hw/xwin/winclipboardwndproc.c       |  529 ----------------------
 hw/xwin/winclipboardwrappers.c      |  226 ---------
 hw/xwin/winclipboardxevents.c       |  703 -----------------------------
 hw/xwin/windialogs.c                |    7 
 hw/xwin/winglobals.c                |   13 
 hw/xwin/winglobals.h                |    4 
 hw/xwin/winwndproc.c                |    3 
 26 files changed, 2548 insertions(+), 2339 deletions(-)

New commits:
commit 78c27d12e1f4857bfcfc92afbb69d5dd989232b9
Merge: 6e50bfa 1d6334d
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Sep 29 13:04:49 2014 -0700

    Merge remote-tracking branch 'jturney/xwin-clipboard-refactoring'

commit 1d6334dd0ca99923b6b55c5c047ef6b5c325f66c
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jun 19 13:09:35 2013 +0100

    hw/xwin: Undefine _XSERVER64 in hw/xwin/winclipboard
    
    Including any server header might define the macro _XSERVER64 on 64 bit
    machines. That macro must _NOT_ be defined for Xlib client code, otherwise bad
    things happen. So let's undef that macro if necessary.
    
    Remove server directories from include path to ensure no server includes are
    included
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
index 614e7ec..b1c95f4 100644
--- a/hw/xwin/winclipboard/Makefile.am
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -9,8 +9,7 @@ libXWinclipboard_la_SOURCES = \
 
 libXWinclipboard_la_CFLAGS = -DHAVE_XWIN_CONFIG_H \
 			     $(DIX_CFLAGS) \
-			     $(XWINMODULES_CFLAGS) \
-		             -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/..
+			     $(XWINMODULES_CFLAGS)
 
 libXWinclipboard_la_LDFLAGS = -static -no-undefined
 
diff --git a/hw/xwin/winclipboard/textconv.c b/hw/xwin/winclipboard/textconv.c
index 4262d98..9c9cb35 100644
--- a/hw/xwin/winclipboard/textconv.c
+++ b/hw/xwin/winclipboard/textconv.c
@@ -31,6 +31,16 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
+
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
 #include <stdlib.h>
 #include "internal.h"
 
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index a124e3e..c179e3f 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -36,6 +36,15 @@
 #define HAS_WINSOCK 1
 #endif
 
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
 #include <assert.h>
 #include <unistd.h>
 #include <fcntl.h>
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index 973f948..165ff55 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -34,6 +34,15 @@
 #include <xwin-config.h>
 #endif
 
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
 #include <sys/types.h>
 #include <sys/time.h>
 
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
index 8a75bc4..d0077b8 100644
--- a/hw/xwin/winclipboard/xevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -34,6 +34,15 @@
 #include <xwin-config.h>
 #endif
 
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
 #include "internal.h"
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
diff --git a/hw/xwin/winclipboard/xwinclip.c b/hw/xwin/winclipboard/xwinclip.c
index 7b45770..3677974 100644
--- a/hw/xwin/winclipboard/xwinclip.c
+++ b/hw/xwin/winclipboard/xwinclip.c
@@ -35,6 +35,15 @@
 #include <xwin-config.h>
 #endif
 
+/*
+ * Including any server header might define the macro _XSERVER64 on 64 bit machines.
+ * That macro must _NOT_ be defined for Xlib client code, otherwise bad things happen.
+ * So let's undef that macro if necessary.
+ */
+#ifdef _XSERVER64
+#undef _XSERVER64
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
commit 7ca93301940647219dbed2d14fcd3f37e49fb477
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Jun 18 19:53:52 2013 +0100

    hw/xwin: Only add to XSetIOErrorHandler() handler chain once
    
    Only use XSetIOErrorHandler() to add to the global XSetIOErrorHandler() chain
    once.  If we do it every restart, then we make a loop in the handler chain, and
    we end up with a thread spinning in that loop when the server shuts down...
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 31986f6..a124e3e 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -113,6 +113,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
     Window iWindow = None;
     int iSelectError;
     Bool fShutdown = FALSE;
+    static Bool fErrorHandlerSet = FALSE;
 
     winDebug("winClipboardProc - Hello\n");
 
@@ -127,11 +128,15 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
         ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
     }
 
-    /* Set error handler */
-    XSetErrorHandler(winClipboardErrorHandler);
     g_winClipboardProcThread = pthread_self();
-    g_winClipboardOldIOErrorHandler =
-        XSetIOErrorHandler(winClipboardIOErrorHandler);
+
+    /* Set error handler */
+    if (!fErrorHandlerSet) {
+      XSetErrorHandler(winClipboardErrorHandler);
+      g_winClipboardOldIOErrorHandler =
+         XSetIOErrorHandler(winClipboardIOErrorHandler);
+      fErrorHandlerSet = TRUE;
+    }
 
     /* Set jump point for Error exits */
     if (setjmp(g_jmpEntry)) {
commit 5819a02d461349dbfc86317c742406d2217f7f0c
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Jun 18 19:35:20 2013 +0100

    hw/xwin: Add a basic manpage for xwinclip
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
index b52e0e7..614e7ec 100644
--- a/hw/xwin/winclipboard/Makefile.am
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -21,3 +21,6 @@ xwinclip_SOURCES = xwinclip.c debug.c
 xwinclip_CFLAGS = $(XWINMODULES_CFLAGS)
 
 xwinclip_LDADD = libXWinclipboard.la $(XWINMODULES_LIBS) -lgdi32
+
+include $(top_srcdir)/manpages.am
+appman_PRE = xwinclip.man
diff --git a/hw/xwin/winclipboard/xwinclip.man b/hw/xwin/winclipboard/xwinclip.man
new file mode 100644
index 0000000..822db91
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.man
@@ -0,0 +1,61 @@
+.TH xwinclip 1 __xorgversion__
+.SH NAME
+xwinclip - An X11 and Windows clipboard integration tool
+
+.SH SYNOPSIS
+.B xwinclip [OPTION]...
+
+.SH DESCRIPTION
+\fIxwinclip\fP is a tool for copying and pasting text between the Windows and X11 clipboard systems.
+
+\fIxwinclip\fP watches for updates to either clipboard and copies data between them when either one is updated.
+
+\fIxwinclip\fP monitors the X PRIMARY and CLIBPOARD selections for changes in ownership, and makes
+the contents of the most recent one to change available to paste from the Windows clipboard.
+
+It also monitors the contents of the Windows clipboard for changes, taking ownership of the PRIMARY and
+CLIPBOARD selections, and making the contents of the Windows clipboard available in them.
+
+.B Note well:
+The \fIXWin(1)\fP X server has internal clipboard integration that is enabled by default.
+Do \fINOT\fP run \fIxwinclip\fP unless \fIXWin(1)\fP has been started with the -noclipboard option.
+
+.SH OPTIONS
+\fIxwinclip\fP accepts the following optional command line switches:
+
+.TP 8
+.B \-display [display]
+Specifies the X server display to connect to.
+.TP 8
+.B \-nounicodeclipboard
+Do not use unicode text on the clipboard.
+
+.SH "SEE ALSO"
+XWin(1)
+
+.SH BUGS
+Only text clipboard contents are supported.
+
+The INCR (Incrememntal transfer) clipboard protocol for clipboard contents larger than the maximum size of an
+X request is not supported.
+
+Some X clients, notably ones written in Tcl/Tk, do not re-assert ownership of the PRIMARY selection or update
+it's timestamp when it's contents change, which currently prevents \fIxwinclip\fP from correctly noticing that
+the PRIMARY selection's contents have changed.
+
+Windows clipboard rendering is synchronous in the WM_RENDER*FORMAT message (that is, we must have placed the
+contents onto the clipboard by the time we return from processing this message), but we must wait for the X
+client which owns the selection to convert the selection to our requested format.  This is currently achieved
+using a fixed timeout of one second.
+
+The XWin(1) server should indicate somehow (by placing an atom on the root window?) that it is running with it's
+internal clipboard integration enabled, and xwinclip should notice this and exit with an appropriate error.
+
+Probably many other bugs.
+
+.SH "CONFORMING TO"
+ICCCM (Inter-Client Communication Conventions Manual) 2.0
+
+.SH AUTHORS
+Contributors to xwinclip include Benjamin Riefenstahl, Roland Cassard, Brian Genisio, Colin Harrison,
+Harold L Hunt II, Matsuzaki Kensuke, Jon Turney, Chris Twiner and Jeremy Wilkins.
commit 492c924c8531b013d50637e29213da287b9a7fa2
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Jun 18 19:28:53 2013 +0100

    hw/xwin: In clipboard function prototypes, use Window type, not int type
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index 4b3531a..94956f8 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -97,7 +97,7 @@ typedef struct
 
 int
 winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
+                         Window iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
 
 
 Atom
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index fa84894..973f948 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -54,7 +54,7 @@
  */
 
 static int
-winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
+winProcessXEventsTimeout(HWND hwnd, Window iWindow, Display * pDisplay,
                          Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
 {
     int iConnNumber;
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
index d1e7df4..8a75bc4 100644
--- a/hw/xwin/winclipboard/xevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -129,7 +129,7 @@ winClipboardInitMonitoredSelections(void)
 
 int
 winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
+                         Window iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
 {
     Atom atomClipboard = atoms->atomClipboard;
     Atom atomLocalProperty = atoms->atomLocalProperty;
commit 4a38c3bda2b0a868d7611f9423d8a0f304b435aa
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Jun 18 19:18:08 2013 +0100

    hw/xwin: Remove XOpenDisplay() retry code
    
    Remove XOpenDisplay() retry code.  This isn't a sensible thing for the
    application to be doing, and XWin server needs to retry much more than just
    XOpenDisplay().
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 53e28c4..31986f6 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -111,7 +111,6 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
     int iMaxDescriptor;
     Display *pDisplay = NULL;
     Window iWindow = None;
-    int iRetries;
     int iSelectError;
     Bool fShutdown = FALSE;
 
@@ -140,26 +139,8 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
         goto winClipboardProc_Done;
     }
 
-    /* Initialize retry count */
-    iRetries = 0;
-
-
-    /* Open the X display */
-    do {
-        pDisplay = XOpenDisplay(szDisplay);
-        if (pDisplay == NULL) {
-            ErrorF("winClipboardProc - Could not open display, "
-                   "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
-            ++iRetries;
-            sleep(WIN_CONNECT_DELAY);
-            continue;
-        }
-        else
-            break;
-    }
-    while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
-
     /* Make sure that the display opened */
+    pDisplay = XOpenDisplay(szDisplay);
     if (pDisplay == NULL) {
         ErrorF("winClipboardProc - Failed opening the display, giving up\n");
         goto winClipboardProc_Done;
commit 4fc62aef8079266f8878cb355e6eb894000d8b8b
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jun 19 14:00:28 2013 +0100

    hw/xwin: Improve comment about why we can't XCloseDisplay()
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 8f0ede5..53e28c4 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -370,8 +370,11 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
 
 #if 0
     /*
-     * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26.  The
-     * XSync and XSelectInput calls did not help.
+     * FIXME: XCloseDisplay hangs if we call it
+     *
+     * XCloseDisplay() calls XSync(), so any outstanding errors are reported.
+     * If we are built into the server, this can deadlock if the server is
+     * in the process of exiting and waiting for this thread to exit.
      */
 
     /* Discard any remaining events */
commit 89eb7bdcad092821b61a48832e1db82975a2252b
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jun 19 13:59:40 2013 +0100

    hw/xwin: Remove setjmp()/longjmp() error constants
    
    Check specially that setjmp() returned a value which we don't pass to longjmp()
    seems a bit over-complex.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index 34563e1..4b3531a 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -38,8 +38,6 @@
 /* Windows headers */
 #include <X11/Xwindows.h>
 
-#define WIN_JMP_OKAY				0
-#define WIN_JMP_ERROR_IO			2
 #define WIN_XEVENTS_SUCCESS			0
 #define WIN_XEVENTS_CONVERT			2
 #define WIN_XEVENTS_NOTIFY			3
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 72d56d5..8f0ede5 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -135,16 +135,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
         XSetIOErrorHandler(winClipboardIOErrorHandler);
 
     /* Set jump point for Error exits */
-    iReturn = setjmp(g_jmpEntry);
-
-    /* Check if we should continue operations */
-    if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
-        /* setjmp returned an unknown value, exit */
-        ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
-        goto winClipboardProc_Exit;
-    }
-    else if (iReturn == WIN_JMP_ERROR_IO) {
-        /* TODO: Cleanup the Win32 window and free any allocated memory */
+    if (setjmp(g_jmpEntry)) {
         ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
         goto winClipboardProc_Done;
     }
@@ -483,7 +474,7 @@ winClipboardIOErrorHandler(Display * pDisplay)
 
     if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
         /* Restart at the main entry point */
-        longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
+        longjmp(g_jmpEntry, 2);
     }
 
     if (g_winClipboardOldIOErrorHandler)
commit d0353bbe57aab910a6ef7da8778023a9d39c37df
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jun 20 00:04:16 2013 +0100

    hw/xwin: Move WIN_MSG_QUEUE_FNAME to where it's used
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index e517123..34563e1 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -38,13 +38,8 @@
 /* Windows headers */
 #include <X11/Xwindows.h>
 
-/* Clipboard module constants */
-#ifdef HAS_DEVWINDOWS
-#define WIN_MSG_QUEUE_FNAME			"/dev/windows"
-#endif
 #define WIN_JMP_OKAY				0
 #define WIN_JMP_ERROR_IO			2
-
 #define WIN_XEVENTS_SUCCESS			0
 #define WIN_XEVENTS_CONVERT			2
 #define WIN_XEVENTS_NOTIFY			3
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 289bbb3..72d56d5 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -59,6 +59,9 @@
 
 #define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
 #define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
+#ifdef HAS_DEVWINDOWS
+#define WIN_MSG_QUEUE_FNAME "/dev/windows"
+#endif
 
 /*
  * Global variables
commit fa0da5a020c2ea9366568375b7f35d3f2ddad680
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jun 20 13:04:35 2013 +0100

    hw/xwin: Use header for prototypes in textconv.c
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/textconv.c b/hw/xwin/winclipboard/textconv.c
index fd405a0..4262d98 100644
--- a/hw/xwin/winclipboard/textconv.c
+++ b/hw/xwin/winclipboard/textconv.c
@@ -31,14 +31,8 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
-#include "win.h"
-#include <stdio.h>
 #include <stdlib.h>
-
-void
- winClipboardDOStoUNIX(char *pszSrc, int iLength);
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
+#include "internal.h"
 
 /*
  * Convert \r\n to \n
commit cbe133752d1e817246b532a274fda3f7d74ebca1
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Thu Jun 20 12:50:18 2013 +0100

    hw/xwin: Remove unused X includes from internal.h and add them where needed
    
    Also removing server headers we might clash with and no longer need.  Make
    a few adjustments to allow for this change:
    
    - provide a prototype of ErrorF()
    - use the MAX() macro provided by sys/param.h, not the max() macro provided by misc.h
    - use the X 'Bool' type rather than the unwrapped Windows 'BOOL' type
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index 0f9a656..e517123 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -33,10 +33,7 @@
 #define WINCLIPBOARD_INTERNAL_H
 
 /* X headers */
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
+#include <X11/Xlib.h>
 
 /* Windows headers */
 #include <X11/Xwindows.h>
@@ -59,7 +56,7 @@
  */
 
 extern void winDebug(const char *format, ...);
-extern void winErrorFVerb(int verb, const char *format, ...);
+extern void ErrorF(const char *format, ...);
 
 /*
  * winclipboardtextconv.c
@@ -89,7 +86,7 @@ typedef struct
  * winclipboardwndproc.c
  */
 
-BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+Bool winClipboardFlushWindowsMessageQueue(HWND hwnd);
 
 LRESULT CALLBACK
 winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index ea0ef42..289bbb3 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -41,6 +41,7 @@
 #include <fcntl.h>
 #include <setjmp.h>
 #include <pthread.h>
+#include <sys/param.h> // for MAX() macro
 
 #ifdef HAS_WINSOCK
 #include <X11/Xwinsock.h>
@@ -48,7 +49,7 @@
 #include <errno.h>
 #endif
 
-#include "misc.h"
+#include <X11/Xatom.h>
 #include <X11/extensions/Xfixes.h>
 #include "winclipboard.h"
 #include "internal.h"
@@ -185,7 +186,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
     }
 
     /* Find max of our file descriptors */
-    iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
+    iMaxDescriptor = MAX(fdMessageQueue, iConnectionNumber) + 1;
 #else
     iMaxDescriptor = iConnectionNumber + 1;
 #endif
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index 28e7ade..fa84894 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -37,8 +37,9 @@
 #include <sys/types.h>
 #include <sys/time.h>
 
+#include <X11/Xatom.h>
+
 #include "internal.h"
-#include "misc.h"
 #include "winclipboard.h"
 
 /*
@@ -499,7 +500,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  * Process any pending Windows messages
  */
 
-BOOL
+Bool
 winClipboardFlushWindowsMessageQueue(HWND hwnd)
 {
     MSG msg;
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
index 7275552..d1e7df4 100644
--- a/hw/xwin/winclipboard/xevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -35,7 +35,8 @@
 #endif
 
 #include "internal.h"
-#include "misc.h"
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
 #include <X11/extensions/Xfixes.h>
 
 /*
commit 52f3cf3c612b2f33e39fd6f985b840a0d7192a50
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jun 19 18:09:07 2013 +0100

    hw/xwin: Remove standard includes from internal.h and add them where needed
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index e31db54..0f9a656 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -32,20 +32,6 @@
 #ifndef WINCLIPBOARD_INTERNAL_H
 #define WINCLIPBOARD_INTERNAL_H
 
-/* Standard library headers */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef __CYGWIN__
-#include <sys/select.h>
-#else
-#include <X11/Xwinsock.h>
-#endif
-#include <fcntl.h>
-#include <setjmp.h>
-#include <pthread.h>
-
 /* X headers */
 #include <X11/X.h>
 #include <X11/Xatom.h>
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 0d64cce..ea0ef42 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -36,10 +36,15 @@
 #define HAS_WINSOCK 1
 #endif
 
-#include <sys/types.h>
-#include <signal.h>
-#include "windisplay.h"
-#ifdef __CYGWIN__
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <pthread.h>
+
+#ifdef HAS_WINSOCK
+#include <X11/Xwinsock.h>
+#else
 #include <errno.h>
 #endif
 
commit 5992550c4cf8818d1c47c1e474c3d8c3383983fa
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 19:01:19 2013 +0100

    hw/xwin: Add xwinclip test client
    
    Add xwinclip test client, which includes stubs for winDebug(), ErrorF()
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
index 91cc116..b52e0e7 100644
--- a/hw/xwin/winclipboard/Makefile.am
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -13,3 +13,11 @@ libXWinclipboard_la_CFLAGS = -DHAVE_XWIN_CONFIG_H \
 		             -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/..
 
 libXWinclipboard_la_LDFLAGS = -static -no-undefined
+
+bin_PROGRAMS = xwinclip
+
+xwinclip_SOURCES = xwinclip.c debug.c
+
+xwinclip_CFLAGS = $(XWINMODULES_CFLAGS)
+
+xwinclip_LDADD = libXWinclipboard.la $(XWINMODULES_LIBS) -lgdi32
diff --git a/hw/xwin/winclipboard/debug.c b/hw/xwin/winclipboard/debug.c
new file mode 100644
index 0000000..78ab6d9
--- /dev/null
+++ b/hw/xwin/winclipboard/debug.c
@@ -0,0 +1,52 @@
+//
+// Copyright © Jon TURNEY 2013
+//
+// This file is part of xwinclip.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if 1
+int
+winDebug(const char *format, ...)
+{
+  int count;
+  va_list ap;
+  va_start(ap, format);
+  count = fprintf(stderr, "xwinclip: ");
+  count += vfprintf(stderr, format, ap);
+  va_end(ap);
+  return count;
+}
+#endif
+
+int
+ErrorF(const char *format, ...)
+{
+  int count;
+  va_list ap;
+  va_start(ap, format);
+  count = vfprintf(stderr, format, ap);
+  va_end(ap);
+  return count;
+}
diff --git a/hw/xwin/winclipboard/xwinclip.c b/hw/xwin/winclipboard/xwinclip.c
new file mode 100644
index 0000000..7b45770
--- /dev/null
+++ b/hw/xwin/winclipboard/xwinclip.c
@@ -0,0 +1,118 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors:	Harold L Hunt II
+ *              Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* X headers */
+#include <X11/Xlib.h>
+#ifdef X_LOCALE
+#include <X11/Xlocale.h>
+#else /* X_LOCALE */
+#include <locale.h>
+#endif /* X_LOCALE */
+
+#include "winclipboard.h"
+
+/*
+ * Main function
+ */
+
+int
+main (int argc, char *argv[])
+{
+  int			i;
+  char			*pszDisplay = NULL;
+  int			fUnicodeClipboard = 1;
+
+  /* Parse command-line parameters */
+  for (i = 1; i < argc; ++i)
+    {
+      /* Look for -display "display_name" or --display "display_name" */
+      if (i < argc - 1
+	  && (!strcmp (argv[i], "-display")
+	      || !strcmp (argv[i], "--display")))
+	{
+	  /* Grab a pointer to the display parameter */
+	  pszDisplay = argv[i + 1];
+
+	  /* Skip the display argument */
+	  i++;
+	  continue;
+	}
+
+      /* Look for -nounicodeclipboard */
+      if (!strcmp (argv[i], "-nounicodeclipboard"))
+	{
+	  fUnicodeClipboard = 0;
+	  continue;
+	}
+
+      /* Yack when we find a parameter that we don't know about */
+      printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
+      exit (1);
+    }
+
+  /* Do we have Unicode support? */
+  if (fUnicodeClipboard)
+    {
+      printf ("Unicode clipboard I/O\n");
+    }
+  else
+    {
+      printf ("Non Unicode clipboard I/O\n");
+    }
+
+  /* Apply locale specified in the LANG environment variable */
+  if (!setlocale (LC_ALL, ""))
+    {
+      printf ("setlocale() error\n");
+      exit (1);
+    }
+
+  /* See if X supports the current locale */
+  if (XSupportsLocale () == False)
+    {
+      printf ("Locale not supported by X, falling back to 'C' locale.\n");
+      setlocale(LC_ALL, "C");
+    }
+
+  winClipboardProc(fUnicodeClipboard, pszDisplay);
+
+  return 0;
+}
commit 5ae674ae6d6c0b02fd86c5e7b23b8c38b19f180a
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 20:03:04 2013 +0100

    hw/xwin: Changes in error logging to make libwinclipboard more useful as a library
    
    Consistently use ErrorF() rather than winErrorFVerb()
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index affedf0..28e7ade 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -189,8 +189,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             s_hwndNextViewer = (HWND) lParam;
             if (s_hwndNextViewer == hwnd) {
                 s_hwndNextViewer = NULL;
-                winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
-                              "attempted to set next window to ourselves.");
+                ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
+                       "attempted to set next window to ourselves.");
             }
         }
         else if (s_hwndNextViewer)
@@ -262,8 +262,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             s_fCBCInitialized = FALSE;
             ChangeClipboardChain(hwnd, s_hwndNextViewer);
             winFixClipboardChain();
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Nested calls detected.  Re-initing.\n");
+            ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                   "Nested calls detected.  Re-initing.\n");
             winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
             s_fProcessingDrawClipboard = FALSE;
             return 0;
@@ -325,9 +325,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                 XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
             }
             else if (BadWindow == iReturn || BadAtom == iReturn)
-                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                              "XGetSelection failed for PRIMARY: %d\n",
-                              iReturn);
+                ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                       "XGetSelectionOwner failed for PRIMARY: %d\n",
+                       iReturn);
 
             /* Release CLIPBOARD selection if owned */
             iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
@@ -337,9 +337,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                 XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
             }
             else if (BadWindow == iReturn || BadAtom == iReturn)
-                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                              "XGetSelection failed for CLIPBOARD: %d\n",
-                              iReturn);
+                ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                       "XGetSelectionOwner failed for CLIPBOARD: %d\n",
+                       iReturn);
 
             winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
             s_fProcessingDrawClipboard = FALSE;
@@ -353,8 +353,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                      XA_PRIMARY, iWindow, CurrentTime);
         if (iReturn == BadAtom || iReturn == BadWindow ||
             XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Could not reassert ownership of PRIMARY\n");
+            ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                   "Could not reassert ownership of PRIMARY\n");
         }
         else {
             winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -367,8 +367,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         if (iReturn == BadAtom || iReturn == BadWindow ||
             XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Could not reassert ownership of CLIPBOARD\n");
+            ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                    "Could not reassert ownership of CLIPBOARD\n");
         }
         else {
             winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -421,8 +421,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                     atoms->atomLocalProperty,
                                     iWindow, CurrentTime);
         if (iReturn == BadAtom || iReturn == BadWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
-                          "XConvertSelection () failed\n");
+            ErrorF("winClipboardWindowProc - WM_RENDER*FORMAT - "
+                   "XConvertSelection () failed\n");
             break;
         }
 
@@ -436,16 +436,16 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             }
 
             if (!OpenClipboard(hwnd)) {
-                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
-                              "OpenClipboard () failed: %08x\n",
-                              GetLastError());
+                ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+                       "OpenClipboard () failed: %08x\n",
+                       GetLastError());
                 break;
             }
 
             if (!EmptyClipboard()) {
-                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
-                              "EmptyClipboard () failed: %08x\n",
-                              GetLastError());
+                ErrorF("winClipboardWindowProc - WM_RENDER*FORMATS - "
+                       "EmptyClipboard () failed: %08x\n",
+                       GetLastError());
                 break;
             }
         }
@@ -479,10 +479,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             /* We must close the clipboard */
 
             if (!CloseClipboard()) {
-                winErrorFVerb(1,
-                              "winClipboardWindowProc - WM_RENDERALLFORMATS - "
-                              "CloseClipboard () failed: %08x\n",
-                              GetLastError());
+                ErrorF("winClipboardWindowProc - WM_RENDERALLFORMATS - "
+                       "CloseClipboard () failed: %08x\n",
+                       GetLastError());
                 break;
             }
         }
commit e1cf2b47bea9ff3e64c0ef1e4d0744d9df4bc1b7
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 19:58:20 2013 +0100

    hw/xwin: Look up atoms in winClipboardProc()
    
    Look up all atoms of interest in clipboard code in winClipboardProc() and pass
    them down.
    
    This avoids the need to check serverGeneration to notice when we need to
    invalidate cached atom values.
    
    Also consistently use cached atom values everywhere, rather than sometimes just
    doing XInternAtom() again.
    
    Remove WIN_LOCAL_PROPERTY as unused now, as we only refer to CYGX_CUT_BUFFER
    once and do that directly.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
index 89f0c39..e31db54 100644
--- a/hw/xwin/winclipboard/internal.h
+++ b/hw/xwin/winclipboard/internal.h
@@ -61,7 +61,7 @@
 #endif
 #define WIN_JMP_OKAY				0
 #define WIN_JMP_ERROR_IO			2
-#define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
+
 #define WIN_XEVENTS_SUCCESS			0
 #define WIN_XEVENTS_CONVERT			2
 #define WIN_XEVENTS_NOTIFY			3
@@ -90,6 +90,15 @@ void
  */
 
 
+typedef struct
+{
+    Atom atomClipboard;
+    Atom atomLocalProperty;
+    Atom atomUTF8String;
+    Atom atomCompoundText;
+    Atom atomTargets;
+} ClipboardAtoms;
+
 /*
  * winclipboardwndproc.c
  */
@@ -103,6 +112,7 @@ typedef struct
 {
   Display *pClipboardDisplay;
   Window iClipboardWindow;
+  ClipboardAtoms *atoms;
 } ClipboardWindowCreationParams;
 
 /*
@@ -111,11 +121,11 @@ typedef struct
 
 int
 winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+                         int iWindow, Display * pDisplay, Bool fUnicodeSupport, ClipboardAtoms *atom);
 
 
 Atom
-winClipboardGetLastOwnedSelectionAtom(void);
+winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms);
 
 void
 winClipboardInitMonitoredSelections(void);
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index a9565fe..0d64cce 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -71,7 +71,7 @@ int xfixes_error_base;
  */
 
 static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow);
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms);
 
 static int
  winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -88,7 +88,7 @@ static int
 Bool
 winClipboardProc(Bool fUseUnicode, char *szDisplay)
 {
-    Atom atomClipboard;
+    ClipboardAtoms atoms;
     int iReturn;
     HWND hwnd = NULL;
     int iConnectionNumber = 0;
@@ -188,8 +188,12 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
     if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
       ErrorF ("winClipboardProc - XFixes extension not present\n");
 
-    /* Create atom */
-    atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+    /* Create atoms */
+    atoms.atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+    atoms.atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False);
+    atoms.atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
+    atoms.atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
+    atoms.atomTargets = XInternAtom (pDisplay, "TARGETS", False);
 
     /* Create a messaging window */
     iWindow = XCreateSimpleWindow(pDisplay,
@@ -220,7 +224,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
 
     XFixesSelectSelectionInput (pDisplay,
                                 iWindow,
-                                XInternAtom (pDisplay, "CLIPBOARD", False),
+                                atoms.atomClipboard,
                                 XFixesSetSelectionOwnerNotifyMask |
                                 XFixesSelectionWindowDestroyNotifyMask |
                                 XFixesSelectionClientCloseNotifyMask);
@@ -229,7 +233,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
     /* Initialize monitored selection state */
     winClipboardInitMonitoredSelections();
     /* Create Windows messaging window */
-    hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow);
+    hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow, &atoms);
 
     /* Save copy of HWND */
     g_hwndClipboard = hwnd;
@@ -246,10 +250,10 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
         }
 
         /* CLIPBOARD */
-        iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
+        iReturn = XSetSelectionOwner(pDisplay, atoms.atomClipboard,
                                      iWindow, CurrentTime);
         if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+            XGetSelectionOwner(pDisplay, atoms.atomClipboard) != iWindow) {
             ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
             goto winClipboardProc_Done;
         }
@@ -261,7 +265,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
      *       because there may be events in local data structures
      *       already.
      */
-    winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+    winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
 
     /* Pre-flush Windows messages */
     if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
@@ -319,7 +323,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
         /* Branch on which descriptor became active */
         if (FD_ISSET(iConnectionNumber, &fdsRead)) {
             /* Process X events */
-            winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+            winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode, &atoms);
         }
 
 #ifdef HAS_DEVWINDOWS
@@ -393,7 +397,7 @@ winClipboardProc(Bool fUseUnicode, char *szDisplay)
  */
 
 static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow)
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow, ClipboardAtoms *atoms)
 {
     WNDCLASSEX wc;
     ClipboardWindowCreationParams cwcp;
@@ -417,6 +421,7 @@ winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow)
     /* Information to be passed to WM_CREATE */
     cwcp.pClipboardDisplay = pDisplay;
     cwcp.iClipboardWindow = iWindow;
+    cwcp.atoms = atoms;
 
     /* Create the window */
     hwnd = CreateWindowExA(0,   /* Extended styles */
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index 769422b..affedf0 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -54,7 +54,7 @@
 
 static int
 winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
-                         Bool fUseUnicode, int iTimeoutSec)
+                         Bool fUseUnicode, ClipboardAtoms *atoms, int iTimeoutSec)
 {
     int iConnNumber;
     struct timeval tv;
@@ -107,7 +107,7 @@ winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
             /* Process X events */
             /* Exit when we see that server is shutting down */
             iReturn = winClipboardFlushXEvents(hwnd,
-                                               iWindow, pDisplay, fUseUnicode);
+                                               iWindow, pDisplay, fUseUnicode, atoms);
 
             winDebug
                 ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
@@ -137,6 +137,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     static Bool s_fCBCInitialized;
     static Display *pDisplay;
     static Window iWindow;
+    static ClipboardAtoms *atoms;
 
     /* Branch on message type */
     switch (message) {
@@ -163,6 +164,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         pDisplay = cwcp->pClipboardDisplay;
         iWindow = cwcp->iClipboardWindow;
+        atoms = cwcp->atoms;
 
         first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
         if (first == hwnd)
@@ -243,18 +245,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
     case WM_DRAWCLIPBOARD:
     {
-        static Atom atomClipboard;
-        static int generation;
         static Bool s_fProcessingDrawClipboard = FALSE;
         int iReturn;
 
         winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
 
-        if (generation != serverGeneration) {
-            generation = serverGeneration;
-            atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
-        }
-
         /*
          * We've occasionally seen a loop in the clipboard chain.
          * Try and fix it on the first hint of recursion.
@@ -335,11 +330,11 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                               iReturn);
 
             /* Release CLIPBOARD selection if owned */
-            iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
+            iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
             if (iReturn == iWindow) {
                 winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                         "CLIPBOARD selection is owned by us.\n");
-                XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
+                         "CLIPBOARD selection is owned by us, releasing\n");
+                XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
             }
             else if (BadWindow == iReturn || BadAtom == iReturn)
                 winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
@@ -368,10 +363,10 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         /* Reassert ownership of the CLIPBOARD */
         iReturn = XSetSelectionOwner(pDisplay,
-                                     atomClipboard, iWindow, CurrentTime);
+                                     atoms->atomClipboard, iWindow, CurrentTime);
 
         if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+            XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
             winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                           "Could not reassert ownership of CLIPBOARD\n");
         }
@@ -421,11 +416,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         /* Request the selection contents */
         iReturn = XConvertSelection(pDisplay,
-                                    winClipboardGetLastOwnedSelectionAtom(),
-                                    XInternAtom(pDisplay,
-                                                "COMPOUND_TEXT", False),
-                                    XInternAtom(pDisplay,
-                                                "CYGX_CUT_BUFFER", False),
+                                    winClipboardGetLastOwnedSelectionAtom(atoms),
+                                    atoms->atomCompoundText,
+                                    atoms->atomLocalProperty,
                                     iWindow, CurrentTime);
         if (iReturn == BadAtom || iReturn == BadWindow) {
             winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
@@ -461,7 +454,9 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         iReturn = winProcessXEventsTimeout(hwnd,
                                            iWindow,
                                            pDisplay,
-                                           fConvertToUnicode, WIN_POLL_TIMEOUT);
+                                           fConvertToUnicode,
+                                           atoms,
+                                           WIN_POLL_TIMEOUT);
 
         /*
          * The last call to winProcessXEventsTimeout
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
index 3fcf6e3..7275552 100644
--- a/hw/xwin/winclipboard/xevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -62,7 +62,6 @@ static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
     { "PRIMARY", "CLIPBOARD" };
 
 static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
-static Atom atomClipboard = None;
 
 static void
 MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
@@ -98,7 +97,7 @@ MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
 }
 
 Atom
-winClipboardGetLastOwnedSelectionAtom(void)
+winClipboardGetLastOwnedSelectionAtom(ClipboardAtoms *atoms)
 {
     if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
         return None;
@@ -107,7 +106,7 @@ winClipboardGetLastOwnedSelectionAtom(void)
         return XA_PRIMARY;
 
     if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
-        return atomClipboard;
+        return atoms->atomClipboard;
 
     return None;
 }
@@ -129,22 +128,13 @@ winClipboardInitMonitoredSelections(void)
 
 int
 winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUseUnicode)
+                         int iWindow, Display * pDisplay, Bool fUseUnicode, ClipboardAtoms *atoms)
 {
-    static Atom atomLocalProperty;
-    static Atom atomCompoundText;
-    static Atom atomUTF8String;
-    static Atom atomTargets;
-    static int generation;
-
-    if (generation != serverGeneration) {
-        generation = serverGeneration;
-        atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
-        atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
-        atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
-        atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
-        atomTargets = XInternAtom(pDisplay, "TARGETS", False);
-    }
+    Atom atomClipboard = atoms->atomClipboard;
+    Atom atomLocalProperty = atoms->atomLocalProperty;
+    Atom atomUTF8String = atoms->atomUTF8String;
+    Atom atomCompoundText = atoms->atomCompoundText;
+    Atom atomTargets = atoms->atomTargets;
 
     /* Process all pending events */
     while (XPending(pDisplay)) {
commit be61a1fc7e25a380f8d506e13b22017492a71913
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 19:07:05 2013 +0100

    hw/xwin: Add fUseUnicode as parameter to winClipboardProc()
    
    Add fUseUnicode as parameter to winClipboardProc()
    Access g_fUseUnicode global when calling it
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 36a1b4e..a9565fe 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -55,12 +55,6 @@
 #define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
 
 /*
- * References to external symbols
- */
-
-extern Bool g_fUnicodeClipboard;
-
-/*
  * Global variables
  */
 
@@ -69,7 +63,6 @@ static jmp_buf g_jmpEntry;
 static XIOErrorHandler g_winClipboardOldIOErrorHandler;
 static pthread_t g_winClipboardProcThread;
 
-Bool g_fUseUnicode = FALSE;
 int xfixes_event_base;
 int xfixes_error_base;
 
@@ -93,7 +86,7 @@ static int
  */
 
 Bool
-winClipboardProc(char *szDisplay)
+winClipboardProc(Bool fUseUnicode, char *szDisplay)
 {
     Atom atomClipboard;
     int iReturn;
@@ -110,18 +103,11 @@ winClipboardProc(char *szDisplay)
     Display *pDisplay = NULL;
     Window iWindow = None;
     int iRetries;
-    Bool fUseUnicode;
     int iSelectError;
     Bool fShutdown = FALSE;
 
     winDebug("winClipboardProc - Hello\n");
 
-    /* Do we use Unicode clipboard? */
-    fUseUnicode = g_fUnicodeClipboard;
-
-    /* Save the Unicode support flag in a global */
-    g_fUseUnicode = fUseUnicode;
-
     /* Allow multiple threads to access Xlib */
     if (XInitThreads() == 0) {
         ErrorF("winClipboardProc - XInitThreads failed.\n");
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
index 7aaa341..5248130 100644
--- a/hw/xwin/winclipboard/winclipboard.h
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -27,7 +27,7 @@
 #ifndef WINCLIPBOARD_H
 #define WINCLIPBOARD_H
 
-Bool winClipboardProc(char *szDisplay);
+Bool winClipboardProc(Bool fUseUnicode, char *szDisplay);
 
 void winFixClipboardChain(void);
 
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 3324661..8aef8fe 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -82,7 +82,7 @@ winClipboardThreadProc(void *arg)
       /* Flag that clipboard client has been launched */
       g_fClipboardStarted = TRUE;
 
-      fShutdown = winClipboardProc(szDisplay);
+      fShutdown = winClipboardProc(g_fUnicodeClipboard, szDisplay);
 
       /* Flag that clipboard client has stopped */
       g_fClipboardStarted = FALSE;
commit 126c1cfaa5b5978026d44a1f8b044d367056965b
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 18:27:56 2013 +0100

    hw/xwin: Separate libwinclipboard interface and internal header files
    
    Rename the libwinclipboard internal header from winclipboard.h to internal.h
    
    Put libwinclipboard's public interface into winclipboard.h
    
    This lets winclipboardinit.c partake of that public interface, and all X server
    headers without clashes
    
    winInitClipboard() prototype belongs in a server header
    
    v2: Remove duplicate declaration of winClipboardWindowDestroy()
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index 1a882f4..7af35e7 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -793,9 +793,6 @@ Bool
  winInitClipboard(void);
 
 void
- winFixClipboardChain(void);
-
-void
  winClipboardShutdown(void);
 #endif
 
diff --git a/hw/xwin/winclipboard/internal.h b/hw/xwin/winclipboard/internal.h
new file mode 100644
index 0000000..89f0c39
--- /dev/null
+++ b/hw/xwin/winclipboard/internal.h
@@ -0,0 +1,123 @@
+
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors:	Harold L Hunt II
+ */
+
+#ifndef WINCLIPBOARD_INTERNAL_H
+#define WINCLIPBOARD_INTERNAL_H
+
+/* Standard library headers */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef __CYGWIN__
+#include <sys/select.h>
+#else
+#include <X11/Xwinsock.h>
+#endif
+#include <fcntl.h>
+#include <setjmp.h>
+#include <pthread.h>
+
+/* X headers */
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+
+/* Windows headers */
+#include <X11/Xwindows.h>
+
+/* Clipboard module constants */
+#ifdef HAS_DEVWINDOWS
+#define WIN_MSG_QUEUE_FNAME			"/dev/windows"
+#endif
+#define WIN_JMP_OKAY				0
+#define WIN_JMP_ERROR_IO			2
+#define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
+#define WIN_XEVENTS_SUCCESS			0
+#define WIN_XEVENTS_CONVERT			2
+#define WIN_XEVENTS_NOTIFY			3
+
+#define WM_WM_REINIT                           (WM_USER + 1)
+
+/*
+ * References to external symbols
+ */
+
+extern void winDebug(const char *format, ...);
+extern void winErrorFVerb(int verb, const char *format, ...);
+
+/*
+ * winclipboardtextconv.c
+ */
+
+void
+ winClipboardDOStoUNIX(char *pszData, int iLength);
+
+void
+ winClipboardUNIXtoDOS(char **ppszData, int iLength);
+
+/*
+ * winclipboardthread.c
+ */
+
+
+/*
+ * winclipboardwndproc.c
+ */
+
+BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+
+LRESULT CALLBACK
+winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+typedef struct
+{
+  Display *pClipboardDisplay;
+  Window iClipboardWindow;
+} ClipboardWindowCreationParams;
+
+/*
+ * winclipboardxevents.c
+ */
+
+int
+winClipboardFlushXEvents(HWND hwnd,
+                         int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(void);
+
+void
+winClipboardInitMonitoredSelections(void);
+
+#endif
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index bbb3a21..36a1b4e 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -35,15 +35,18 @@
 #else
 #define HAS_WINSOCK 1
 #endif
+
 #include <sys/types.h>
 #include <signal.h>
-#include "winclipboard.h"
 #include "windisplay.h"
 #ifdef __CYGWIN__
 #include <errno.h>
 #endif
+
 #include "misc.h"
 #include <X11/extensions/Xfixes.h>
+#include "winclipboard.h"
+#include "internal.h"
 
 #define WIN_CONNECT_RETRIES			40
 #define WIN_CONNECT_DELAY			4
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
index 95b18a6..7aaa341 100644
--- a/hw/xwin/winclipboard/winclipboard.h
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -1,134 +1,36 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors:	Harold L Hunt II
- */
-
-#ifndef _WINCLIPBOARD_H_
-#define _WINCLIPBOARD_H_
-
-/* Standard library headers */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef __CYGWIN__
-#include <sys/select.h>
-#else
-#include <X11/Xwinsock.h>
-#endif
-#include <fcntl.h>
-#include <setjmp.h>
-#include <pthread.h>
-
-/* X headers */
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xlocale.h>
-
-/* Windows headers */
-#include <X11/Xwindows.h>
-
-/* Clipboard module constants */
-#ifdef HAS_DEVWINDOWS
-#define WIN_MSG_QUEUE_FNAME			"/dev/windows"
-#endif
-#define WIN_JMP_OKAY				0
-#define WIN_JMP_ERROR_IO			2
-#define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
-#define WIN_XEVENTS_SUCCESS			0
-#define WIN_XEVENTS_CONVERT			2
-#define WIN_XEVENTS_NOTIFY			3
-
-#define WM_WM_REINIT                           (WM_USER + 1)
-
-/*
- * References to external symbols
- */
-
-extern void winDebug(const char *format, ...);
-extern void winErrorFVerb(int verb, const char *format, ...);
-
-/*
- * winclipboardinit.c
- */
-
-Bool
- winInitClipboard(void);
-
-/*
- * winclipboardtextconv.c
- */
-
-void
- winClipboardDOStoUNIX(char *pszData, int iLength);
-
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
-
-/*
- * winclipboardthread.c
- */
+//
+// Copyright © Jon TURNEY 2013
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice (including the next
+// paragraph) shall be included in all copies or substantial portions of the
+// Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// File: winclipboard.h
+// Purpose: public interface to winclipboard library
+//
+
+#ifndef WINCLIPBOARD_H
+#define WINCLIPBOARD_H
 
 Bool winClipboardProc(char *szDisplay);
 
-void
-winClipboardWindowDestroy(void);
-
-/*
- * winclipboardwndproc.c
- */
-
-BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
-
-LRESULT CALLBACK
-winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-typedef struct
-{
-  Display *pClipboardDisplay;
-  Window iClipboardWindow;
-} ClipboardWindowCreationParams;
-
-/*
- * winclipboardxevents.c
- */
-
-int
-winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUnicodeSupport);
-
-
-Atom
-winClipboardGetLastOwnedSelectionAtom(void);
+void winFixClipboardChain(void);
 
-void
-winClipboardInitMonitoredSelections(void);
+void winClipboardWindowDestroy(void);
 
 #endif
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
index 459170f..769422b 100644
--- a/hw/xwin/winclipboard/wndproc.c
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -33,10 +33,13 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
+
 #include <sys/types.h>
 #include <sys/time.h>
-#include "winclipboard.h"
+
+#include "internal.h"
 #include "misc.h"
+#include "winclipboard.h"
 
 /*
  * Constants
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
index a792467..3fcf6e3 100644
--- a/hw/xwin/winclipboard/xevents.c
+++ b/hw/xwin/winclipboard/xevents.c
@@ -34,7 +34,7 @@
 #include <xwin-config.h>
 #endif
 
-#include "winclipboard.h"
+#include "internal.h"
 #include "misc.h"
 #include <X11/extensions/Xfixes.h>
 
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 25790d0..3324661 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -35,22 +35,13 @@
 #include <unistd.h>
 #include <pthread.h>
 
-#include "os.h"
+#include "win.h"
 #include "winclipboard/winclipboard.h"
 #include "windisplay.h"
 
 #define WIN_CLIPBOARD_RETRIES			40
 #define WIN_CLIPBOARD_DELAY			1
 
-extern void winSetAuthorization(void);
-
-/*
- * References to external symbols
- */
-
-extern Bool g_fClipboard;
-extern Bool g_fClipboardStarted;
-
 /*
  * Local variables
  */
diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c
index bee223d..e3adb56 100644
--- a/hw/xwin/winwndproc.c
+++ b/hw/xwin/winwndproc.c
@@ -42,6 +42,9 @@
 #include "winmsg.h"
 #include "winmonitors.h"
 #include "inputstr.h"
+#ifdef XWIN_CLIPBOARD
+#include "winclipboard/winclipboard.h"
+#endif
 
 /*
  * Global variables
commit 30c535219ef2c251d90a1a1d3d07c8a7ec936da9
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Tue Jun 18 00:32:53 2013 +0100

    hw/xwin: Return a shutdown flag from winClipboardProc() if we should stop trying
    
    Return a shutdown flag from winClipboardProc(), and use it in
    winClipboardThreadProc() to determine if we should stop.
    
    Currently this is set if the clipboard messaging window received a WM_QUIT.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
index 9ec61f8..bbb3a21 100644
--- a/hw/xwin/winclipboard/thread.c
+++ b/hw/xwin/winclipboard/thread.c
@@ -56,7 +56,6 @@
  */
 
 extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboard;
 
 /*
  * Global variables
@@ -85,10 +84,12 @@ static int
  winClipboardIOErrorHandler(Display * pDisplay);
 
 /*
- * Main thread function
+ * Create X11 and Win32 messaging windows, and run message processing loop
+ *
+ * returns TRUE if shutdown was signalled to loop, FALSE if some error occurred
  */
 
-void *
+Bool
 winClipboardProc(char *szDisplay)
 {
     Atom atomClipboard;
@@ -108,6 +109,7 @@ winClipboardProc(char *szDisplay)
     int iRetries;
     Bool fUseUnicode;
     int iSelectError;
+    Bool fShutdown = FALSE;
 
     winDebug("winClipboardProc - Hello\n");
 
@@ -349,8 +351,8 @@ winClipboardProc(char *szDisplay)
     }
 
  winClipboardProc_Exit:
-    /* disable the clipboard, which means the thread will die */
-    g_fClipboard = FALSE;
+    /* broke out of while loop on a shutdown message */
+    fShutdown = TRUE;
 
  winClipboardProc_Done:
     /* Close our Windows window */
@@ -394,7 +396,7 @@ winClipboardProc(char *szDisplay)
     /* global clipboard variable reset */
     g_hwndClipboard = NULL;
 
-    return NULL;
+    return fShutdown;
 }
 
 /*
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
index 58e35dc..95b18a6 100644
--- a/hw/xwin/winclipboard/winclipboard.h
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -96,7 +96,7 @@ void
  * winclipboardthread.c
  */
 
-void *winClipboardProc(char *szDisplay);
+Bool winClipboardProc(char *szDisplay);
 
 void
 winClipboardWindowDestroy(void);
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 2e400f6..25790d0 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -68,6 +68,8 @@ winClipboardThreadProc(void *arg)
 
   while (1)
     {
+      Bool fShutdown;
+
       ++clipboardRestarts;
 
       /* Use our generated cookie for authentication */
@@ -89,11 +91,14 @@ winClipboardThreadProc(void *arg)
       /* Flag that clipboard client has been launched */
       g_fClipboardStarted = TRUE;
 
-      winClipboardProc(szDisplay);
+      fShutdown = winClipboardProc(szDisplay);
 
       /* Flag that clipboard client has stopped */
       g_fClipboardStarted = FALSE;
 
+      if (fShutdown)
+        break;
+
       /* checking if we need to restart */
       if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
         /* terminates clipboard thread but the main server still lives */
commit 88d44597046086953032fec7e035fc036596e255
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 00:38:47 2013 +0100

    hw/xwin: Move clipboard integration code down to a subdirectory
    
    Move clipboard integration code down to a subdirectory and build as a
    convenience library
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/configure.ac b/configure.ac
index 8dc7198..93e8895 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2599,6 +2599,7 @@ hw/xnest/man/Makefile
 hw/xwin/Makefile
 hw/xwin/glx/Makefile
 hw/xwin/man/Makefile
+hw/xwin/winclipboard/Makefile
 hw/xquartz/Makefile
 hw/xquartz/GL/Makefile
 hw/xquartz/bundle/Makefile
diff --git a/hw/xwin/Makefile.am b/hw/xwin/Makefile.am
index 326ffa0..2c7fde3 100644
--- a/hw/xwin/Makefile.am
+++ b/hw/xwin/Makefile.am
@@ -3,12 +3,9 @@ bin_PROGRAMS = XWin
 if XWIN_CLIPBOARD
 SRCS_CLIPBOARD = \
 	winclipboardinit.c \
-	winclipboardtextconv.c \
-	winclipboardthread.c \
-	winclipboardwndproc.c \
-	winclipboardwrappers.c \
-	winclipboardxevents.c
+	winclipboardwrappers.c
 DEFS_CLIPBOARD = -DXWIN_CLIPBOARD
+CLIPBOARD_LIBS = $(top_builddir)/hw/xwin/winclipboard/libXWinclipboard.la
 endif
 
 if XWIN_GLX_WINDOWS
@@ -110,7 +107,6 @@ SRCS =	InitInput.c \
 	winwindow.c \
 	winwndproc.c \
 	ddraw.h \
-	winclipboard.h \
 	winconfig.h \
 	win.h \
 	winglobals.h \
@@ -162,12 +158,15 @@ XWin_DEPENDENCIES = \
 	$(MULTIWINDOWEXTWM_LIBS) \
 	$(XWIN_GLX_LIBS) \
 	$(XWIN_LIBS) \
+	$(CLIPBOARD_LIBS) \
 	$(XSERVER_LIBS)
 
+
 XWin_LDADD = \
 	$(MULTIWINDOWEXTWM_LIBS) \
 	$(XWIN_GLX_LIBS) \
 	$(XWIN_LIBS) \
+	$(CLIPBOARD_LIBS) \
 	$(XSERVER_LIBS) \
 	$(XWIN_GLX_SYS_LIBS) \
 	$(XSERVER_SYS_LIBS) \
@@ -210,5 +209,5 @@ EXTRA_DIST = \
 relink:
 	$(AM_V_at)rm -f XWin$(EXEEXT) && $(MAKE) XWin$(EXEEXT)
 
-SUBDIRS = man $(GLX_DIR) .
-DIST_SUBDIRS = man glx .
+SUBDIRS = man $(GLX_DIR) winclipboard .
+DIST_SUBDIRS = man glx winclipboard .
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
deleted file mode 100644
index 41c0a53..0000000
--- a/hw/xwin/winclipboard.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef _WINCLIPBOARD_H_
-#define _WINCLIPBOARD_H_
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors:	Harold L Hunt II
- */
-
-/* Standard library headers */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef __CYGWIN__
-#include <sys/select.h>
-#else
-#include <X11/Xwinsock.h>
-#endif
-#include <fcntl.h>
-#include <setjmp.h>
-#include <pthread.h>
-
-/* X headers */
-#include <X11/X.h>
-#include <X11/Xatom.h>
-#include <X11/Xproto.h>
-#include <X11/Xutil.h>
-#include <X11/Xlocale.h>
-
-/* Windows headers */
-#include <X11/Xwindows.h>
-
-/* Clipboard module constants */
-#ifdef HAS_DEVWINDOWS
-#define WIN_MSG_QUEUE_FNAME			"/dev/windows"
-#endif
-#define WIN_JMP_OKAY				0
-#define WIN_JMP_ERROR_IO			2
-#define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
-#define WIN_XEVENTS_SUCCESS			0
-#define WIN_XEVENTS_CONVERT			2
-#define WIN_XEVENTS_NOTIFY			3
-
-#define WM_WM_REINIT                           (WM_USER + 1)
-
-/*
- * References to external symbols
- */
-
-extern void winDebug(const char *format, ...);
-extern void winErrorFVerb(int verb, const char *format, ...);
-
-/*
- * winclipboardinit.c
- */
-
-Bool
- winInitClipboard(void);
-
-/*
- * winclipboardtextconv.c
- */
-
-void
- winClipboardDOStoUNIX(char *pszData, int iLength);
-
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
-
-/*
- * winclipboardthread.c
- */
-
-void *winClipboardProc(char *szDisplay);
-
-void
-winClipboardWindowDestroy(void);
-
-/*
- * winclipboardwndproc.c
- */
-
-BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
-
-LRESULT CALLBACK
-winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-typedef struct
-{
-  Display *pClipboardDisplay;
-  Window iClipboardWindow;
-} ClipboardWindowCreationParams;
-
-/*
- * winclipboardxevents.c
- */
-
-int
-winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUnicodeSupport);
-
-
-Atom
-winClipboardGetLastOwnedSelectionAtom(void);
-
-void
-winClipboardInitMonitoredSelections(void);
-
-#endif
diff --git a/hw/xwin/winclipboard/Makefile.am b/hw/xwin/winclipboard/Makefile.am
new file mode 100644
index 0000000..91cc116
--- /dev/null
+++ b/hw/xwin/winclipboard/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LTLIBRARIES = libXWinclipboard.la
+
+libXWinclipboard_la_SOURCES = \
+	winclipboard.h \
+	textconv.c \
+	thread.c \
+	wndproc.c \
+	xevents.c
+
+libXWinclipboard_la_CFLAGS = -DHAVE_XWIN_CONFIG_H \
+			     $(DIX_CFLAGS) \
+			     $(XWINMODULES_CFLAGS) \
+		             -I$(top_srcdir) -I$(top_srcdir)/miext/rootless -I$(srcdir)/..
+
+libXWinclipboard_la_LDFLAGS = -static -no-undefined
diff --git a/hw/xwin/winclipboard/textconv.c b/hw/xwin/winclipboard/textconv.c
new file mode 100644
index 0000000..fd405a0
--- /dev/null
+++ b/hw/xwin/winclipboard/textconv.c
@@ -0,0 +1,147 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors:	Harold L Hunt II
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include "win.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+ winClipboardDOStoUNIX(char *pszSrc, int iLength);
+void
+ winClipboardUNIXtoDOS(char **ppszData, int iLength);
+
+/*
+ * Convert \r\n to \n
+ *
+ * NOTE: This was heavily inspired by, Cygwin's
+ * winsup/cygwin/fhandler.cc/fhandler_base::read ()
+ */
+
+void
+winClipboardDOStoUNIX(char *pszSrc, int iLength)
+{
+    char *pszDest = pszSrc;
+    char *pszEnd = pszSrc + iLength;
+
+    /* Loop until the last character */
+    while (pszSrc < pszEnd) {
+        /* Copy the current source character to current destination character */
+        *pszDest = *pszSrc;
+
+        /* Advance to the next source character */
+        pszSrc++;
+
+        /* Don't advance the destination character if we need to drop an \r */
+        if (*pszDest != '\r' || *pszSrc != '\n')
+            pszDest++;
+    }
+
+    /* Move the terminating null */
+    *pszDest = '\0';
+}
+
+/*
+ * Convert \n to \r\n
+ */
+
+void
+winClipboardUNIXtoDOS(char **ppszData, int iLength)
+{
+    int iNewlineCount = 0;
+    char *pszSrc = *ppszData;
+    char *pszEnd = pszSrc + iLength;
+    char *pszDest = NULL, *pszDestBegin = NULL;
+
+    winDebug("UNIXtoDOS () - Original data:'%s'\n", *ppszData);
+
+    /* Count \n characters without leading \r */
+    while (pszSrc < pszEnd) {
+        /* Skip ahead two character if found set of \r\n */
+        if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
+            pszSrc += 2;
+            continue;
+        }
+
+        /* Increment the count if found naked \n */
+        if (*pszSrc == '\n') {
+            iNewlineCount++;
+        }
+
+        pszSrc++;
+    }
+
+    /* Return if no naked \n's */
+    if (iNewlineCount == 0)
+        return;
+
+    /* Allocate a new string */
+    pszDestBegin = pszDest = malloc(iLength + iNewlineCount + 1);
+
+    /* Set source pointer to beginning of data string */
+    pszSrc = *ppszData;
+
+    /* Loop through all characters in source string */
+    while (pszSrc < pszEnd) {
+        /* Copy line endings that are already valid */
+        if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
+            *pszDest = *pszSrc;
+            *(pszDest + 1) = *(pszSrc + 1);
+            pszDest += 2;
+            pszSrc += 2;
+            continue;
+        }
+
+        /* Add \r to naked \n's */
+        if (*pszSrc == '\n') {
+            *pszDest = '\r';
+            *(pszDest + 1) = *pszSrc;
+            pszDest += 2;
+            pszSrc += 1;
+            continue;
+        }
+
+        /* Copy normal characters */
+        *pszDest = *pszSrc;
+        pszSrc++;
+        pszDest++;
+    }
+
+    /* Put terminating null at end of new string */
+    *pszDest = '\0';
+
+    /* Swap string pointers */
+    free(*ppszData);
+    *ppszData = pszDestBegin;
+
+    winDebug("UNIXtoDOS () - Final string:'%s'\n", pszDestBegin);
+}
diff --git a/hw/xwin/winclipboard/thread.c b/hw/xwin/winclipboard/thread.c
new file mode 100644
index 0000000..9ec61f8
--- /dev/null
+++ b/hw/xwin/winclipboard/thread.c
@@ -0,0 +1,504 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors:	Harold L Hunt II
+ *              Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#else
+#define HAS_WINSOCK 1
+#endif
+#include <sys/types.h>
+#include <signal.h>
+#include "winclipboard.h"
+#include "windisplay.h"
+#ifdef __CYGWIN__
+#include <errno.h>
+#endif
+#include "misc.h"
+#include <X11/extensions/Xfixes.h>
+
+#define WIN_CONNECT_RETRIES			40
+#define WIN_CONNECT_DELAY			4
+
+#define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
+#define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
+
+/*
+ * References to external symbols
+ */
+
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboard;
+
+/*
+ * Global variables
+ */
+
+static HWND g_hwndClipboard = NULL;
+static jmp_buf g_jmpEntry;
+static XIOErrorHandler g_winClipboardOldIOErrorHandler;
+static pthread_t g_winClipboardProcThread;
+
+Bool g_fUseUnicode = FALSE;
+int xfixes_event_base;
+int xfixes_error_base;
+
+/*
+ * Local function prototypes
+ */
+
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow);
+
+static int
+ winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
+
+static int
+ winClipboardIOErrorHandler(Display * pDisplay);
+
+/*
+ * Main thread function
+ */
+
+void *
+winClipboardProc(char *szDisplay)
+{
+    Atom atomClipboard;
+    int iReturn;
+    HWND hwnd = NULL;
+    int iConnectionNumber = 0;
+
+#ifdef HAS_DEVWINDOWS
+    int fdMessageQueue = 0;
+#else
+    struct timeval tvTimeout;
+#endif
+    fd_set fdsRead;
+    int iMaxDescriptor;
+    Display *pDisplay = NULL;
+    Window iWindow = None;
+    int iRetries;
+    Bool fUseUnicode;
+    int iSelectError;
+
+    winDebug("winClipboardProc - Hello\n");
+
+    /* Do we use Unicode clipboard? */
+    fUseUnicode = g_fUnicodeClipboard;
+
+    /* Save the Unicode support flag in a global */
+    g_fUseUnicode = fUseUnicode;
+
+    /* Allow multiple threads to access Xlib */
+    if (XInitThreads() == 0) {
+        ErrorF("winClipboardProc - XInitThreads failed.\n");
+        goto winClipboardProc_Exit;
+    }
+
+    /* See if X supports the current locale */
+    if (XSupportsLocale() == False) {
+        ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
+    }
+
+    /* Set error handler */
+    XSetErrorHandler(winClipboardErrorHandler);
+    g_winClipboardProcThread = pthread_self();
+    g_winClipboardOldIOErrorHandler =
+        XSetIOErrorHandler(winClipboardIOErrorHandler);
+
+    /* Set jump point for Error exits */
+    iReturn = setjmp(g_jmpEntry);
+
+    /* Check if we should continue operations */
+    if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
+        /* setjmp returned an unknown value, exit */
+        ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
+        goto winClipboardProc_Exit;
+    }
+    else if (iReturn == WIN_JMP_ERROR_IO) {
+        /* TODO: Cleanup the Win32 window and free any allocated memory */
+        ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
+        goto winClipboardProc_Done;
+    }
+
+    /* Initialize retry count */
+    iRetries = 0;
+
+
+    /* Open the X display */
+    do {
+        pDisplay = XOpenDisplay(szDisplay);
+        if (pDisplay == NULL) {
+            ErrorF("winClipboardProc - Could not open display, "
+                   "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
+            ++iRetries;
+            sleep(WIN_CONNECT_DELAY);
+            continue;
+        }
+        else
+            break;
+    }
+    while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
+
+    /* Make sure that the display opened */
+    if (pDisplay == NULL) {
+        ErrorF("winClipboardProc - Failed opening the display, giving up\n");
+        goto winClipboardProc_Done;
+    }
+
+    ErrorF("winClipboardProc - XOpenDisplay () returned and "
+           "successfully opened the display.\n");
+
+    /* Get our connection number */
+    iConnectionNumber = ConnectionNumber(pDisplay);
+
+#ifdef HAS_DEVWINDOWS
+    /* Open a file descriptor for the windows message queue */
+    fdMessageQueue = open(WIN_MSG_QUEUE_FNAME, O_RDONLY);
+    if (fdMessageQueue == -1) {
+        ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
+        goto winClipboardProc_Done;
+    }
+
+    /* Find max of our file descriptors */
+    iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
+#else
+    iMaxDescriptor = iConnectionNumber + 1;
+#endif
+
+    if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
+      ErrorF ("winClipboardProc - XFixes extension not present\n");
+
+    /* Create atom */
+    atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+
+    /* Create a messaging window */
+    iWindow = XCreateSimpleWindow(pDisplay,
+                                  DefaultRootWindow(pDisplay),
+                                  1, 1,
+                                  500, 500,
+                                  0,
+                                  BlackPixel(pDisplay, 0),
+                                  BlackPixel(pDisplay, 0));
+    if (iWindow == 0) {
+        ErrorF("winClipboardProc - Could not create an X window.\n");
+        goto winClipboardProc_Done;
+    }
+
+    XStoreName(pDisplay, iWindow, "xwinclip");
+
+    /* Select event types to watch */
+    if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow)
+        ErrorF("winClipboardProc - XSelectInput generated BadWindow "
+               "on messaging window\n");
+
+    XFixesSelectSelectionInput (pDisplay,
+                                iWindow,
+                                XA_PRIMARY,
+                                XFixesSetSelectionOwnerNotifyMask |
+                                XFixesSelectionWindowDestroyNotifyMask |
+                                XFixesSelectionClientCloseNotifyMask);
+
+    XFixesSelectSelectionInput (pDisplay,
+                                iWindow,
+                                XInternAtom (pDisplay, "CLIPBOARD", False),
+                                XFixesSetSelectionOwnerNotifyMask |
+                                XFixesSelectionWindowDestroyNotifyMask |
+                                XFixesSelectionClientCloseNotifyMask);
+
+
+    /* Initialize monitored selection state */
+    winClipboardInitMonitoredSelections();
+    /* Create Windows messaging window */
+    hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow);
+
+    /* Save copy of HWND */
+    g_hwndClipboard = hwnd;
+
+    /* Assert ownership of selections if Win32 clipboard is owned */
+    if (NULL != GetClipboardOwner()) {
+        /* PRIMARY */
+        iReturn = XSetSelectionOwner(pDisplay, XA_PRIMARY,
+                                     iWindow, CurrentTime);
+        if (iReturn == BadAtom || iReturn == BadWindow ||
+            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
+            ErrorF("winClipboardProc - Could not set PRIMARY owner\n");
+            goto winClipboardProc_Done;
+        }
+
+        /* CLIPBOARD */
+        iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
+                                     iWindow, CurrentTime);
+        if (iReturn == BadAtom || iReturn == BadWindow ||
+            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+            ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
+            goto winClipboardProc_Done;
+        }
+    }
+
+    /* Pre-flush X events */
+    /*
+     * NOTE: Apparently you'll freeze if you don't do this,
+     *       because there may be events in local data structures
+     *       already.
+     */
+    winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+
+    /* Pre-flush Windows messages */
+    if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+        ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
+    }
+
+    /* Loop for X events */
+    while (1) {
+        /* Setup the file descriptor set */
+        /*
+         * NOTE: You have to do this before every call to select
+         *       because select modifies the mask to indicate
+         *       which descriptors are ready.
+         */
+        FD_ZERO(&fdsRead);
+        FD_SET(iConnectionNumber, &fdsRead);
+#ifdef HAS_DEVWINDOWS
+        FD_SET(fdMessageQueue, &fdsRead);
+#else
+        tvTimeout.tv_sec = 0;
+        tvTimeout.tv_usec = 100;
+#endif
+
+        /* Wait for a Windows event or an X event */
+        iReturn = select(iMaxDescriptor,        /* Highest fds number */
+                         &fdsRead,      /* Read mask */
+                         NULL,  /* No write mask */
+                         NULL,  /* No exception mask */
+#ifdef HAS_DEVWINDOWS
+                         NULL   /* No timeout */
+#else
+                         &tvTimeout     /* Set timeout */
+#endif
+            );
+
+#ifndef HAS_WINSOCK
+        iSelectError = errno;
+#else
+        iSelectError = WSAGetLastError();
+#endif
+
+        if (iReturn < 0) {
+#ifndef HAS_WINSOCK
+            if (iSelectError == EINTR)
+#else
+            if (iSelectError == WSAEINTR)
+#endif
+                continue;
+
+            ErrorF("winClipboardProc - Call to select () failed: %d.  "
+                   "Bailing.\n", iReturn);
+            break;
+        }
+
+        /* Branch on which descriptor became active */
+        if (FD_ISSET(iConnectionNumber, &fdsRead)) {
+            /* Process X events */
+            winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
+        }
+
+#ifdef HAS_DEVWINDOWS
+        /* Check for Windows event ready */
+        if (FD_ISSET(fdMessageQueue, &fdsRead))
+#else
+        if (1)
+#endif
+        {
+            /* Process Windows messages */
+            if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+                ErrorF("winClipboardProc - "
+                       "winClipboardFlushWindowsMessageQueue trapped "
+                       "WM_QUIT message, exiting main loop.\n");
+                break;
+            }
+        }
+    }
+
+ winClipboardProc_Exit:
+    /* disable the clipboard, which means the thread will die */
+    g_fClipboard = FALSE;
+
+ winClipboardProc_Done:
+    /* Close our Windows window */
+    if (g_hwndClipboard) {
+        winClipboardWindowDestroy();
+    }
+
+    /* Close our X window */
+    if (pDisplay && iWindow) {
+        iReturn = XDestroyWindow(pDisplay, iWindow);
+        if (iReturn == BadWindow)
+            ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n");
+        else
+            ErrorF("winClipboardProc - XDestroyWindow succeeded.\n");
+    }
+
+#ifdef HAS_DEVWINDOWS
+    /* Close our Win32 message handle */
+    if (fdMessageQueue)
+        close(fdMessageQueue);
+#endif
+
+#if 0
+    /*
+     * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26.  The
+     * XSync and XSelectInput calls did not help.
+     */
+
+    /* Discard any remaining events */
+    XSync(pDisplay, TRUE);
+
+    /* Select event types to watch */
+    XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
+
+    /* Close our X display */
+    if (pDisplay) {
+        XCloseDisplay(pDisplay);
+    }
+#endif
+
+    /* global clipboard variable reset */
+    g_hwndClipboard = NULL;
+
+    return NULL;
+}
+
+/*
+ * Create the Windows window that we use to receive Windows messages
+ */
+
+static HWND
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow)
+{
+    WNDCLASSEX wc;
+    ClipboardWindowCreationParams cwcp;
+    HWND hwnd;
+
+    /* Setup our window class */
+    wc.cbSize = sizeof(WNDCLASSEX);
+    wc.style = CS_HREDRAW | CS_VREDRAW;
+    wc.lpfnWndProc = winClipboardWindowProc;
+    wc.cbClsExtra = 0;
+    wc.cbWndExtra = 0;
+    wc.hInstance = GetModuleHandle(NULL);
+    wc.hIcon = 0;
+    wc.hCursor = 0;
+    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+    wc.lpszMenuName = NULL;
+    wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
+    wc.hIconSm = 0;
+    RegisterClassEx(&wc);
+
+    /* Information to be passed to WM_CREATE */
+    cwcp.pClipboardDisplay = pDisplay;
+    cwcp.iClipboardWindow = iWindow;
+
+    /* Create the window */
+    hwnd = CreateWindowExA(0,   /* Extended styles */
+                           WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
+                           WIN_CLIPBOARD_WINDOW_TITLE,  /* Window name */
+                           WS_OVERLAPPED,       /* Not visible anyway */
+                           CW_USEDEFAULT,       /* Horizontal position */
+                           CW_USEDEFAULT,       /* Vertical position */
+                           CW_USEDEFAULT,       /* Right edge */
+                           CW_USEDEFAULT,       /* Bottom edge */
+                           (HWND) NULL, /* No parent or owner window */
+                           (HMENU) NULL,        /* No menu */
+                           GetModuleHandle(NULL),       /* Instance handle */
+                           &cwcp);       /* Creation data */
+    assert(hwnd != NULL);
+
+    /* I'm not sure, but we may need to call this to start message processing */
+    ShowWindow(hwnd, SW_HIDE);
+
+    /* Similarly, we may need a call to this even though we don't paint */
+    UpdateWindow(hwnd);
+
+    return hwnd;
+}
+
+/*
+ * winClipboardErrorHandler - Our application specific error handler
+ */
+
+static int
+winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
+{
+    char pszErrorMsg[100];
+
+    XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
+    ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n"
+           "\tSerial: %lu, Request Code: %d, Minor Code: %d\n",
+           pszErrorMsg, pErr->serial, pErr->request_code, pErr->minor_code);
+    return 0;
+}
+
+/*
+ * winClipboardIOErrorHandler - Our application specific IO error handler
+ */
+
+static int
+winClipboardIOErrorHandler(Display * pDisplay)
+{
+    ErrorF("winClipboardIOErrorHandler!\n");
+
+    if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
+        /* Restart at the main entry point */
+        longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
+    }
+
+    if (g_winClipboardOldIOErrorHandler)
+        g_winClipboardOldIOErrorHandler(pDisplay);
+
+    return 0;
+}
+
+void
+winClipboardWindowDestroy(void)
+{
+  if (g_hwndClipboard) {
+    SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
+  }
+}
+
+void
+winFixClipboardChain(void)
+{
+  if (g_hwndClipboard) {
+    PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
+  }
+}
diff --git a/hw/xwin/winclipboard/winclipboard.h b/hw/xwin/winclipboard/winclipboard.h
new file mode 100644
index 0000000..58e35dc
--- /dev/null
+++ b/hw/xwin/winclipboard/winclipboard.h
@@ -0,0 +1,134 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of Harold L Hunt II
+ *shall not be used in advertising or otherwise to promote the sale, use
+ *or other dealings in this Software without prior written authorization
+ *from Harold L Hunt II.
+ *
+ * Authors:	Harold L Hunt II
+ */
+
+#ifndef _WINCLIPBOARD_H_
+#define _WINCLIPBOARD_H_
+
+/* Standard library headers */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef __CYGWIN__
+#include <sys/select.h>
+#else
+#include <X11/Xwinsock.h>
+#endif
+#include <fcntl.h>
+#include <setjmp.h>
+#include <pthread.h>
+
+/* X headers */
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xproto.h>
+#include <X11/Xutil.h>
+#include <X11/Xlocale.h>
+
+/* Windows headers */
+#include <X11/Xwindows.h>
+
+/* Clipboard module constants */
+#ifdef HAS_DEVWINDOWS
+#define WIN_MSG_QUEUE_FNAME			"/dev/windows"
+#endif
+#define WIN_JMP_OKAY				0
+#define WIN_JMP_ERROR_IO			2
+#define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
+#define WIN_XEVENTS_SUCCESS			0
+#define WIN_XEVENTS_CONVERT			2
+#define WIN_XEVENTS_NOTIFY			3
+
+#define WM_WM_REINIT                           (WM_USER + 1)
+
+/*
+ * References to external symbols
+ */
+
+extern void winDebug(const char *format, ...);
+extern void winErrorFVerb(int verb, const char *format, ...);
+
+/*
+ * winclipboardinit.c
+ */
+
+Bool
+ winInitClipboard(void);
+
+/*
+ * winclipboardtextconv.c
+ */
+
+void
+ winClipboardDOStoUNIX(char *pszData, int iLength);
+
+void
+ winClipboardUNIXtoDOS(char **ppszData, int iLength);
+
+/*
+ * winclipboardthread.c
+ */
+
+void *winClipboardProc(char *szDisplay);
+
+void
+winClipboardWindowDestroy(void);
+
+/*
+ * winclipboardwndproc.c
+ */
+
+BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
+
+LRESULT CALLBACK
+winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+typedef struct
+{
+  Display *pClipboardDisplay;
+  Window iClipboardWindow;
+} ClipboardWindowCreationParams;
+
+/*
+ * winclipboardxevents.c
+ */
+
+int
+winClipboardFlushXEvents(HWND hwnd,
+                         int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(void);
+
+void
+winClipboardInitMonitoredSelections(void);
+
+#endif
diff --git a/hw/xwin/winclipboard/wndproc.c b/hw/xwin/winclipboard/wndproc.c
new file mode 100644
index 0000000..459170f
--- /dev/null
+++ b/hw/xwin/winclipboard/wndproc.c
@@ -0,0 +1,524 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors:	Harold L Hunt II
+ *              Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+#include <sys/types.h>
+#include <sys/time.h>
+#include "winclipboard.h"
+#include "misc.h"
+
+/*
+ * Constants
+ */
+
+#define WIN_POLL_TIMEOUT	1
+
+
+/*
+ * Process X events up to specified timeout
+ */
+
+static int
+winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
+                         Bool fUseUnicode, int iTimeoutSec)
+{
+    int iConnNumber;
+    struct timeval tv;
+    int iReturn;
+    DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000;
+
+    winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n",
+             iTimeoutSec);
+
+    /* Get our connection number */
+    iConnNumber = ConnectionNumber(pDisplay);
+
+    /* Loop for X events */
+    while (1) {
+        fd_set fdsRead;
+        long remainingTime;
+
+        /* We need to ensure that all pending events are processed */
+        XSync(pDisplay, FALSE);
+
+        /* Setup the file descriptor set */
+        FD_ZERO(&fdsRead);
+        FD_SET(iConnNumber, &fdsRead);
+
+        /* Adjust timeout */
+        remainingTime = dwStopTime - GetTickCount();
+        tv.tv_sec = remainingTime / 1000;
+        tv.tv_usec = (remainingTime % 1000) * 1000;
+        winDebug("winProcessXEventsTimeout () - %d milliseconds left\n",
+                 remainingTime);
+
+        /* Break out if no time left */
+        if (remainingTime <= 0)
+            return WIN_XEVENTS_SUCCESS;
+
+        /* Wait for an X event */
+        iReturn = select(iConnNumber + 1,       /* Highest fds number */
+                         &fdsRead,      /* Read mask */
+                         NULL,  /* No write mask */
+                         NULL,  /* No exception mask */
+                         &tv);  /* Timeout */
+        if (iReturn < 0) {
+            ErrorF("winProcessXEventsTimeout - Call to select () failed: %d.  "
+                   "Bailing.\n", iReturn);
+            break;
+        }
+
+        /* Branch on which descriptor became active */
+        if (FD_ISSET(iConnNumber, &fdsRead)) {
+            /* Process X events */
+            /* Exit when we see that server is shutting down */
+            iReturn = winClipboardFlushXEvents(hwnd,
+                                               iWindow, pDisplay, fUseUnicode);
+
+            winDebug
+                ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
+                 iReturn);
+
+            if (WIN_XEVENTS_NOTIFY == iReturn) {
+                /* Bail out if notify processed */
+                return iReturn;
+            }
+        }
+        else {
+            winDebug("winProcessXEventsTimeout - Spurious wake\n");
+        }
+    }
+
+    return WIN_XEVENTS_SUCCESS;
+}
+
+/*
+ * Process a given Windows message
+ */
+
+LRESULT CALLBACK
+winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    static HWND s_hwndNextViewer;
+    static Bool s_fCBCInitialized;
+    static Display *pDisplay;
+    static Window iWindow;
+
+    /* Branch on message type */
+    switch (message) {
+    case WM_DESTROY:
+    {
+        winDebug("winClipboardWindowProc - WM_DESTROY\n");
+
+        /* Remove ourselves from the clipboard chain */
+        ChangeClipboardChain(hwnd, s_hwndNextViewer);
+
+        s_hwndNextViewer = NULL;
+
+        PostQuitMessage(0);
+    }
+        return 0;
+
+    case WM_CREATE:
+    {
+        HWND first, next;
+        DWORD error_code = 0;
+        ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
+
+        winDebug("winClipboardWindowProc - WM_CREATE\n");
+
+        pDisplay = cwcp->pClipboardDisplay;
+        iWindow = cwcp->iClipboardWindow;
+
+        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
+        if (first == hwnd)
+            return 0;           /* Make sure it's not us! */
+        /* Add ourselves to the clipboard viewer chain */
+        next = SetClipboardViewer(hwnd);
+        error_code = GetLastError();
+        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
+            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
+        else
+            s_fCBCInitialized = FALSE;
+    }
+        return 0;
+
+    case WM_CHANGECBCHAIN:
+    {
+        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
+                 "lParam(%x) s_hwndNextViewer(%x)\n",
+                 wParam, lParam, s_hwndNextViewer);
+
+        if ((HWND) wParam == s_hwndNextViewer) {
+            s_hwndNextViewer = (HWND) lParam;
+            if (s_hwndNextViewer == hwnd) {
+                s_hwndNextViewer = NULL;
+                winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
+                              "attempted to set next window to ourselves.");
+            }
+        }
+        else if (s_hwndNextViewer)
+            SendMessage(s_hwndNextViewer, message, wParam, lParam);
+
+    }
+        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
+        return 0;
+
+    case WM_WM_REINIT:
+    {
+        /* Ensure that we're in the clipboard chain.  Some apps,
+         * WinXP's remote desktop for one, don't play nice with the
+         * chain.  This message is called whenever we receive a
+         * WM_ACTIVATEAPP message to ensure that we continue to
+         * receive clipboard messages.
+         *
+         * It might be possible to detect if we're still in the chain
+         * by calling SendMessage (GetClipboardViewer(),
+         * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
+         * WM_DRAWCLIPBOARD message.  That, however, might be more
+         * expensive than just putting ourselves back into the chain.
+         */
+
+        HWND first, next;
+        DWORD error_code = 0;
+
+        winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
+
+        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
+        if (first == hwnd)
+            return 0;           /* Make sure it's not us! */
+        winDebug("  WM_WM_REINIT: Replacing us(%x) with %x at head "
+                 "of chain\n", hwnd, s_hwndNextViewer);
+        s_fCBCInitialized = FALSE;
+        ChangeClipboardChain(hwnd, s_hwndNextViewer);
+        s_hwndNextViewer = NULL;
+        s_fCBCInitialized = FALSE;
+        winDebug("  WM_WM_REINIT: Putting us back at head of chain.\n");
+        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
+        if (first == hwnd)
+            return 0;           /* Make sure it's not us! */
+        next = SetClipboardViewer(hwnd);
+        error_code = GetLastError();
+        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
+            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
+        else
+            s_fCBCInitialized = FALSE;
+    }
+        winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
+        return 0;
+
+    case WM_DRAWCLIPBOARD:
+    {
+        static Atom atomClipboard;
+        static int generation;
+        static Bool s_fProcessingDrawClipboard = FALSE;
+        int iReturn;
+
+        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
+
+        if (generation != serverGeneration) {
+            generation = serverGeneration;
+            atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+        }
+
+        /*
+         * We've occasionally seen a loop in the clipboard chain.
+         * Try and fix it on the first hint of recursion.
+         */
+        if (!s_fProcessingDrawClipboard) {
+            s_fProcessingDrawClipboard = TRUE;
+        }
+        else {
+            /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
+            s_fCBCInitialized = FALSE;
+            ChangeClipboardChain(hwnd, s_hwndNextViewer);
+            winFixClipboardChain();
+            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                          "Nested calls detected.  Re-initing.\n");
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+            s_fProcessingDrawClipboard = FALSE;
+            return 0;
+        }
+
+        /* Bail on first message */
+        if (!s_fCBCInitialized) {
+            s_fCBCInitialized = TRUE;
+            s_fProcessingDrawClipboard = FALSE;
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+            return 0;
+        }
+
+        /*
+         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
+         * because some applications deal with the clipboard in a manner
+         * that causes the clipboard owner to be NULL when they are in
+         * fact taking ownership.  One example of this is the Win32
+         * native compile of emacs.
+         */
+
+        /* Bail when we still own the clipboard */
+        if (hwnd == GetClipboardOwner()) {
+
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                     "We own the clipboard, returning.\n");
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+            s_fProcessingDrawClipboard = FALSE;
+            if (s_hwndNextViewer)
+                SendMessage(s_hwndNextViewer, message, wParam, lParam);
+            return 0;
+        }
+
+        /*
+         * Do not take ownership of the X11 selections when something
+         * other than CF_TEXT or CF_UNICODETEXT has been copied
+         * into the Win32 clipboard.
+         */
+        if (!IsClipboardFormatAvailable(CF_TEXT)
+            && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                     "Clipboard does not contain CF_TEXT nor "
+                     "CF_UNICODETEXT.\n");
+
+            /*
+             * We need to make sure that the X Server has processed
+             * previous XSetSelectionOwner messages.
+             */
+            XSync(pDisplay, FALSE);
+
+            winDebug("winClipboardWindowProc - XSync done.\n");
+
+            /* Release PRIMARY selection if owned */
+            iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
+            if (iReturn == iWindow) {
+                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                         "PRIMARY selection is owned by us.\n");
+                XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
+            }
+            else if (BadWindow == iReturn || BadAtom == iReturn)
+                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                              "XGetSelection failed for PRIMARY: %d\n",
+                              iReturn);
+
+            /* Release CLIPBOARD selection if owned */
+            iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
+            if (iReturn == iWindow) {
+                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                         "CLIPBOARD selection is owned by us.\n");
+                XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
+            }
+            else if (BadWindow == iReturn || BadAtom == iReturn)
+                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                              "XGetSelection failed for CLIPBOARD: %d\n",
+                              iReturn);
+
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+            s_fProcessingDrawClipboard = FALSE;
+            if (s_hwndNextViewer)
+                SendMessage(s_hwndNextViewer, message, wParam, lParam);
+            return 0;
+        }
+
+        /* Reassert ownership of PRIMARY */
+        iReturn = XSetSelectionOwner(pDisplay,
+                                     XA_PRIMARY, iWindow, CurrentTime);
+        if (iReturn == BadAtom || iReturn == BadWindow ||
+            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
+            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                          "Could not reassert ownership of PRIMARY\n");
+        }
+        else {
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                     "Reasserted ownership of PRIMARY\n");
+        }
+
+        /* Reassert ownership of the CLIPBOARD */
+        iReturn = XSetSelectionOwner(pDisplay,
+                                     atomClipboard, iWindow, CurrentTime);
+
+        if (iReturn == BadAtom || iReturn == BadWindow ||
+            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
+            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                          "Could not reassert ownership of CLIPBOARD\n");
+        }
+        else {
+            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
+                     "Reasserted ownership of CLIPBOARD\n");
+        }
+
+        /* Flush the pending SetSelectionOwner event now */
+        XFlush(pDisplay);
+
+        s_fProcessingDrawClipboard = FALSE;
+    }
+        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
+        /* Pass the message on the next window in the clipboard viewer chain */
+        if (s_hwndNextViewer)
+            SendMessage(s_hwndNextViewer, message, wParam, lParam);
+        return 0;
+
+    case WM_DESTROYCLIPBOARD:
+        /*
+         * NOTE: Intentionally do nothing.
+         * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
+         * above.  We only process this message to conform to the specs
+         * for delayed clipboard rendering in Win32.  You might think
+         * that we need to release ownership of the X11 selections, but
+         * we do not, because a WM_DRAWCLIPBOARD message will closely
+         * follow this message and reassert ownership of the X11
+         * selections, handling the issue for us.
+         */
+        winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
+        return 0;
+
+    case WM_RENDERFORMAT:
+    case WM_RENDERALLFORMATS:
+    {
+        int iReturn;
+        Bool fConvertToUnicode;
+
+        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
+
+        /* Flag whether to convert to Unicode or not */
+        if (message == WM_RENDERALLFORMATS)
+            fConvertToUnicode = FALSE;
+        else
+            fConvertToUnicode = (CF_UNICODETEXT == wParam);
+
+        /* Request the selection contents */
+        iReturn = XConvertSelection(pDisplay,
+                                    winClipboardGetLastOwnedSelectionAtom(),
+                                    XInternAtom(pDisplay,
+                                                "COMPOUND_TEXT", False),
+                                    XInternAtom(pDisplay,
+                                                "CYGX_CUT_BUFFER", False),
+                                    iWindow, CurrentTime);
+        if (iReturn == BadAtom || iReturn == BadWindow) {
+            winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
+                          "XConvertSelection () failed\n");
+            break;
+        }
+
+        /* Special handling for WM_RENDERALLFORMATS */
+        if (message == WM_RENDERALLFORMATS) {
+            /* We must open and empty the clipboard */
+
+            /* Close clipboard if we have it open already */
+            if (GetOpenClipboardWindow() == hwnd) {
+                CloseClipboard();
+            }
+
+            if (!OpenClipboard(hwnd)) {
+                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
+                              "OpenClipboard () failed: %08x\n",
+                              GetLastError());
+                break;
+            }
+
+            if (!EmptyClipboard()) {
+                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
+                              "EmptyClipboard () failed: %08x\n",
+                              GetLastError());
+                break;
+            }
+        }
+
+        /* Process the SelectionNotify event */
+        iReturn = winProcessXEventsTimeout(hwnd,
+                                           iWindow,
+                                           pDisplay,
+                                           fConvertToUnicode, WIN_POLL_TIMEOUT);
+
+        /*
+         * The last call to winProcessXEventsTimeout
+         * from above had better have seen a notify event, or else we
+         * are dealing with a buggy or old X11 app.  In these cases we
+         * have to paste some fake data to the Win32 clipboard to
+         * satisfy the requirement that we write something to it.
+         */
+        if (WIN_XEVENTS_NOTIFY != iReturn) {
+            /* Paste no data, to satisfy required call to SetClipboardData */
+            SetClipboardData(CF_UNICODETEXT, NULL);
+            SetClipboardData(CF_TEXT, NULL);
+
+            ErrorF
+                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n");
+        }
+
+        /* Special handling for WM_RENDERALLFORMATS */
+        if (message == WM_RENDERALLFORMATS) {
+            /* We must close the clipboard */
+
+            if (!CloseClipboard()) {
+                winErrorFVerb(1,
+                              "winClipboardWindowProc - WM_RENDERALLFORMATS - "
+                              "CloseClipboard () failed: %08x\n",
+                              GetLastError());
+                break;
+            }
+        }
+
+        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
+        return 0;
+    }
+    }
+
+    /* Let Windows perform default processing for unhandled messages */
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+/*
+ * Process any pending Windows messages
+ */
+
+BOOL
+winClipboardFlushWindowsMessageQueue(HWND hwnd)
+{
+    MSG msg;
+
+    /* Flush the messaging window queue */
+    /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
+     * as this will filter out many non-window-specific messages that
+     * are sent to our thread, such as WM_QUIT.
+     */
+    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+        /* Dispatch the message if not WM_QUIT */
+        if (msg.message == WM_QUIT)
+            return FALSE;
+        else
+            DispatchMessage(&msg);
+    }
+
+    return TRUE;
+}
diff --git a/hw/xwin/winclipboard/xevents.c b/hw/xwin/winclipboard/xevents.c
new file mode 100644
index 0000000..a792467
--- /dev/null
+++ b/hw/xwin/winclipboard/xevents.c
@@ -0,0 +1,862 @@
+/*
+ *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
+ *Copyright (C) Colin Harrison 2005-2008
+ *
+ *Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ *"Software"), to deal in the Software without restriction, including
+ *without limitation the rights to use, copy, modify, merge, publish,
+ *distribute, sublicense, and/or sell copies of the Software, and to
+ *permit persons to whom the Software is furnished to do so, subject to
+ *the following conditions:
+ *
+ *The above copyright notice and this permission notice shall be
+ *included in all copies or substantial portions of the Software.
+ *
+ *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
+ *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *Except as contained in this notice, the name of the copyright holder(s)
+ *and author(s) shall not be used in advertising or otherwise to promote
+ *the sale, use or other dealings in this Software without prior written
+ *authorization from the copyright holder(s) and author(s).
+ *
+ * Authors:	Harold L Hunt II
+ *              Colin Harrison
+ */
+
+#ifdef HAVE_XWIN_CONFIG_H
+#include <xwin-config.h>
+#endif
+
+#include "winclipboard.h"
+#include "misc.h"
+#include <X11/extensions/Xfixes.h>
+
+/*
+ * Constants
+ */
+
+#define CLIP_NUM_SELECTIONS		2
+#define CLIP_OWN_NONE     		-1
+#define CLIP_OWN_PRIMARY		0
+#define CLIP_OWN_CLIPBOARD		1
+
+/*
+ * Global variables
+ */
+
+extern int xfixes_event_base;
+
+/*
+ * Local variables
+ */
+
+static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
+static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
+    { "PRIMARY", "CLIPBOARD" };
+
+static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
+static Atom atomClipboard = None;
+
+static void
+MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
+{
+    /* Look for owned -> not owned transition */
+    if (None == e->owner && None != s_iOwners[i]) {
+        unsigned int other_index;
+
+        winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
+                 szSelectionNames[i]);
+
+        /* If this selection is not owned, the other monitored selection must be the most
+           recently owned, if it is owned at all */
+        if (i == CLIP_OWN_PRIMARY)
+            other_index = CLIP_OWN_CLIPBOARD;
+        if (i == CLIP_OWN_CLIPBOARD)
+            other_index = CLIP_OWN_PRIMARY;
+        if (None != s_iOwners[other_index])
+            lastOwnedSelectionIndex = other_index;
+        else
+            lastOwnedSelectionIndex = CLIP_OWN_NONE;
+    }
+
+    /* Save last owned selection */
+    if (None != e->owner) {
+        lastOwnedSelectionIndex = i;
+    }
+
+    /* Save new selection owner or None */
+    s_iOwners[i] = e->owner;
+    winDebug("MonitorSelection - %s - Now owned by XID %x\n",
+             szSelectionNames[i], e->owner);
+}
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(void)
+{
+    if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
+        return None;
+
+    if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
+        return XA_PRIMARY;
+
+    if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
+        return atomClipboard;
+
+    return None;
+}
+
+
+void
+winClipboardInitMonitoredSelections(void)
+{
+    /* Initialize static variables */
+    for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
+      s_iOwners[i] = None;
+
+    lastOwnedSelectionIndex = CLIP_OWN_NONE;
+}
+
+/*
+ * Process any pending X events
+ */
+
+int
+winClipboardFlushXEvents(HWND hwnd,
+                         int iWindow, Display * pDisplay, Bool fUseUnicode)
+{
+    static Atom atomLocalProperty;
+    static Atom atomCompoundText;
+    static Atom atomUTF8String;
+    static Atom atomTargets;
+    static int generation;
+
+    if (generation != serverGeneration) {
+        generation = serverGeneration;
+        atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
+        atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
+        atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
+        atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
+        atomTargets = XInternAtom(pDisplay, "TARGETS", False);
+    }
+
+    /* Process all pending events */
+    while (XPending(pDisplay)) {
+        XTextProperty xtpText = { 0 };
+        XEvent event;
+        XSelectionEvent eventSelection;
+        unsigned long ulReturnBytesLeft;
+        char *pszReturnData = NULL;
+        char *pszGlobalData = NULL;
+        int iReturn;
+        HGLOBAL hGlobal = NULL;
+        XICCEncodingStyle xiccesStyle;
+        int iConvertDataLen = 0;
+        char *pszConvertData = NULL;
+        char *pszTextList[2] = { NULL };
+        int iCount;
+        char **ppszTextList = NULL;
+        wchar_t *pwszUnicodeStr = NULL;
+        int iUnicodeLen = 0;
+        int iReturnDataLen = 0;
+        Bool fAbort = FALSE;
+        Bool fCloseClipboard = FALSE;
+        Bool fSetClipboardData = TRUE;
+
+        /* Get the next event - will not block because one is ready */
+        XNextEvent(pDisplay, &event);
+
+        /* Branch on the event type */
+        switch (event.type) {
+            /*
+             * SelectionRequest
+             */
+
+        case SelectionRequest:
+        {
+            char *pszAtomName = NULL;
+
+            winDebug("SelectionRequest - target %d\n",
+                     event.xselectionrequest.target);
+
+            pszAtomName = XGetAtomName(pDisplay,
+                                       event.xselectionrequest.target);
+            winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
+            XFree(pszAtomName);
+            pszAtomName = NULL;
+        }
+
+            /* Abort if invalid target type */
+            if (event.xselectionrequest.target != XA_STRING
+                && event.xselectionrequest.target != atomUTF8String
+                && event.xselectionrequest.target != atomCompoundText
+                && event.xselectionrequest.target != atomTargets) {
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+            /* Handle targets type of request */
+            if (event.xselectionrequest.target == atomTargets) {
+                Atom atomTargetArr[] = { atomTargets,
+                    atomCompoundText,
+                    atomUTF8String,
+                    XA_STRING
+                };
+
+                /* Try to change the property */
+                iReturn = XChangeProperty(pDisplay,
+                                          event.xselectionrequest.requestor,
+                                          event.xselectionrequest.property,
+                                          XA_ATOM,
+                                          32,
+                                          PropModeReplace,
+                                          (unsigned char *) atomTargetArr,
+                                          (sizeof(atomTargetArr)
+                                           / sizeof(atomTargetArr[0])));
+                if (iReturn == BadAlloc
+                    || iReturn == BadAtom
+                    || iReturn == BadMatch
+                    || iReturn == BadValue || iReturn == BadWindow) {
+                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                           "XChangeProperty failed: %d\n", iReturn);
+                }
+
+                /* Setup selection notify xevent */
+                eventSelection.type = SelectionNotify;
+                eventSelection.send_event = True;
+                eventSelection.display = pDisplay;
+                eventSelection.requestor = event.xselectionrequest.requestor;
+                eventSelection.selection = event.xselectionrequest.selection;
+                eventSelection.target = event.xselectionrequest.target;
+                eventSelection.property = event.xselectionrequest.property;
+                eventSelection.time = event.xselectionrequest.time;
+
+                /*
+                 * Notify the requesting window that
+                 * the operation has completed
+                 */
+                iReturn = XSendEvent(pDisplay,
+                                     eventSelection.requestor,
+                                     False, 0L, (XEvent *) &eventSelection);
+                if (iReturn == BadValue || iReturn == BadWindow) {
+                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                           "XSendEvent () failed\n");
+                }
+                break;
+            }
+
+            /* Close clipboard if we have it open already */
+            if (GetOpenClipboardWindow() == hwnd) {
+                CloseClipboard();
+            }
+
+            /* Access the clipboard */
+            if (!OpenClipboard(hwnd)) {
+                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                       "OpenClipboard () failed: %08lx\n", GetLastError());
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+            /* Indicate that clipboard was opened */
+            fCloseClipboard = TRUE;
+
+            /* Check that clipboard format is available */
+            if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
+                static int count;       /* Hack to stop acroread spamming the log */
+                static HWND lasthwnd;   /* I've not seen any other client get here repeatedly? */
+
+                if (hwnd != lasthwnd)
+                    count = 0;
+                count++;
+                if (count < 6)
+                    ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
+                           "available from Win32 clipboard.  Aborting %d.\n",
+                           count);
+                lasthwnd = hwnd;
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+            else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
+                ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
+                       "available from Win32 clipboard.  Aborting.\n");
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+            /* Setup the string style */
+            if (event.xselectionrequest.target == XA_STRING)
+                xiccesStyle = XStringStyle;
+#ifdef X_HAVE_UTF8_STRING
+            else if (event.xselectionrequest.target == atomUTF8String)
+                xiccesStyle = XUTF8StringStyle;
+#endif
+            else if (event.xselectionrequest.target == atomCompoundText)
+                xiccesStyle = XCompoundTextStyle;
+            else
+                xiccesStyle = XStringStyle;
+
+            /* Get a pointer to the clipboard text, in desired format */
+            if (fUseUnicode) {
+                /* Retrieve clipboard data */
+                hGlobal = GetClipboardData(CF_UNICODETEXT);
+            }
+            else {
+                /* Retrieve clipboard data */
+                hGlobal = GetClipboardData(CF_TEXT);
+            }
+            if (!hGlobal) {
+                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                       "GetClipboardData () failed: %08lx\n", GetLastError());
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+            pszGlobalData = (char *) GlobalLock(hGlobal);
+
+            /* Convert the Unicode string to UTF8 (MBCS) */
+            if (fUseUnicode) {
+                iConvertDataLen = WideCharToMultiByte(CP_UTF8,
+                                                      0,
+                                                      (LPCWSTR) pszGlobalData,
+                                                      -1, NULL, 0, NULL, NULL);
+                /* NOTE: iConvertDataLen includes space for null terminator */
+                pszConvertData = malloc(iConvertDataLen);
+                WideCharToMultiByte(CP_UTF8,
+                                    0,
+                                    (LPCWSTR) pszGlobalData,
+                                    -1,
+                                    pszConvertData,
+                                    iConvertDataLen, NULL, NULL);
+            }
+            else {
+                pszConvertData = strdup(pszGlobalData);
+                iConvertDataLen = strlen(pszConvertData) + 1;
+            }
+
+            /* Convert DOS string to UNIX string */
+            winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));
+
+            /* Setup our text list */
+            pszTextList[0] = pszConvertData;
+            pszTextList[1] = NULL;
+
+            /* Initialize the text property */
+            xtpText.value = NULL;
+            xtpText.nitems = 0;
+
+            /* Create the text property from the text list */
+            if (fUseUnicode) {
+#ifdef X_HAVE_UTF8_STRING
+                iReturn = Xutf8TextListToTextProperty(pDisplay,
+                                                      pszTextList,
+                                                      1, xiccesStyle, &xtpText);
+#endif
+            }
+            else {
+                iReturn = XmbTextListToTextProperty(pDisplay,
+                                                    pszTextList,
+                                                    1, xiccesStyle, &xtpText);
+            }
+            if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
+                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                       "X*TextListToTextProperty failed: %d\n", iReturn);
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+            /* Free the converted string */
+            free(pszConvertData);
+            pszConvertData = NULL;
+
+            /* Copy the clipboard text to the requesting window */
+            iReturn = XChangeProperty(pDisplay,
+                                      event.xselectionrequest.requestor,
+                                      event.xselectionrequest.property,
+                                      event.xselectionrequest.target,
+                                      8,
+                                      PropModeReplace,
+                                      xtpText.value, xtpText.nitems);
+            if (iReturn == BadAlloc || iReturn == BadAtom
+                || iReturn == BadMatch || iReturn == BadValue
+                || iReturn == BadWindow) {
+                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                       "XChangeProperty failed: %d\n", iReturn);
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+            /* Release the clipboard data */
+            GlobalUnlock(hGlobal);
+            pszGlobalData = NULL;
+            fCloseClipboard = FALSE;
+            CloseClipboard();
+
+            /* Clean up */
+            XFree(xtpText.value);
+            xtpText.value = NULL;
+            xtpText.nitems = 0;
+
+            /* Setup selection notify event */
+            eventSelection.type = SelectionNotify;
+            eventSelection.send_event = True;
+            eventSelection.display = pDisplay;
+            eventSelection.requestor = event.xselectionrequest.requestor;
+            eventSelection.selection = event.xselectionrequest.selection;
+            eventSelection.target = event.xselectionrequest.target;
+            eventSelection.property = event.xselectionrequest.property;
+            eventSelection.time = event.xselectionrequest.time;
+
+            /* Notify the requesting window that the operation has completed */
+            iReturn = XSendEvent(pDisplay,
+                                 eventSelection.requestor,
+                                 False, 0L, (XEvent *) &eventSelection);
+            if (iReturn == BadValue || iReturn == BadWindow) {
+                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                       "XSendEvent () failed\n");
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionRequest_Done;
+            }
+
+ winClipboardFlushXEvents_SelectionRequest_Done:
+            /* Free allocated resources */
+            if (xtpText.value) {
+                XFree(xtpText.value);
+                xtpText.value = NULL;
+                xtpText.nitems = 0;
+            }
+            free(pszConvertData);
+            if (hGlobal && pszGlobalData)
+                GlobalUnlock(hGlobal);
+
+            /*
+             * Send a SelectionNotify event to the requesting
+             * client when we abort.
+             */
+            if (fAbort) {
+                /* Setup selection notify event */
+                eventSelection.type = SelectionNotify;
+                eventSelection.send_event = True;
+                eventSelection.display = pDisplay;
+                eventSelection.requestor = event.xselectionrequest.requestor;
+                eventSelection.selection = event.xselectionrequest.selection;
+                eventSelection.target = event.xselectionrequest.target;
+                eventSelection.property = None;
+                eventSelection.time = event.xselectionrequest.time;
+
+                /* Notify the requesting window that the operation is complete */
+                iReturn = XSendEvent(pDisplay,
+                                     eventSelection.requestor,
+                                     False, 0L, (XEvent *) &eventSelection);
+                if (iReturn == BadValue || iReturn == BadWindow) {
+                    /*
+                     * Should not be a problem if XSendEvent fails because
+                     * the client may simply have exited.
+                     */
+                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
+                           "XSendEvent () failed for abort event.\n");
+                }
+            }
+
+            /* Close clipboard if it was opened */
+            if (fCloseClipboard) {
+                fCloseClipboard = FALSE;
+                CloseClipboard();
+            }
+            break;
+
+            /*
+             * SelectionNotify
+             */
+
+        case SelectionNotify:
+
+            winDebug("winClipboardFlushXEvents - SelectionNotify\n");
+            {
+                char *pszAtomName;
+
+                pszAtomName = XGetAtomName(pDisplay,
+                                           event.xselection.selection);
+
+                winDebug
+                    ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
+                     pszAtomName);
+                XFree(pszAtomName);
+            }
+
+            /*
+             * Request conversion of UTF8 and CompoundText targets.
+             */
+            if (event.xselection.property == None) {
+                if (event.xselection.target == XA_STRING) {
+                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
+                             "XA_STRING\n");
+
+                    return WIN_XEVENTS_CONVERT;
+                }
+                else if (event.xselection.target == atomUTF8String) {
+                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
+                             "Requesting conversion of UTF8 target.\n");
+
+                    XConvertSelection(pDisplay,
+                                      event.xselection.selection,
+                                      XA_STRING,
+                                      atomLocalProperty, iWindow, CurrentTime);
+
+                    /* Process the ConvertSelection event */
+                    XFlush(pDisplay);
+                    return WIN_XEVENTS_CONVERT;
+                }
+#ifdef X_HAVE_UTF8_STRING
+                else if (event.xselection.target == atomCompoundText) {
+                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
+                             "Requesting conversion of CompoundText target.\n");
+
+                    XConvertSelection(pDisplay,
+                                      event.xselection.selection,
+                                      atomUTF8String,
+                                      atomLocalProperty, iWindow, CurrentTime);
+
+                    /* Process the ConvertSelection event */
+                    XFlush(pDisplay);
+                    return WIN_XEVENTS_CONVERT;
+                }
+#endif
+                else {
+                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+                           "Unknown format.  Cannot request conversion, "
+                           "aborting.\n");
+                    break;
+                }
+            }
+
+            /* Retrieve the size of the stored data */
+            iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0,    /* Don't get data, just size */
+                                         False,
+                                         AnyPropertyType,
+                                         &xtpText.encoding,
+                                         &xtpText.format,
+                                         &xtpText.nitems,
+                                         &ulReturnBytesLeft, &xtpText.value);
+            if (iReturn != Success) {
+                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
+                break;
+            }
+
+            winDebug("SelectionNotify - returned data %d left %d\n",
+                     xtpText.nitems, ulReturnBytesLeft);
+
+            /* Request the selection data */
+            iReturn = XGetWindowProperty(pDisplay,
+                                         iWindow,
+                                         atomLocalProperty,
+                                         0,
+                                         ulReturnBytesLeft,
+                                         False,
+                                         AnyPropertyType,
+                                         &xtpText.encoding,
+                                         &xtpText.format,
+                                         &xtpText.nitems,
+                                         &ulReturnBytesLeft, &xtpText.value);
+            if (iReturn != Success) {
+                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
+                break;
+            }
+
+            {
+                char *pszAtomName = NULL;
+
+                winDebug("SelectionNotify - returned data %d left %d\n",
+                         xtpText.nitems, ulReturnBytesLeft);
+                pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
+                winDebug("Notify atom name %s\n", pszAtomName);
+                XFree(pszAtomName);
+                pszAtomName = NULL;
+            }
+
+            if (fUseUnicode) {
+#ifdef X_HAVE_UTF8_STRING
+                /* Convert the text property to a text list */
+                iReturn = Xutf8TextPropertyToTextList(pDisplay,
+                                                      &xtpText,
+                                                      &ppszTextList, &iCount);
+#endif
+            }
+            else {
+                iReturn = XmbTextPropertyToTextList(pDisplay,
+                                                    &xtpText,
+                                                    &ppszTextList, &iCount);
+            }
+            if (iReturn == Success || iReturn > 0) {
+                /* Conversion succeeded or some unconvertible characters */
+                if (ppszTextList != NULL) {
+                    int i;
+
+                    iReturnDataLen = 0;
+                    for (i = 0; i < iCount; i++) {
+                        iReturnDataLen += strlen(ppszTextList[i]);
+                    }
+                    pszReturnData = malloc(iReturnDataLen + 1);
+                    pszReturnData[0] = '\0';
+                    for (i = 0; i < iCount; i++) {
+                        strcat(pszReturnData, ppszTextList[i]);
+                    }
+                }
+                else {
+                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+                           "X*TextPropertyToTextList list_return is NULL.\n");
+                    pszReturnData = malloc(1);
+                    pszReturnData[0] = '\0';
+                }
+            }
+            else {
+                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
+                       "X*TextPropertyToTextList returned: ");
+                switch (iReturn) {
+                case XNoMemory:
+                    ErrorF("XNoMemory\n");
+                    break;
+                case XLocaleNotSupported:
+                    ErrorF("XLocaleNotSupported\n");
+                    break;
+                case XConverterNotFound:
+                    ErrorF("XConverterNotFound\n");
+                    break;
+                default:
+                    ErrorF("%d\n", iReturn);
+                    break;
+                }
+                pszReturnData = malloc(1);
+                pszReturnData[0] = '\0';
+            }
+
+            /* Free the data returned from XGetWindowProperty */
+            if (ppszTextList)
+                XFreeStringList(ppszTextList);
+            ppszTextList = NULL;
+            XFree(xtpText.value);
+            xtpText.value = NULL;
+            xtpText.nitems = 0;
+
+            /* Convert the X clipboard string to DOS format */
+            winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
+
+            if (fUseUnicode) {
+                /* Find out how much space needed to convert MBCS to Unicode */
+                iUnicodeLen = MultiByteToWideChar(CP_UTF8,
+                                                  0,
+                                                  pszReturnData, -1, NULL, 0);
+
+                /* Allocate memory for the Unicode string */
+                pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
+                if (!pwszUnicodeStr) {
+                    ErrorF("winClipboardFlushXEvents - SelectionNotify "
+                           "malloc failed for pwszUnicodeStr, aborting.\n");
+
+                    /* Abort */
+                    fAbort = TRUE;
+                    goto winClipboardFlushXEvents_SelectionNotify_Done;
+                }
+
+                /* Do the actual conversion */
+                MultiByteToWideChar(CP_UTF8,
+                                    0,
+                                    pszReturnData,
+                                    -1, pwszUnicodeStr, iUnicodeLen);
+
+                /* Allocate global memory for the X clipboard data */
+                hGlobal = GlobalAlloc(GMEM_MOVEABLE,
+                                      sizeof(wchar_t) * (iUnicodeLen + 1));
+            }
+            else {
+                pszConvertData = strdup(pszReturnData);
+                iConvertDataLen = strlen(pszConvertData) + 1;
+
+                /* Allocate global memory for the X clipboard data */
+                hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
+            }
+
+            free(pszReturnData);
+
+            /* Check that global memory was allocated */
+            if (!hGlobal) {
+                ErrorF("winClipboardFlushXEvents - SelectionNotify "
+                       "GlobalAlloc failed, aborting: %ld\n", GetLastError());
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionNotify_Done;
+            }
+
+            /* Obtain a pointer to the global memory */
+            pszGlobalData = GlobalLock(hGlobal);
+            if (pszGlobalData == NULL) {
+                ErrorF("winClipboardFlushXEvents - Could not lock global "
+                       "memory for clipboard transfer\n");
+
+                /* Abort */
+                fAbort = TRUE;
+                goto winClipboardFlushXEvents_SelectionNotify_Done;
+            }
+
+            /* Copy the returned string into the global memory */
+            if (fUseUnicode) {
+                memcpy(pszGlobalData,
+                       pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
+                free(pwszUnicodeStr);
+                pwszUnicodeStr = NULL;
+            }
+            else {
+                strcpy(pszGlobalData, pszConvertData);
+                free(pszConvertData);
+                pszConvertData = NULL;
+            }
+
+            /* Release the pointer to the global memory */
+            GlobalUnlock(hGlobal);
+            pszGlobalData = NULL;
+
+            /* Push the selection data to the Windows clipboard */
+            if (fUseUnicode)
+                SetClipboardData(CF_UNICODETEXT, hGlobal);
+            else
+                SetClipboardData(CF_TEXT, hGlobal);
+
+            /* Flag that SetClipboardData has been called */
+            fSetClipboardData = FALSE;
+
+            /*
+             * NOTE: Do not try to free pszGlobalData, it is owned by
+             * Windows after the call to SetClipboardData ().
+             */
+
+ winClipboardFlushXEvents_SelectionNotify_Done:
+            /* Free allocated resources */
+            if (ppszTextList)
+                XFreeStringList(ppszTextList);
+            if (xtpText.value) {
+                XFree(xtpText.value);
+                xtpText.value = NULL;
+                xtpText.nitems = 0;
+            }
+            free(pszConvertData);
+            free(pwszUnicodeStr);
+            if (hGlobal && pszGlobalData)
+                GlobalUnlock(hGlobal);
+            if (fSetClipboardData) {
+                SetClipboardData(CF_UNICODETEXT, NULL);
+                SetClipboardData(CF_TEXT, NULL);
+            }
+            return WIN_XEVENTS_NOTIFY;
+
+        case SelectionClear:
+            winDebug("SelectionClear - doing nothing\n");
+            break;
+
+        case PropertyNotify:
+            break;
+
+        case MappingNotify:
+            break;
+
+        default:
+            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
+                XFixesSelectionNotifyEvent *e =
+                    (XFixesSelectionNotifyEvent *) & event;
+
+                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
+
+                /* Save selection owners for monitored selections, ignore other selections */
+                if (e->selection == XA_PRIMARY) {
+                    MonitorSelection(e, CLIP_OWN_PRIMARY);
+                }
+                else if (e->selection == atomClipboard) {
+                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
+                }
+                else
+                    break;
+
+                /* Selection is being disowned */
+                if (e->owner == None) {
+                    winDebug
+                        ("winClipboardFlushXEvents - No window, returning.\n");
+                    break;
+                }
+
+                /*
+                   XXX: there are all kinds of wacky edge cases we might need here:
+                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
+                   - root window is taking ownership?
+                 */
+
+                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
+                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
+                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
+                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
+                    break;
+                }
+
+                /* Close clipboard if we have it open already (possible? correct??) */
+                if (GetOpenClipboardWindow() == hwnd) {
+                    CloseClipboard();
+                }
+
+                /* Access the Windows clipboard */
+                if (!OpenClipboard(hwnd)) {
+                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+
+                /* Take ownership of the Windows clipboard */
+                if (!EmptyClipboard()) {
+                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+
+                /* Advertise regular text and unicode */
+                SetClipboardData(CF_UNICODETEXT, NULL);
+                SetClipboardData(CF_TEXT, NULL);
+
+                /* Release the clipboard */
+                if (!CloseClipboard()) {
+                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+            }
+            /* XFixesSelectionWindowDestroyNotifyMask */
+            /* XFixesSelectionClientCloseNotifyMask */
+            else {
+                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
+                       event.type);
+            }
+            break;
+        }
+    }
+
+    return WIN_XEVENTS_SUCCESS;
+}
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index d16c121..2e400f6 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -36,7 +36,7 @@
 #include <pthread.h>
 
 #include "os.h"
-#include "winclipboard.h"
+#include "winclipboard/winclipboard.h"
 #include "windisplay.h"
 
 #define WIN_CLIPBOARD_RETRIES			40
diff --git a/hw/xwin/winclipboardtextconv.c b/hw/xwin/winclipboardtextconv.c
deleted file mode 100644
index fd405a0..0000000
--- a/hw/xwin/winclipboardtextconv.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of Harold L Hunt II
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from Harold L Hunt II.
- *
- * Authors:	Harold L Hunt II
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-void
- winClipboardDOStoUNIX(char *pszSrc, int iLength);
-void
- winClipboardUNIXtoDOS(char **ppszData, int iLength);
-
-/*
- * Convert \r\n to \n
- *
- * NOTE: This was heavily inspired by, Cygwin's
- * winsup/cygwin/fhandler.cc/fhandler_base::read ()
- */
-
-void
-winClipboardDOStoUNIX(char *pszSrc, int iLength)
-{
-    char *pszDest = pszSrc;
-    char *pszEnd = pszSrc + iLength;
-
-    /* Loop until the last character */
-    while (pszSrc < pszEnd) {
-        /* Copy the current source character to current destination character */
-        *pszDest = *pszSrc;
-
-        /* Advance to the next source character */
-        pszSrc++;
-
-        /* Don't advance the destination character if we need to drop an \r */
-        if (*pszDest != '\r' || *pszSrc != '\n')
-            pszDest++;
-    }
-
-    /* Move the terminating null */
-    *pszDest = '\0';
-}
-
-/*
- * Convert \n to \r\n
- */
-
-void
-winClipboardUNIXtoDOS(char **ppszData, int iLength)
-{
-    int iNewlineCount = 0;
-    char *pszSrc = *ppszData;
-    char *pszEnd = pszSrc + iLength;
-    char *pszDest = NULL, *pszDestBegin = NULL;
-
-    winDebug("UNIXtoDOS () - Original data:'%s'\n", *ppszData);
-
-    /* Count \n characters without leading \r */
-    while (pszSrc < pszEnd) {
-        /* Skip ahead two character if found set of \r\n */
-        if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
-            pszSrc += 2;
-            continue;
-        }
-
-        /* Increment the count if found naked \n */
-        if (*pszSrc == '\n') {
-            iNewlineCount++;
-        }
-
-        pszSrc++;
-    }
-
-    /* Return if no naked \n's */
-    if (iNewlineCount == 0)
-        return;
-
-    /* Allocate a new string */
-    pszDestBegin = pszDest = malloc(iLength + iNewlineCount + 1);
-
-    /* Set source pointer to beginning of data string */
-    pszSrc = *ppszData;
-
-    /* Loop through all characters in source string */
-    while (pszSrc < pszEnd) {
-        /* Copy line endings that are already valid */
-        if (*pszSrc == '\r' && pszSrc + 1 < pszEnd && *(pszSrc + 1) == '\n') {
-            *pszDest = *pszSrc;
-            *(pszDest + 1) = *(pszSrc + 1);
-            pszDest += 2;
-            pszSrc += 2;
-            continue;
-        }
-
-        /* Add \r to naked \n's */
-        if (*pszSrc == '\n') {
-            *pszDest = '\r';
-            *(pszDest + 1) = *pszSrc;
-            pszDest += 2;
-            pszSrc += 1;
-            continue;
-        }
-
-        /* Copy normal characters */
-        *pszDest = *pszSrc;
-        pszSrc++;
-        pszDest++;
-    }
-
-    /* Put terminating null at end of new string */
-    *pszDest = '\0';
-
-    /* Swap string pointers */
-    free(*ppszData);
-    *ppszData = pszDestBegin;
-
-    winDebug("UNIXtoDOS () - Final string:'%s'\n", pszDestBegin);
-}
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
deleted file mode 100644
index 2641e20..0000000
--- a/hw/xwin/winclipboardthread.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *Copyright (C) Colin Harrison 2005-2008
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the copyright holder(s)
- *and author(s) shall not be used in advertising or otherwise to promote
- *the sale, use or other dealings in this Software without prior written
- *authorization from the copyright holder(s) and author(s).
- *
- * Authors:	Harold L Hunt II
- *              Colin Harrison
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#else
-#define HAS_WINSOCK 1
-#endif
-#include <sys/types.h>
-#include <signal.h>
-#include "winclipboard.h"
-#include "windisplay.h"
-#ifdef __CYGWIN__
-#include <errno.h>
-#endif
-#include "misc.h"
-#include <X11/extensions/Xfixes.h>
-
-#define WIN_CONNECT_RETRIES			40
-#define WIN_CONNECT_DELAY			4
-
-#define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
-#define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
-
-/*
- * References to external symbols
- */
-
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboard;
-
-/*
- * Global variables
- */
-
-static HWND g_hwndClipboard = NULL;
-static jmp_buf g_jmpEntry;
-static XIOErrorHandler g_winClipboardOldIOErrorHandler;
-static pthread_t g_winClipboardProcThread;
-
-Bool g_fUseUnicode = FALSE;
-int xfixes_event_base;
-int xfixes_error_base;
-
-/*
- * Local function prototypes
- */
-
-static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow);
-
-static int
- winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
-
-static int
- winClipboardIOErrorHandler(Display * pDisplay);
-
-/*
- * Main thread function
- */
-
-void *
-winClipboardProc(char *szDisplay)
-{
-    Atom atomClipboard;
-    int iReturn;
-    HWND hwnd = NULL;
-    int iConnectionNumber = 0;
-
-#ifdef HAS_DEVWINDOWS
-    int fdMessageQueue = 0;
-#else
-    struct timeval tvTimeout;
-#endif
-    fd_set fdsRead;
-    int iMaxDescriptor;
-    Display *pDisplay = NULL;
-    Window iWindow = None;
-    int iRetries;
-    Bool fUseUnicode;
-    int iSelectError;
-
-    winDebug("winClipboardProc - Hello\n");
-
-    /* Do we use Unicode clipboard? */
-    fUseUnicode = g_fUnicodeClipboard;
-
-    /* Save the Unicode support flag in a global */
-    g_fUseUnicode = fUseUnicode;
-
-    /* Allow multiple threads to access Xlib */
-    if (XInitThreads() == 0) {
-        ErrorF("winClipboardProc - XInitThreads failed.\n");
-        goto winClipboardProc_Exit;
-    }
-
-    /* See if X supports the current locale */
-    if (XSupportsLocale() == False) {
-        ErrorF("winClipboardProc - Warning: Locale not supported by X.\n");
-    }
-
-    /* Set error handler */
-    XSetErrorHandler(winClipboardErrorHandler);
-    g_winClipboardProcThread = pthread_self();
-    g_winClipboardOldIOErrorHandler =
-        XSetIOErrorHandler(winClipboardIOErrorHandler);
-
-    /* Set jump point for Error exits */
-    iReturn = setjmp(g_jmpEntry);
-
-    /* Check if we should continue operations */
-    if (iReturn != WIN_JMP_ERROR_IO && iReturn != WIN_JMP_OKAY) {
-        /* setjmp returned an unknown value, exit */
-        ErrorF("winClipboardProc - setjmp returned: %d exiting\n", iReturn);
-        goto winClipboardProc_Exit;
-    }
-    else if (iReturn == WIN_JMP_ERROR_IO) {
-        /* TODO: Cleanup the Win32 window and free any allocated memory */
-        ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
-        goto winClipboardProc_Done;
-    }
-
-    /* Initialize retry count */
-    iRetries = 0;
-
-
-    /* Open the X display */
-    do {
-        pDisplay = XOpenDisplay(szDisplay);
-        if (pDisplay == NULL) {
-            ErrorF("winClipboardProc - Could not open display, "
-                   "try: %d, sleeping: %d\n", iRetries + 1, WIN_CONNECT_DELAY);
-            ++iRetries;
-            sleep(WIN_CONNECT_DELAY);
-            continue;
-        }
-        else
-            break;
-    }
-    while (pDisplay == NULL && iRetries < WIN_CONNECT_RETRIES);
-
-    /* Make sure that the display opened */
-    if (pDisplay == NULL) {
-        ErrorF("winClipboardProc - Failed opening the display, giving up\n");
-        goto winClipboardProc_Done;
-    }
-
-    ErrorF("winClipboardProc - XOpenDisplay () returned and "
-           "successfully opened the display.\n");
-
-    /* Get our connection number */
-    iConnectionNumber = ConnectionNumber(pDisplay);
-
-#ifdef HAS_DEVWINDOWS
-    /* Open a file descriptor for the windows message queue */
-    fdMessageQueue = open(WIN_MSG_QUEUE_FNAME, O_RDONLY);
-    if (fdMessageQueue == -1) {
-        ErrorF("winClipboardProc - Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
-        goto winClipboardProc_Done;
-    }
-
-    /* Find max of our file descriptors */
-    iMaxDescriptor = max(fdMessageQueue, iConnectionNumber) + 1;
-#else
-    iMaxDescriptor = iConnectionNumber + 1;
-#endif
-
-    if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
-      ErrorF ("winClipboardProc - XFixes extension not present\n");
-
-    /* Create atom */
-    atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
-
-    /* Create a messaging window */
-    iWindow = XCreateSimpleWindow(pDisplay,
-                                  DefaultRootWindow(pDisplay),
-                                  1, 1,
-                                  500, 500,
-                                  0,
-                                  BlackPixel(pDisplay, 0),
-                                  BlackPixel(pDisplay, 0));
-    if (iWindow == 0) {
-        ErrorF("winClipboardProc - Could not create an X window.\n");
-        goto winClipboardProc_Done;
-    }
-
-    XStoreName(pDisplay, iWindow, "xwinclip");
-
-    /* Select event types to watch */
-    if (XSelectInput(pDisplay, iWindow, PropertyChangeMask) == BadWindow)
-        ErrorF("winClipboardProc - XSelectInput generated BadWindow "
-               "on messaging window\n");
-
-    XFixesSelectSelectionInput (pDisplay,
-                                iWindow,
-                                XA_PRIMARY,
-                                XFixesSetSelectionOwnerNotifyMask |
-                                XFixesSelectionWindowDestroyNotifyMask |
-                                XFixesSelectionClientCloseNotifyMask);
-
-    XFixesSelectSelectionInput (pDisplay,
-                                iWindow,
-                                XInternAtom (pDisplay, "CLIPBOARD", False),
-                                XFixesSetSelectionOwnerNotifyMask |
-                                XFixesSelectionWindowDestroyNotifyMask |
-                                XFixesSelectionClientCloseNotifyMask);
-
-
-    /* Initialize monitored selection state */
-    winClipboardInitMonitoredSelections();
-    /* Create Windows messaging window */
-    hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow);
-
-    /* Save copy of HWND */
-    g_hwndClipboard = hwnd;
-
-    /* Assert ownership of selections if Win32 clipboard is owned */
-    if (NULL != GetClipboardOwner()) {
-        /* PRIMARY */
-        iReturn = XSetSelectionOwner(pDisplay, XA_PRIMARY,
-                                     iWindow, CurrentTime);
-        if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
-            ErrorF("winClipboardProc - Could not set PRIMARY owner\n");
-            goto winClipboardProc_Done;
-        }
-
-        /* CLIPBOARD */
-        iReturn = XSetSelectionOwner(pDisplay, atomClipboard,
-                                     iWindow, CurrentTime);
-        if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
-            ErrorF("winClipboardProc - Could not set CLIPBOARD owner\n");
-            goto winClipboardProc_Done;
-        }
-    }
-
-    /* Pre-flush X events */
-    /* 
-     * NOTE: Apparently you'll freeze if you don't do this,
-     *       because there may be events in local data structures
-     *       already.
-     */
-    winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
-
-    /* Pre-flush Windows messages */
-    if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
-        ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
-    }
-
-    /* Loop for X events */
-    while (1) {
-        /* Setup the file descriptor set */
-        /*
-         * NOTE: You have to do this before every call to select
-         *       because select modifies the mask to indicate
-         *       which descriptors are ready.
-         */
-        FD_ZERO(&fdsRead);
-        FD_SET(iConnectionNumber, &fdsRead);
-#ifdef HAS_DEVWINDOWS
-        FD_SET(fdMessageQueue, &fdsRead);
-#else
-        tvTimeout.tv_sec = 0;
-        tvTimeout.tv_usec = 100;
-#endif
-
-        /* Wait for a Windows event or an X event */
-        iReturn = select(iMaxDescriptor,        /* Highest fds number */
-                         &fdsRead,      /* Read mask */
-                         NULL,  /* No write mask */
-                         NULL,  /* No exception mask */
-#ifdef HAS_DEVWINDOWS
-                         NULL   /* No timeout */
-#else
-                         &tvTimeout     /* Set timeout */
-#endif
-            );
-
-#ifndef HAS_WINSOCK
-        iSelectError = errno;
-#else
-        iSelectError = WSAGetLastError();
-#endif
-
-        if (iReturn < 0) {
-#ifndef HAS_WINSOCK
-            if (iSelectError == EINTR)
-#else
-            if (iSelectError == WSAEINTR)
-#endif
-                continue;
-
-            ErrorF("winClipboardProc - Call to select () failed: %d.  "
-                   "Bailing.\n", iReturn);
-            break;
-        }
-
-        /* Branch on which descriptor became active */
-        if (FD_ISSET(iConnectionNumber, &fdsRead)) {
-            /* Process X events */
-            winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
-        }
-
-#ifdef HAS_DEVWINDOWS
-        /* Check for Windows event ready */
-        if (FD_ISSET(fdMessageQueue, &fdsRead))
-#else
-        if (1)
-#endif
-        {
-            /* Process Windows messages */
-            if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
-                ErrorF("winClipboardProc - "
-                       "winClipboardFlushWindowsMessageQueue trapped "
-                       "WM_QUIT message, exiting main loop.\n");
-                break;
-            }
-        }
-    }
-
- winClipboardProc_Exit:
-    /* disable the clipboard, which means the thread will die */
-    g_fClipboard = FALSE;
-
- winClipboardProc_Done:
-    /* Close our Windows window */
-    if (g_hwndClipboard) {
-        winClipboardWindowDestroy();
-    }
-
-    /* Close our X window */
-    if (pDisplay && iWindow) {
-        iReturn = XDestroyWindow(pDisplay, iWindow);
-        if (iReturn == BadWindow)
-            ErrorF("winClipboardProc - XDestroyWindow returned BadWindow.\n");
-        else
-            ErrorF("winClipboardProc - XDestroyWindow succeeded.\n");
-    }
-
-#ifdef HAS_DEVWINDOWS
-    /* Close our Win32 message handle */
-    if (fdMessageQueue)
-        close(fdMessageQueue);
-#endif
-
-#if 0
-    /*
-     * FIXME: XCloseDisplay hangs if we call it, as of 2004/03/26.  The
-     * XSync and XSelectInput calls did not help.
-     */
-
-    /* Discard any remaining events */
-    XSync(pDisplay, TRUE);
-
-    /* Select event types to watch */
-    XSelectInput(pDisplay, DefaultRootWindow(pDisplay), None);
-
-    /* Close our X display */
-    if (pDisplay) {
-        XCloseDisplay(pDisplay);
-    }
-#endif
-
-    /* global clipboard variable reset */
-    g_hwndClipboard = NULL;
-
-    return NULL;
-}
-
-/*
- * Create the Windows window that we use to receive Windows messages
- */
-
-static HWND
-winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow)
-{
-    WNDCLASSEX wc;
-    ClipboardWindowCreationParams cwcp;
-    HWND hwnd;
-
-    /* Setup our window class */
-    wc.cbSize = sizeof(WNDCLASSEX);
-    wc.style = CS_HREDRAW | CS_VREDRAW;
-    wc.lpfnWndProc = winClipboardWindowProc;
-    wc.cbClsExtra = 0;
-    wc.cbWndExtra = 0;
-    wc.hInstance = GetModuleHandle(NULL);
-    wc.hIcon = 0;
-    wc.hCursor = 0;
-    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
-    wc.lpszMenuName = NULL;
-    wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
-    wc.hIconSm = 0;
-    RegisterClassEx(&wc);
-
-    /* Information to be passed to WM_CREATE */
-    cwcp.pClipboardDisplay = pDisplay;
-    cwcp.iClipboardWindow = iWindow;
-
-    /* Create the window */
-    hwnd = CreateWindowExA(0,   /* Extended styles */
-                           WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
-                           WIN_CLIPBOARD_WINDOW_TITLE,  /* Window name */
-                           WS_OVERLAPPED,       /* Not visible anyway */
-                           CW_USEDEFAULT,       /* Horizontal position */
-                           CW_USEDEFAULT,       /* Vertical position */
-                           CW_USEDEFAULT,       /* Right edge */
-                           CW_USEDEFAULT,       /* Bottom edge */
-                           (HWND) NULL, /* No parent or owner window */
-                           (HMENU) NULL,        /* No menu */
-                           GetModuleHandle(NULL),       /* Instance handle */
-                           &cwcp);       /* Creation data */
-    assert(hwnd != NULL);
-
-    /* I'm not sure, but we may need to call this to start message processing */
-    ShowWindow(hwnd, SW_HIDE);
-
-    /* Similarly, we may need a call to this even though we don't paint */
-    UpdateWindow(hwnd);
-
-    return hwnd;
-}
-
-/*
- * winClipboardErrorHandler - Our application specific error handler
- */
-
-static int
-winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr)
-{
-    char pszErrorMsg[100];
-
-    XGetErrorText(pDisplay, pErr->error_code, pszErrorMsg, sizeof(pszErrorMsg));
-    ErrorF("winClipboardErrorHandler - ERROR: \n\t%s\n"
-           "\tSerial: %lu, Request Code: %d, Minor Code: %d\n",
-           pszErrorMsg, pErr->serial, pErr->request_code, pErr->minor_code);
-    return 0;
-}
-
-/*
- * winClipboardIOErrorHandler - Our application specific IO error handler
- */
-
-static int
-winClipboardIOErrorHandler(Display * pDisplay)
-{
-    ErrorF("winClipboardIOErrorHandler!\n");
-
-    if (pthread_equal(pthread_self(), g_winClipboardProcThread)) {
-        /* Restart at the main entry point */
-        longjmp(g_jmpEntry, WIN_JMP_ERROR_IO);
-    }
-
-    if (g_winClipboardOldIOErrorHandler)
-        g_winClipboardOldIOErrorHandler(pDisplay);
-
-    return 0;
-}
-
-void
-winClipboardWindowDestroy(void)
-{
-  if (g_hwndClipboard) {
-    SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
-  }
-}
-
-void
-winFixClipboardChain(void)
-{
-  if (g_hwndClipboard) {
-    PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
-  }
-}
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
deleted file mode 100644
index 459170f..0000000
--- a/hw/xwin/winclipboardwndproc.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *Copyright (C) Colin Harrison 2005-2008
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the copyright holder(s)
- *and author(s) shall not be used in advertising or otherwise to promote
- *the sale, use or other dealings in this Software without prior written
- *authorization from the copyright holder(s) and author(s).
- *
- * Authors:	Harold L Hunt II
- *              Colin Harrison
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include <sys/types.h>
-#include <sys/time.h>
-#include "winclipboard.h"
-#include "misc.h"
-
-/*
- * Constants
- */
-
-#define WIN_POLL_TIMEOUT	1
-
-
-/*
- * Process X events up to specified timeout
- */
-
-static int
-winProcessXEventsTimeout(HWND hwnd, int iWindow, Display * pDisplay,
-                         Bool fUseUnicode, int iTimeoutSec)
-{
-    int iConnNumber;
-    struct timeval tv;
-    int iReturn;
-    DWORD dwStopTime = GetTickCount() + iTimeoutSec * 1000;
-
-    winDebug("winProcessXEventsTimeout () - pumping X events for %d seconds\n",
-             iTimeoutSec);
-
-    /* Get our connection number */
-    iConnNumber = ConnectionNumber(pDisplay);
-
-    /* Loop for X events */
-    while (1) {
-        fd_set fdsRead;
-        long remainingTime;
-
-        /* We need to ensure that all pending events are processed */
-        XSync(pDisplay, FALSE);
-
-        /* Setup the file descriptor set */
-        FD_ZERO(&fdsRead);
-        FD_SET(iConnNumber, &fdsRead);
-
-        /* Adjust timeout */
-        remainingTime = dwStopTime - GetTickCount();
-        tv.tv_sec = remainingTime / 1000;
-        tv.tv_usec = (remainingTime % 1000) * 1000;
-        winDebug("winProcessXEventsTimeout () - %d milliseconds left\n",
-                 remainingTime);
-
-        /* Break out if no time left */
-        if (remainingTime <= 0)
-            return WIN_XEVENTS_SUCCESS;
-
-        /* Wait for an X event */
-        iReturn = select(iConnNumber + 1,       /* Highest fds number */
-                         &fdsRead,      /* Read mask */
-                         NULL,  /* No write mask */
-                         NULL,  /* No exception mask */
-                         &tv);  /* Timeout */
-        if (iReturn < 0) {
-            ErrorF("winProcessXEventsTimeout - Call to select () failed: %d.  "
-                   "Bailing.\n", iReturn);
-            break;
-        }
-
-        /* Branch on which descriptor became active */
-        if (FD_ISSET(iConnNumber, &fdsRead)) {
-            /* Process X events */
-            /* Exit when we see that server is shutting down */
-            iReturn = winClipboardFlushXEvents(hwnd,
-                                               iWindow, pDisplay, fUseUnicode);
-
-            winDebug
-                ("winProcessXEventsTimeout () - winClipboardFlushXEvents returned %d\n",
-                 iReturn);
-
-            if (WIN_XEVENTS_NOTIFY == iReturn) {
-                /* Bail out if notify processed */
-                return iReturn;
-            }
-        }
-        else {
-            winDebug("winProcessXEventsTimeout - Spurious wake\n");
-        }
-    }
-
-    return WIN_XEVENTS_SUCCESS;
-}
-
-/*
- * Process a given Windows message
- */
-
-LRESULT CALLBACK
-winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-    static HWND s_hwndNextViewer;
-    static Bool s_fCBCInitialized;
-    static Display *pDisplay;
-    static Window iWindow;
-
-    /* Branch on message type */
-    switch (message) {
-    case WM_DESTROY:
-    {
-        winDebug("winClipboardWindowProc - WM_DESTROY\n");
-
-        /* Remove ourselves from the clipboard chain */
-        ChangeClipboardChain(hwnd, s_hwndNextViewer);
-
-        s_hwndNextViewer = NULL;
-
-        PostQuitMessage(0);
-    }
-        return 0;
-
-    case WM_CREATE:
-    {
-        HWND first, next;
-        DWORD error_code = 0;
-        ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
-
-        winDebug("winClipboardWindowProc - WM_CREATE\n");
-
-        pDisplay = cwcp->pClipboardDisplay;
-        iWindow = cwcp->iClipboardWindow;
-
-        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
-        if (first == hwnd)
-            return 0;           /* Make sure it's not us! */
-        /* Add ourselves to the clipboard viewer chain */
-        next = SetClipboardViewer(hwnd);
-        error_code = GetLastError();
-        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
-            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
-        else
-            s_fCBCInitialized = FALSE;
-    }
-        return 0;
-
-    case WM_CHANGECBCHAIN:
-    {
-        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
-                 "lParam(%x) s_hwndNextViewer(%x)\n",
-                 wParam, lParam, s_hwndNextViewer);
-
-        if ((HWND) wParam == s_hwndNextViewer) {
-            s_hwndNextViewer = (HWND) lParam;
-            if (s_hwndNextViewer == hwnd) {
-                s_hwndNextViewer = NULL;
-                winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
-                              "attempted to set next window to ourselves.");
-            }
-        }
-        else if (s_hwndNextViewer)
-            SendMessage(s_hwndNextViewer, message, wParam, lParam);
-
-    }
-        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
-        return 0;
-
-    case WM_WM_REINIT:
-    {
-        /* Ensure that we're in the clipboard chain.  Some apps,
-         * WinXP's remote desktop for one, don't play nice with the
-         * chain.  This message is called whenever we receive a
-         * WM_ACTIVATEAPP message to ensure that we continue to
-         * receive clipboard messages.
-         *
-         * It might be possible to detect if we're still in the chain
-         * by calling SendMessage (GetClipboardViewer(),
-         * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
-         * WM_DRAWCLIPBOARD message.  That, however, might be more
-         * expensive than just putting ourselves back into the chain.
-         */
-
-        HWND first, next;
-        DWORD error_code = 0;
-
-        winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");
-
-        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
-        if (first == hwnd)
-            return 0;           /* Make sure it's not us! */
-        winDebug("  WM_WM_REINIT: Replacing us(%x) with %x at head "
-                 "of chain\n", hwnd, s_hwndNextViewer);
-        s_fCBCInitialized = FALSE;
-        ChangeClipboardChain(hwnd, s_hwndNextViewer);
-        s_hwndNextViewer = NULL;
-        s_fCBCInitialized = FALSE;
-        winDebug("  WM_WM_REINIT: Putting us back at head of chain.\n");
-        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
-        if (first == hwnd)
-            return 0;           /* Make sure it's not us! */
-        next = SetClipboardViewer(hwnd);
-        error_code = GetLastError();
-        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
-            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
-        else
-            s_fCBCInitialized = FALSE;
-    }
-        winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
-        return 0;
-
-    case WM_DRAWCLIPBOARD:
-    {
-        static Atom atomClipboard;
-        static int generation;
-        static Bool s_fProcessingDrawClipboard = FALSE;
-        int iReturn;
-
-        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
-
-        if (generation != serverGeneration) {
-            generation = serverGeneration;
-            atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
-        }
-
-        /*
-         * We've occasionally seen a loop in the clipboard chain.
-         * Try and fix it on the first hint of recursion.
-         */
-        if (!s_fProcessingDrawClipboard) {
-            s_fProcessingDrawClipboard = TRUE;
-        }
-        else {
-            /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
-            s_fCBCInitialized = FALSE;
-            ChangeClipboardChain(hwnd, s_hwndNextViewer);
-            winFixClipboardChain();
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Nested calls detected.  Re-initing.\n");
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
-            s_fProcessingDrawClipboard = FALSE;
-            return 0;
-        }
-
-        /* Bail on first message */
-        if (!s_fCBCInitialized) {
-            s_fCBCInitialized = TRUE;
-            s_fProcessingDrawClipboard = FALSE;
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
-            return 0;
-        }
-
-        /*
-         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
-         * because some applications deal with the clipboard in a manner
-         * that causes the clipboard owner to be NULL when they are in
-         * fact taking ownership.  One example of this is the Win32
-         * native compile of emacs.
-         */
-
-        /* Bail when we still own the clipboard */
-        if (hwnd == GetClipboardOwner()) {
-
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                     "We own the clipboard, returning.\n");
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
-            s_fProcessingDrawClipboard = FALSE;
-            if (s_hwndNextViewer)
-                SendMessage(s_hwndNextViewer, message, wParam, lParam);
-            return 0;
-        }
-
-        /*
-         * Do not take ownership of the X11 selections when something
-         * other than CF_TEXT or CF_UNICODETEXT has been copied
-         * into the Win32 clipboard.
-         */
-        if (!IsClipboardFormatAvailable(CF_TEXT)
-            && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
-
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                     "Clipboard does not contain CF_TEXT nor "
-                     "CF_UNICODETEXT.\n");
-
-            /*
-             * We need to make sure that the X Server has processed
-             * previous XSetSelectionOwner messages.
-             */
-            XSync(pDisplay, FALSE);
-
-            winDebug("winClipboardWindowProc - XSync done.\n");
-
-            /* Release PRIMARY selection if owned */
-            iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
-            if (iReturn == iWindow) {
-                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                         "PRIMARY selection is owned by us.\n");
-                XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
-            }
-            else if (BadWindow == iReturn || BadAtom == iReturn)
-                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                              "XGetSelection failed for PRIMARY: %d\n",
-                              iReturn);
-
-            /* Release CLIPBOARD selection if owned */
-            iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
-            if (iReturn == iWindow) {
-                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                         "CLIPBOARD selection is owned by us.\n");
-                XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
-            }
-            else if (BadWindow == iReturn || BadAtom == iReturn)
-                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                              "XGetSelection failed for CLIPBOARD: %d\n",
-                              iReturn);
-
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
-            s_fProcessingDrawClipboard = FALSE;
-            if (s_hwndNextViewer)
-                SendMessage(s_hwndNextViewer, message, wParam, lParam);
-            return 0;
-        }
-
-        /* Reassert ownership of PRIMARY */
-        iReturn = XSetSelectionOwner(pDisplay,
-                                     XA_PRIMARY, iWindow, CurrentTime);
-        if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Could not reassert ownership of PRIMARY\n");
-        }
-        else {
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                     "Reasserted ownership of PRIMARY\n");
-        }
-
-        /* Reassert ownership of the CLIPBOARD */
-        iReturn = XSetSelectionOwner(pDisplay,
-                                     atomClipboard, iWindow, CurrentTime);
-
-        if (iReturn == BadAtom || iReturn == BadWindow ||
-            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                          "Could not reassert ownership of CLIPBOARD\n");
-        }
-        else {
-            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
-                     "Reasserted ownership of CLIPBOARD\n");
-        }
-
-        /* Flush the pending SetSelectionOwner event now */
-        XFlush(pDisplay);
-
-        s_fProcessingDrawClipboard = FALSE;
-    }
-        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
-        /* Pass the message on the next window in the clipboard viewer chain */
-        if (s_hwndNextViewer)
-            SendMessage(s_hwndNextViewer, message, wParam, lParam);
-        return 0;
-
-    case WM_DESTROYCLIPBOARD:
-        /*
-         * NOTE: Intentionally do nothing.
-         * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
-         * above.  We only process this message to conform to the specs
-         * for delayed clipboard rendering in Win32.  You might think
-         * that we need to release ownership of the X11 selections, but
-         * we do not, because a WM_DRAWCLIPBOARD message will closely
-         * follow this message and reassert ownership of the X11
-         * selections, handling the issue for us.
-         */
-        winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
-        return 0;
-
-    case WM_RENDERFORMAT:
-    case WM_RENDERALLFORMATS:
-    {
-        int iReturn;
-        Bool fConvertToUnicode;
-
-        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
-
-        /* Flag whether to convert to Unicode or not */
-        if (message == WM_RENDERALLFORMATS)
-            fConvertToUnicode = FALSE;
-        else
-            fConvertToUnicode = (CF_UNICODETEXT == wParam);
-
-        /* Request the selection contents */
-        iReturn = XConvertSelection(pDisplay,
-                                    winClipboardGetLastOwnedSelectionAtom(),
-                                    XInternAtom(pDisplay,
-                                                "COMPOUND_TEXT", False),
-                                    XInternAtom(pDisplay,
-                                                "CYGX_CUT_BUFFER", False),
-                                    iWindow, CurrentTime);
-        if (iReturn == BadAtom || iReturn == BadWindow) {
-            winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
-                          "XConvertSelection () failed\n");
-            break;
-        }
-
-        /* Special handling for WM_RENDERALLFORMATS */
-        if (message == WM_RENDERALLFORMATS) {
-            /* We must open and empty the clipboard */
-
-            /* Close clipboard if we have it open already */
-            if (GetOpenClipboardWindow() == hwnd) {
-                CloseClipboard();
-            }
-
-            if (!OpenClipboard(hwnd)) {
-                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
-                              "OpenClipboard () failed: %08x\n",
-                              GetLastError());
-                break;
-            }
-
-            if (!EmptyClipboard()) {
-                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
-                              "EmptyClipboard () failed: %08x\n",
-                              GetLastError());
-                break;
-            }
-        }
-
-        /* Process the SelectionNotify event */
-        iReturn = winProcessXEventsTimeout(hwnd,
-                                           iWindow,
-                                           pDisplay,
-                                           fConvertToUnicode, WIN_POLL_TIMEOUT);
-
-        /*
-         * The last call to winProcessXEventsTimeout
-         * from above had better have seen a notify event, or else we
-         * are dealing with a buggy or old X11 app.  In these cases we
-         * have to paste some fake data to the Win32 clipboard to
-         * satisfy the requirement that we write something to it.
-         */
-        if (WIN_XEVENTS_NOTIFY != iReturn) {
-            /* Paste no data, to satisfy required call to SetClipboardData */
-            SetClipboardData(CF_UNICODETEXT, NULL);
-            SetClipboardData(CF_TEXT, NULL);
-
-            ErrorF
-                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n");
-        }
-
-        /* Special handling for WM_RENDERALLFORMATS */
-        if (message == WM_RENDERALLFORMATS) {
-            /* We must close the clipboard */
-
-            if (!CloseClipboard()) {
-                winErrorFVerb(1,
-                              "winClipboardWindowProc - WM_RENDERALLFORMATS - "
-                              "CloseClipboard () failed: %08x\n",
-                              GetLastError());
-                break;
-            }
-        }
-
-        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
-        return 0;
-    }
-    }
-
-    /* Let Windows perform default processing for unhandled messages */
-    return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-/*
- * Process any pending Windows messages
- */
-
-BOOL
-winClipboardFlushWindowsMessageQueue(HWND hwnd)
-{
-    MSG msg;
-
-    /* Flush the messaging window queue */
-    /* NOTE: Do not pass the hwnd of our messaging window to PeekMessage,
-     * as this will filter out many non-window-specific messages that
-     * are sent to our thread, such as WM_QUIT.
-     */
-    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-        /* Dispatch the message if not WM_QUIT */
-        if (msg.message == WM_QUIT)
-            return FALSE;
-        else
-            DispatchMessage(&msg);
-    }
-
-    return TRUE;
-}
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboardxevents.c
deleted file mode 100644
index a792467..0000000
--- a/hw/xwin/winclipboardxevents.c
+++ /dev/null
@@ -1,862 +0,0 @@
-/*
- *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
- *Copyright (C) Colin Harrison 2005-2008
- *
- *Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- *"Software"), to deal in the Software without restriction, including
- *without limitation the rights to use, copy, modify, merge, publish,
- *distribute, sublicense, and/or sell copies of the Software, and to
- *permit persons to whom the Software is furnished to do so, subject to
- *the following conditions:
- *
- *The above copyright notice and this permission notice shall be
- *included in all copies or substantial portions of the Software.
- *
- *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
- *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *Except as contained in this notice, the name of the copyright holder(s)
- *and author(s) shall not be used in advertising or otherwise to promote
- *the sale, use or other dealings in this Software without prior written
- *authorization from the copyright holder(s) and author(s).
- *
- * Authors:	Harold L Hunt II
- *              Colin Harrison
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-
-#include "winclipboard.h"
-#include "misc.h"
-#include <X11/extensions/Xfixes.h>
-
-/*
- * Constants
- */
-
-#define CLIP_NUM_SELECTIONS		2
-#define CLIP_OWN_NONE     		-1
-#define CLIP_OWN_PRIMARY		0
-#define CLIP_OWN_CLIPBOARD		1
-
-/*
- * Global variables
- */
-
-extern int xfixes_event_base;
-
-/*
- * Local variables
- */
-
-static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
-static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
-    { "PRIMARY", "CLIPBOARD" };
-
-static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
-static Atom atomClipboard = None;
-
-static void
-MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
-{
-    /* Look for owned -> not owned transition */
-    if (None == e->owner && None != s_iOwners[i]) {
-        unsigned int other_index;
-
-        winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
-                 szSelectionNames[i]);
-
-        /* If this selection is not owned, the other monitored selection must be the most
-           recently owned, if it is owned at all */
-        if (i == CLIP_OWN_PRIMARY)
-            other_index = CLIP_OWN_CLIPBOARD;
-        if (i == CLIP_OWN_CLIPBOARD)
-            other_index = CLIP_OWN_PRIMARY;
-        if (None != s_iOwners[other_index])
-            lastOwnedSelectionIndex = other_index;
-        else
-            lastOwnedSelectionIndex = CLIP_OWN_NONE;
-    }
-
-    /* Save last owned selection */
-    if (None != e->owner) {
-        lastOwnedSelectionIndex = i;
-    }
-
-    /* Save new selection owner or None */
-    s_iOwners[i] = e->owner;
-    winDebug("MonitorSelection - %s - Now owned by XID %x\n",
-             szSelectionNames[i], e->owner);
-}
-
-Atom
-winClipboardGetLastOwnedSelectionAtom(void)
-{
-    if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
-        return None;
-
-    if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
-        return XA_PRIMARY;
-
-    if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
-        return atomClipboard;
-
-    return None;
-}
-
-
-void
-winClipboardInitMonitoredSelections(void)
-{
-    /* Initialize static variables */
-    for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
-      s_iOwners[i] = None;
-
-    lastOwnedSelectionIndex = CLIP_OWN_NONE;
-}
-
-/*
- * Process any pending X events
- */
-
-int
-winClipboardFlushXEvents(HWND hwnd,
-                         int iWindow, Display * pDisplay, Bool fUseUnicode)
-{
-    static Atom atomLocalProperty;
-    static Atom atomCompoundText;
-    static Atom atomUTF8String;
-    static Atom atomTargets;
-    static int generation;
-
-    if (generation != serverGeneration) {
-        generation = serverGeneration;
-        atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
-        atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
-        atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
-        atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
-        atomTargets = XInternAtom(pDisplay, "TARGETS", False);
-    }
-
-    /* Process all pending events */
-    while (XPending(pDisplay)) {
-        XTextProperty xtpText = { 0 };
-        XEvent event;
-        XSelectionEvent eventSelection;
-        unsigned long ulReturnBytesLeft;
-        char *pszReturnData = NULL;
-        char *pszGlobalData = NULL;
-        int iReturn;
-        HGLOBAL hGlobal = NULL;
-        XICCEncodingStyle xiccesStyle;
-        int iConvertDataLen = 0;
-        char *pszConvertData = NULL;
-        char *pszTextList[2] = { NULL };
-        int iCount;
-        char **ppszTextList = NULL;
-        wchar_t *pwszUnicodeStr = NULL;
-        int iUnicodeLen = 0;
-        int iReturnDataLen = 0;
-        Bool fAbort = FALSE;
-        Bool fCloseClipboard = FALSE;
-        Bool fSetClipboardData = TRUE;
-
-        /* Get the next event - will not block because one is ready */
-        XNextEvent(pDisplay, &event);
-
-        /* Branch on the event type */
-        switch (event.type) {
-            /*
-             * SelectionRequest
-             */
-
-        case SelectionRequest:
-        {
-            char *pszAtomName = NULL;
-
-            winDebug("SelectionRequest - target %d\n",
-                     event.xselectionrequest.target);
-
-            pszAtomName = XGetAtomName(pDisplay,
-                                       event.xselectionrequest.target);
-            winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
-            XFree(pszAtomName);
-            pszAtomName = NULL;
-        }
-
-            /* Abort if invalid target type */
-            if (event.xselectionrequest.target != XA_STRING
-                && event.xselectionrequest.target != atomUTF8String
-                && event.xselectionrequest.target != atomCompoundText
-                && event.xselectionrequest.target != atomTargets) {
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
-            /* Handle targets type of request */
-            if (event.xselectionrequest.target == atomTargets) {
-                Atom atomTargetArr[] = { atomTargets,
-                    atomCompoundText,
-                    atomUTF8String,
-                    XA_STRING
-                };
-
-                /* Try to change the property */
-                iReturn = XChangeProperty(pDisplay,
-                                          event.xselectionrequest.requestor,
-                                          event.xselectionrequest.property,
-                                          XA_ATOM,
-                                          32,
-                                          PropModeReplace,
-                                          (unsigned char *) atomTargetArr,
-                                          (sizeof(atomTargetArr)
-                                           / sizeof(atomTargetArr[0])));
-                if (iReturn == BadAlloc
-                    || iReturn == BadAtom
-                    || iReturn == BadMatch
-                    || iReturn == BadValue || iReturn == BadWindow) {
-                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                           "XChangeProperty failed: %d\n", iReturn);
-                }
-
-                /* Setup selection notify xevent */
-                eventSelection.type = SelectionNotify;
-                eventSelection.send_event = True;
-                eventSelection.display = pDisplay;
-                eventSelection.requestor = event.xselectionrequest.requestor;
-                eventSelection.selection = event.xselectionrequest.selection;
-                eventSelection.target = event.xselectionrequest.target;
-                eventSelection.property = event.xselectionrequest.property;
-                eventSelection.time = event.xselectionrequest.time;
-
-                /*
-                 * Notify the requesting window that
-                 * the operation has completed
-                 */
-                iReturn = XSendEvent(pDisplay,
-                                     eventSelection.requestor,
-                                     False, 0L, (XEvent *) &eventSelection);
-                if (iReturn == BadValue || iReturn == BadWindow) {
-                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                           "XSendEvent () failed\n");
-                }
-                break;
-            }
-
-            /* Close clipboard if we have it open already */
-            if (GetOpenClipboardWindow() == hwnd) {
-                CloseClipboard();
-            }
-
-            /* Access the clipboard */
-            if (!OpenClipboard(hwnd)) {
-                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                       "OpenClipboard () failed: %08lx\n", GetLastError());
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
-            /* Indicate that clipboard was opened */
-            fCloseClipboard = TRUE;
-
-            /* Check that clipboard format is available */
-            if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
-                static int count;       /* Hack to stop acroread spamming the log */
-                static HWND lasthwnd;   /* I've not seen any other client get here repeatedly? */
-
-                if (hwnd != lasthwnd)
-                    count = 0;
-                count++;
-                if (count < 6)
-                    ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
-                           "available from Win32 clipboard.  Aborting %d.\n",
-                           count);
-                lasthwnd = hwnd;
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-            else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
-                ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
-                       "available from Win32 clipboard.  Aborting.\n");
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
-            /* Setup the string style */
-            if (event.xselectionrequest.target == XA_STRING)
-                xiccesStyle = XStringStyle;
-#ifdef X_HAVE_UTF8_STRING
-            else if (event.xselectionrequest.target == atomUTF8String)
-                xiccesStyle = XUTF8StringStyle;
-#endif
-            else if (event.xselectionrequest.target == atomCompoundText)
-                xiccesStyle = XCompoundTextStyle;
-            else
-                xiccesStyle = XStringStyle;
-
-            /* Get a pointer to the clipboard text, in desired format */
-            if (fUseUnicode) {
-                /* Retrieve clipboard data */
-                hGlobal = GetClipboardData(CF_UNICODETEXT);
-            }
-            else {
-                /* Retrieve clipboard data */
-                hGlobal = GetClipboardData(CF_TEXT);
-            }
-            if (!hGlobal) {
-                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                       "GetClipboardData () failed: %08lx\n", GetLastError());
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-            pszGlobalData = (char *) GlobalLock(hGlobal);
-
-            /* Convert the Unicode string to UTF8 (MBCS) */
-            if (fUseUnicode) {
-                iConvertDataLen = WideCharToMultiByte(CP_UTF8,
-                                                      0,
-                                                      (LPCWSTR) pszGlobalData,
-                                                      -1, NULL, 0, NULL, NULL);
-                /* NOTE: iConvertDataLen includes space for null terminator */
-                pszConvertData = malloc(iConvertDataLen);
-                WideCharToMultiByte(CP_UTF8,
-                                    0,
-                                    (LPCWSTR) pszGlobalData,
-                                    -1,
-                                    pszConvertData,
-                                    iConvertDataLen, NULL, NULL);
-            }
-            else {
-                pszConvertData = strdup(pszGlobalData);
-                iConvertDataLen = strlen(pszConvertData) + 1;
-            }
-
-            /* Convert DOS string to UNIX string */
-            winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));
-
-            /* Setup our text list */
-            pszTextList[0] = pszConvertData;
-            pszTextList[1] = NULL;
-
-            /* Initialize the text property */
-            xtpText.value = NULL;
-            xtpText.nitems = 0;
-
-            /* Create the text property from the text list */
-            if (fUseUnicode) {
-#ifdef X_HAVE_UTF8_STRING
-                iReturn = Xutf8TextListToTextProperty(pDisplay,
-                                                      pszTextList,
-                                                      1, xiccesStyle, &xtpText);
-#endif
-            }
-            else {
-                iReturn = XmbTextListToTextProperty(pDisplay,
-                                                    pszTextList,
-                                                    1, xiccesStyle, &xtpText);
-            }
-            if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
-                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                       "X*TextListToTextProperty failed: %d\n", iReturn);
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
-            /* Free the converted string */
-            free(pszConvertData);
-            pszConvertData = NULL;
-
-            /* Copy the clipboard text to the requesting window */
-            iReturn = XChangeProperty(pDisplay,
-                                      event.xselectionrequest.requestor,
-                                      event.xselectionrequest.property,
-                                      event.xselectionrequest.target,
-                                      8,
-                                      PropModeReplace,
-                                      xtpText.value, xtpText.nitems);
-            if (iReturn == BadAlloc || iReturn == BadAtom
-                || iReturn == BadMatch || iReturn == BadValue
-                || iReturn == BadWindow) {
-                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                       "XChangeProperty failed: %d\n", iReturn);
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
-            /* Release the clipboard data */
-            GlobalUnlock(hGlobal);
-            pszGlobalData = NULL;
-            fCloseClipboard = FALSE;
-            CloseClipboard();
-
-            /* Clean up */
-            XFree(xtpText.value);
-            xtpText.value = NULL;
-            xtpText.nitems = 0;
-
-            /* Setup selection notify event */
-            eventSelection.type = SelectionNotify;
-            eventSelection.send_event = True;
-            eventSelection.display = pDisplay;
-            eventSelection.requestor = event.xselectionrequest.requestor;
-            eventSelection.selection = event.xselectionrequest.selection;
-            eventSelection.target = event.xselectionrequest.target;
-            eventSelection.property = event.xselectionrequest.property;
-            eventSelection.time = event.xselectionrequest.time;
-
-            /* Notify the requesting window that the operation has completed */
-            iReturn = XSendEvent(pDisplay,
-                                 eventSelection.requestor,
-                                 False, 0L, (XEvent *) &eventSelection);
-            if (iReturn == BadValue || iReturn == BadWindow) {
-                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                       "XSendEvent () failed\n");
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionRequest_Done;
-            }
-
- winClipboardFlushXEvents_SelectionRequest_Done:
-            /* Free allocated resources */
-            if (xtpText.value) {
-                XFree(xtpText.value);
-                xtpText.value = NULL;
-                xtpText.nitems = 0;
-            }
-            free(pszConvertData);
-            if (hGlobal && pszGlobalData)
-                GlobalUnlock(hGlobal);
-
-            /*
-             * Send a SelectionNotify event to the requesting
-             * client when we abort.
-             */
-            if (fAbort) {
-                /* Setup selection notify event */
-                eventSelection.type = SelectionNotify;
-                eventSelection.send_event = True;
-                eventSelection.display = pDisplay;
-                eventSelection.requestor = event.xselectionrequest.requestor;
-                eventSelection.selection = event.xselectionrequest.selection;
-                eventSelection.target = event.xselectionrequest.target;
-                eventSelection.property = None;
-                eventSelection.time = event.xselectionrequest.time;
-
-                /* Notify the requesting window that the operation is complete */
-                iReturn = XSendEvent(pDisplay,
-                                     eventSelection.requestor,
-                                     False, 0L, (XEvent *) &eventSelection);
-                if (iReturn == BadValue || iReturn == BadWindow) {
-                    /*
-                     * Should not be a problem if XSendEvent fails because
-                     * the client may simply have exited.
-                     */
-                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
-                           "XSendEvent () failed for abort event.\n");
-                }
-            }
-
-            /* Close clipboard if it was opened */
-            if (fCloseClipboard) {
-                fCloseClipboard = FALSE;
-                CloseClipboard();
-            }
-            break;
-
-            /*
-             * SelectionNotify
-             */
-
-        case SelectionNotify:
-
-            winDebug("winClipboardFlushXEvents - SelectionNotify\n");
-            {
-                char *pszAtomName;
-
-                pszAtomName = XGetAtomName(pDisplay,
-                                           event.xselection.selection);
-
-                winDebug
-                    ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
-                     pszAtomName);
-                XFree(pszAtomName);
-            }
-
-            /*
-             * Request conversion of UTF8 and CompoundText targets.
-             */
-            if (event.xselection.property == None) {
-                if (event.xselection.target == XA_STRING) {
-                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
-                             "XA_STRING\n");
-
-                    return WIN_XEVENTS_CONVERT;
-                }
-                else if (event.xselection.target == atomUTF8String) {
-                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
-                             "Requesting conversion of UTF8 target.\n");
-
-                    XConvertSelection(pDisplay,
-                                      event.xselection.selection,
-                                      XA_STRING,
-                                      atomLocalProperty, iWindow, CurrentTime);
-
-                    /* Process the ConvertSelection event */
-                    XFlush(pDisplay);
-                    return WIN_XEVENTS_CONVERT;
-                }
-#ifdef X_HAVE_UTF8_STRING
-                else if (event.xselection.target == atomCompoundText) {
-                    winDebug("winClipboardFlushXEvents - SelectionNotify - "
-                             "Requesting conversion of CompoundText target.\n");
-
-                    XConvertSelection(pDisplay,
-                                      event.xselection.selection,
-                                      atomUTF8String,
-                                      atomLocalProperty, iWindow, CurrentTime);
-
-                    /* Process the ConvertSelection event */
-                    XFlush(pDisplay);
-                    return WIN_XEVENTS_CONVERT;
-                }
-#endif
-                else {
-                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
-                           "Unknown format.  Cannot request conversion, "
-                           "aborting.\n");
-                    break;
-                }
-            }
-
-            /* Retrieve the size of the stored data */
-            iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0,    /* Don't get data, just size */
-                                         False,
-                                         AnyPropertyType,
-                                         &xtpText.encoding,
-                                         &xtpText.format,
-                                         &xtpText.nitems,
-                                         &ulReturnBytesLeft, &xtpText.value);
-            if (iReturn != Success) {
-                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
-                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
-                break;
-            }
-
-            winDebug("SelectionNotify - returned data %d left %d\n",
-                     xtpText.nitems, ulReturnBytesLeft);
-
-            /* Request the selection data */
-            iReturn = XGetWindowProperty(pDisplay,
-                                         iWindow,
-                                         atomLocalProperty,
-                                         0,
-                                         ulReturnBytesLeft,
-                                         False,
-                                         AnyPropertyType,
-                                         &xtpText.encoding,
-                                         &xtpText.format,
-                                         &xtpText.nitems,
-                                         &ulReturnBytesLeft, &xtpText.value);
-            if (iReturn != Success) {
-                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
-                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
-                break;
-            }
-
-            {
-                char *pszAtomName = NULL;
-
-                winDebug("SelectionNotify - returned data %d left %d\n",
-                         xtpText.nitems, ulReturnBytesLeft);
-                pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
-                winDebug("Notify atom name %s\n", pszAtomName);
-                XFree(pszAtomName);
-                pszAtomName = NULL;
-            }
-
-            if (fUseUnicode) {
-#ifdef X_HAVE_UTF8_STRING
-                /* Convert the text property to a text list */
-                iReturn = Xutf8TextPropertyToTextList(pDisplay,
-                                                      &xtpText,
-                                                      &ppszTextList, &iCount);
-#endif
-            }
-            else {
-                iReturn = XmbTextPropertyToTextList(pDisplay,
-                                                    &xtpText,
-                                                    &ppszTextList, &iCount);
-            }
-            if (iReturn == Success || iReturn > 0) {
-                /* Conversion succeeded or some unconvertible characters */
-                if (ppszTextList != NULL) {
-                    int i;
-
-                    iReturnDataLen = 0;
-                    for (i = 0; i < iCount; i++) {
-                        iReturnDataLen += strlen(ppszTextList[i]);
-                    }
-                    pszReturnData = malloc(iReturnDataLen + 1);
-                    pszReturnData[0] = '\0';
-                    for (i = 0; i < iCount; i++) {
-                        strcat(pszReturnData, ppszTextList[i]);
-                    }
-                }
-                else {
-                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
-                           "X*TextPropertyToTextList list_return is NULL.\n");
-                    pszReturnData = malloc(1);
-                    pszReturnData[0] = '\0';
-                }
-            }
-            else {
-                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
-                       "X*TextPropertyToTextList returned: ");
-                switch (iReturn) {
-                case XNoMemory:
-                    ErrorF("XNoMemory\n");
-                    break;
-                case XLocaleNotSupported:
-                    ErrorF("XLocaleNotSupported\n");
-                    break;
-                case XConverterNotFound:
-                    ErrorF("XConverterNotFound\n");
-                    break;
-                default:
-                    ErrorF("%d\n", iReturn);
-                    break;
-                }
-                pszReturnData = malloc(1);
-                pszReturnData[0] = '\0';
-            }
-
-            /* Free the data returned from XGetWindowProperty */
-            if (ppszTextList)
-                XFreeStringList(ppszTextList);
-            ppszTextList = NULL;
-            XFree(xtpText.value);
-            xtpText.value = NULL;
-            xtpText.nitems = 0;
-
-            /* Convert the X clipboard string to DOS format */
-            winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
-
-            if (fUseUnicode) {
-                /* Find out how much space needed to convert MBCS to Unicode */
-                iUnicodeLen = MultiByteToWideChar(CP_UTF8,
-                                                  0,
-                                                  pszReturnData, -1, NULL, 0);
-
-                /* Allocate memory for the Unicode string */
-                pwszUnicodeStr = malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
-                if (!pwszUnicodeStr) {
-                    ErrorF("winClipboardFlushXEvents - SelectionNotify "
-                           "malloc failed for pwszUnicodeStr, aborting.\n");
-
-                    /* Abort */
-                    fAbort = TRUE;
-                    goto winClipboardFlushXEvents_SelectionNotify_Done;
-                }
-
-                /* Do the actual conversion */
-                MultiByteToWideChar(CP_UTF8,
-                                    0,
-                                    pszReturnData,
-                                    -1, pwszUnicodeStr, iUnicodeLen);
-
-                /* Allocate global memory for the X clipboard data */
-                hGlobal = GlobalAlloc(GMEM_MOVEABLE,
-                                      sizeof(wchar_t) * (iUnicodeLen + 1));
-            }
-            else {
-                pszConvertData = strdup(pszReturnData);
-                iConvertDataLen = strlen(pszConvertData) + 1;
-
-                /* Allocate global memory for the X clipboard data */
-                hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
-            }
-
-            free(pszReturnData);
-
-            /* Check that global memory was allocated */
-            if (!hGlobal) {
-                ErrorF("winClipboardFlushXEvents - SelectionNotify "
-                       "GlobalAlloc failed, aborting: %ld\n", GetLastError());
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionNotify_Done;
-            }
-
-            /* Obtain a pointer to the global memory */
-            pszGlobalData = GlobalLock(hGlobal);
-            if (pszGlobalData == NULL) {
-                ErrorF("winClipboardFlushXEvents - Could not lock global "
-                       "memory for clipboard transfer\n");
-
-                /* Abort */
-                fAbort = TRUE;
-                goto winClipboardFlushXEvents_SelectionNotify_Done;
-            }
-
-            /* Copy the returned string into the global memory */
-            if (fUseUnicode) {
-                memcpy(pszGlobalData,
-                       pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
-                free(pwszUnicodeStr);
-                pwszUnicodeStr = NULL;
-            }
-            else {
-                strcpy(pszGlobalData, pszConvertData);
-                free(pszConvertData);
-                pszConvertData = NULL;
-            }
-
-            /* Release the pointer to the global memory */
-            GlobalUnlock(hGlobal);
-            pszGlobalData = NULL;
-
-            /* Push the selection data to the Windows clipboard */
-            if (fUseUnicode)
-                SetClipboardData(CF_UNICODETEXT, hGlobal);
-            else
-                SetClipboardData(CF_TEXT, hGlobal);
-
-            /* Flag that SetClipboardData has been called */
-            fSetClipboardData = FALSE;
-
-            /*
-             * NOTE: Do not try to free pszGlobalData, it is owned by
-             * Windows after the call to SetClipboardData ().
-             */
-
- winClipboardFlushXEvents_SelectionNotify_Done:
-            /* Free allocated resources */
-            if (ppszTextList)
-                XFreeStringList(ppszTextList);
-            if (xtpText.value) {
-                XFree(xtpText.value);
-                xtpText.value = NULL;
-                xtpText.nitems = 0;
-            }
-            free(pszConvertData);
-            free(pwszUnicodeStr);
-            if (hGlobal && pszGlobalData)
-                GlobalUnlock(hGlobal);
-            if (fSetClipboardData) {
-                SetClipboardData(CF_UNICODETEXT, NULL);
-                SetClipboardData(CF_TEXT, NULL);
-            }
-            return WIN_XEVENTS_NOTIFY;
-
-        case SelectionClear:
-            winDebug("SelectionClear - doing nothing\n");
-            break;
-
-        case PropertyNotify:
-            break;
-
-        case MappingNotify:
-            break;
-
-        default:
-            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
-                XFixesSelectionNotifyEvent *e =
-                    (XFixesSelectionNotifyEvent *) & event;
-
-                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
-
-                /* Save selection owners for monitored selections, ignore other selections */
-                if (e->selection == XA_PRIMARY) {
-                    MonitorSelection(e, CLIP_OWN_PRIMARY);
-                }
-                else if (e->selection == atomClipboard) {
-                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
-                }
-                else
-                    break;
-
-                /* Selection is being disowned */
-                if (e->owner == None) {
-                    winDebug
-                        ("winClipboardFlushXEvents - No window, returning.\n");
-                    break;
-                }
-
-                /*
-                   XXX: there are all kinds of wacky edge cases we might need here:
-                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
-                   - root window is taking ownership?
-                 */
-
-                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
-                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
-                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
-                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
-                    break;
-                }
-
-                /* Close clipboard if we have it open already (possible? correct??) */
-                if (GetOpenClipboardWindow() == hwnd) {
-                    CloseClipboard();
-                }
-
-                /* Access the Windows clipboard */
-                if (!OpenClipboard(hwnd)) {
-                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
-                           (int) GetLastError());
-                    break;
-                }
-
-                /* Take ownership of the Windows clipboard */
-                if (!EmptyClipboard()) {
-                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
-                           (int) GetLastError());
-                    break;
-                }
-
-                /* Advertise regular text and unicode */
-                SetClipboardData(CF_UNICODETEXT, NULL);
-                SetClipboardData(CF_TEXT, NULL);
-
-                /* Release the clipboard */
-                if (!CloseClipboard()) {
-                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
-                           (int) GetLastError());
-                    break;
-                }
-            }
-            /* XFixesSelectionWindowDestroyNotifyMask */
-            /* XFixesSelectionClientCloseNotifyMask */
-            else {
-                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
-                       event.type);
-            }
-            break;
-        }
-    }
-
-    return WIN_XEVENTS_SUCCESS;
-}
commit e965001a732a6b573c374f6a3503e172df01e8ec
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 13:18:16 2013 +0100

    hw/xwin: Make g_hwndClipboard static
    
    Move winFixClipboardChain() into winclipboardthread.c
    Add winCLipboardWindowDestroy() function to access it for WM_DESTROY
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index fa32c62..41c0a53 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -97,6 +97,9 @@ void
 
 void *winClipboardProc(char *szDisplay);
 
+void
+winClipboardWindowDestroy(void);
+
 /*
  * winclipboardwndproc.c
  */
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 335e379..d16c121 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -49,7 +49,6 @@ extern void winSetAuthorization(void);
  */
 
 extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
 extern Bool g_fClipboardStarted;
 
 /*
@@ -135,12 +134,7 @@ winClipboardShutdown(void)
   /* Close down clipboard resources */
   if (g_fClipboard && g_fClipboardStarted) {
     /* Synchronously destroy the clipboard window */
-    if (g_hwndClipboard != NULL) {
-      SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
-      /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
-    }
-    else
-      return;
+    winClipboardWindowDestroy();
 
     /* Wait for the clipboard thread to exit */
     pthread_join(g_ptClipboardProc, NULL);
@@ -150,11 +144,3 @@ winClipboardShutdown(void)
     winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
   }
 }
-
-void
-winFixClipboardChain(void)
-{
-    if (g_fClipboard && g_hwndClipboard) {
-        PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
-    }
-}
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 3d49606..2641e20 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -57,12 +57,12 @@
 
 extern Bool g_fUnicodeClipboard;
 extern Bool g_fClipboard;
-extern HWND g_hwndClipboard;
 
 /*
  * Global variables
  */
 
+static HWND g_hwndClipboard = NULL;
 static jmp_buf g_jmpEntry;
 static XIOErrorHandler g_winClipboardOldIOErrorHandler;
 static pthread_t g_winClipboardProcThread;
@@ -240,7 +240,7 @@ winClipboardProc(char *szDisplay)
     /* Create Windows messaging window */
     hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow);
 
-    /* Save copy of HWND in screen privates */
+    /* Save copy of HWND */
     g_hwndClipboard = hwnd;
 
     /* Assert ownership of selections if Win32 clipboard is owned */
@@ -355,10 +355,7 @@ winClipboardProc(char *szDisplay)
  winClipboardProc_Done:
     /* Close our Windows window */
     if (g_hwndClipboard) {
-        /* Destroy the Window window (hwnd) */
-        winDebug("winClipboardProc - Destroy Windows window\n");
-        PostMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
-        winClipboardFlushWindowsMessageQueue(g_hwndClipboard);
+        winClipboardWindowDestroy();
     }
 
     /* Close our X window */
@@ -489,3 +486,19 @@ winClipboardIOErrorHandler(Display * pDisplay)
 
     return 0;
 }
+
+void
+winClipboardWindowDestroy(void)
+{
+  if (g_hwndClipboard) {
+    SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
+  }
+}
+
+void
+winFixClipboardChain(void)
+{
+  if (g_hwndClipboard) {
+    PostMessage(g_hwndClipboard, WM_WM_REINIT, 0, 0);
+  }
+}
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index 8eaaf38..ad82b83 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -94,7 +94,6 @@ winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
 Bool g_fUnicodeClipboard = TRUE;
 Bool g_fClipboard = TRUE;
 Bool g_fClipboardStarted = FALSE;
-HWND g_hwndClipboard = NULL;
 #endif
 
 /*
@@ -106,7 +105,4 @@ void
 winInitializeGlobals(void)
 {
     g_dwCurrentThreadID = GetCurrentThreadId();
-#ifdef XWIN_CLIPBOARD
-    g_hwndClipboard = NULL;
-#endif
 }
commit 03a59e7f787a160c6cc07c7a37df64a793242ef2
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 02:01:39 2013 +0100

    hw/xwin: Add remaining clipboard globals to winglobals.h
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/windialogs.c b/hw/xwin/windialogs.c
index c9af0e2..61f7fe0 100644
--- a/hw/xwin/windialogs.c
+++ b/hw/xwin/windialogs.c
@@ -37,13 +37,6 @@
 #include "winprefs.h"
 
 /*
- * References to external globals
- */
-
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fClipboardStarted;
-#endif
-/*
  * Local function prototypes
  */
 
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index 5d8e7a0..d7b813d 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -73,6 +73,9 @@ typedef int (*winDispatchProcPtr) (ClientPtr);
  */
 extern winDispatchProcPtr winProcEstablishConnectionOrig;
 #endif
+extern Bool g_fUnicodeClipboard;
+extern Bool g_fClipboard;
+extern Bool g_fClipboardStarted;
 
 /* The global X default icons */
 #if defined(XWIN_MULTIWINDOW)
commit 8f9fba5bc1499804a6c4a3287d99fe7dab8d6b8f
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 02:01:27 2013 +0100

    hw/xwin: Hoist use of winSetAuthorization() and winGetDisplayName() up one level
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index fcda6bf..fa32c62 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -71,7 +71,6 @@
  * References to external symbols
  */
 
-extern char *display;
 extern void winDebug(const char *format, ...);
 extern void winErrorFVerb(int verb, const char *format, ...);
 
@@ -96,7 +95,7 @@ void
  * winclipboardthread.c
  */
 
-void *winClipboardProc(void *);
+void *winClipboardProc(char *szDisplay);
 
 /*
  * winclipboardwndproc.c
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 07e57ee..335e379 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -37,10 +37,13 @@
 
 #include "os.h"
 #include "winclipboard.h"
+#include "windisplay.h"
 
 #define WIN_CLIPBOARD_RETRIES			40
 #define WIN_CLIPBOARD_DELAY			1
 
+extern void winSetAuthorization(void);
+
 /*
  * References to external symbols
  */
@@ -61,16 +64,33 @@ static pthread_t g_ptClipboardProc;
 static void *
 winClipboardThreadProc(void *arg)
 {
+  char szDisplay[512];
   int clipboardRestarts = 0;
 
   while (1)
     {
       ++clipboardRestarts;
 
+      /* Use our generated cookie for authentication */
+      winSetAuthorization();
+
+      /* Setup the display connection string */
+      /*
+       * NOTE: Always connect to screen 0 since we require that screen
+       * numbers start at 0 and increase without gaps.  We only need
+       * to connect to one screen on the display to get events
+       * for all screens on the display.  That is why there is only
+       * one clipboard client thread.
+      */
+      winGetDisplayName(szDisplay, 0);
+
+      /* Print the display connection string */
+      ErrorF("winClipboardThreadProc - DISPLAY=%s\n", szDisplay);
+
       /* Flag that clipboard client has been launched */
       g_fClipboardStarted = TRUE;
 
-      winClipboardProc(arg);
+      winClipboardProc(szDisplay);
 
       /* Flag that clipboard client has stopped */
       g_fClipboardStarted = FALSE;
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index f9089ff..3d49606 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -89,7 +89,7 @@ static int
  */
 
 void *
-winClipboardProc(void *pvNotUsed)
+winClipboardProc(char *szDisplay)
 {
     Atom atomClipboard;
     int iReturn;
@@ -107,7 +107,6 @@ winClipboardProc(void *pvNotUsed)
     Window iWindow = None;
     int iRetries;
     Bool fUseUnicode;
-    char szDisplay[512];
     int iSelectError;
 
     winDebug("winClipboardProc - Hello\n");
@@ -150,24 +149,9 @@ winClipboardProc(void *pvNotUsed)
         goto winClipboardProc_Done;
     }
 
-    /* Use our generated cookie for authentication */
-    winSetAuthorization();
-
     /* Initialize retry count */
     iRetries = 0;
 
-    /* Setup the display connection string x */
-    /*
-     * NOTE: Always connect to screen 0 since we require that screen
-     * numbers start at 0 and increase without gaps.  We only need
-     * to connect to one screen on the display to get events
-     * for all screens on the display.  That is why there is only
-     * one clipboard client thread.
-     */
-    winGetDisplayName(szDisplay, 0);
-
-    /* Print the display connection string */
-    ErrorF("winClipboardProc - DISPLAY=%s\n", szDisplay);
 
     /* Open the X display */
     do {
commit a3c1e405cb78df9ef18a1158dcaed3c27b3cbffe
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jun 16 22:35:22 2013 +0100

    hw/xwin: Eliminate g_pClipboardDisplay and g_iClipboardWindow globals
    
    Eliminate the g_pClipboardDisplay and g_iClipboardWindow globals used to make
    those values available to the clipboard wndproc, by passing them in via the
    WM_CREATE message instead.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index 2d1b508..fcda6bf 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -107,6 +107,12 @@ BOOL winClipboardFlushWindowsMessageQueue(HWND hwnd);
 LRESULT CALLBACK
 winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
 
+typedef struct
+{
+  Display *pClipboardDisplay;
+  Window iClipboardWindow;
+} ClipboardWindowCreationParams;
+
 /*
  * winclipboardxevents.c
  */
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 0bffd44..f9089ff 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -58,8 +58,6 @@
 extern Bool g_fUnicodeClipboard;
 extern Bool g_fClipboard;
 extern HWND g_hwndClipboard;
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
 
 /*
  * Global variables
@@ -78,7 +76,7 @@ int xfixes_error_base;
  */
 
 static HWND
-winClipboardCreateMessagingWindow(void);
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow);
 
 static int
  winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
@@ -192,9 +190,6 @@ winClipboardProc(void *pvNotUsed)
         goto winClipboardProc_Done;
     }
 
-    /* Save the display in a global used by the wndproc */
-    g_pClipboardDisplay = pDisplay;
-
     ErrorF("winClipboardProc - XOpenDisplay () returned and "
            "successfully opened the display.\n");
 
@@ -255,14 +250,11 @@ winClipboardProc(void *pvNotUsed)
                                 XFixesSelectionWindowDestroyNotifyMask |
                                 XFixesSelectionClientCloseNotifyMask);
 
-    /* Save the window in the screen privates */
-    g_iClipboardWindow = iWindow;
 
     /* Initialize monitored selection state */
     winClipboardInitMonitoredSelections();
-
     /* Create Windows messaging window */
-    hwnd = winClipboardCreateMessagingWindow();
+    hwnd = winClipboardCreateMessagingWindow(pDisplay, iWindow);
 
     /* Save copy of HWND in screen privates */
     g_hwndClipboard = hwnd;
@@ -419,8 +411,6 @@ winClipboardProc(void *pvNotUsed)
 #endif
 
     /* global clipboard variable reset */
-    g_iClipboardWindow = None;
-    g_pClipboardDisplay = NULL;
     g_hwndClipboard = NULL;
 
     return NULL;
@@ -431,9 +421,10 @@ winClipboardProc(void *pvNotUsed)
  */
 
 static HWND
-winClipboardCreateMessagingWindow(void)
+winClipboardCreateMessagingWindow(Display *pDisplay, Window iWindow)
 {
     WNDCLASSEX wc;
+    ClipboardWindowCreationParams cwcp;
     HWND hwnd;
 
     /* Setup our window class */
@@ -451,6 +442,10 @@ winClipboardCreateMessagingWindow(void)
     wc.hIconSm = 0;
     RegisterClassEx(&wc);
 
+    /* Information to be passed to WM_CREATE */
+    cwcp.pClipboardDisplay = pDisplay;
+    cwcp.iClipboardWindow = iWindow;
+
     /* Create the window */
     hwnd = CreateWindowExA(0,   /* Extended styles */
                            WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
@@ -463,7 +458,7 @@ winClipboardCreateMessagingWindow(void)
                            (HWND) NULL, /* No parent or owner window */
                            (HMENU) NULL,        /* No menu */
                            GetModuleHandle(NULL),       /* Instance handle */
-                           NULL);       /* Creation data */
+                           &cwcp);       /* Creation data */
     assert(hwnd != NULL);
 
     /* I'm not sure, but we may need to call this to start message processing */
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index d73c2db..459170f 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -44,12 +44,6 @@
 
 #define WIN_POLL_TIMEOUT	1
 
-/*
- * References to external symbols
- */
-
-extern void *g_pClipboardDisplay;
-extern Window g_iClipboardWindow;
 
 /*
  * Process X events up to specified timeout
@@ -138,6 +132,8 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
     static HWND s_hwndNextViewer;
     static Bool s_fCBCInitialized;
+    static Display *pDisplay;
+    static Window iWindow;
 
     /* Branch on message type */
     switch (message) {
@@ -158,9 +154,13 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     {
         HWND first, next;
         DWORD error_code = 0;
+        ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;
 
         winDebug("winClipboardWindowProc - WM_CREATE\n");
 
+        pDisplay = cwcp->pClipboardDisplay;
+        iWindow = cwcp->iClipboardWindow;
+
         first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
         if (first == hwnd)
             return 0;           /* Make sure it's not us! */
@@ -243,8 +243,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         static Atom atomClipboard;
         static int generation;
         static Bool s_fProcessingDrawClipboard = FALSE;
-        Display *pDisplay = g_pClipboardDisplay;
-        Window iWindow = g_iClipboardWindow;
         int iReturn;
 
         winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
@@ -323,7 +321,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
             /* Release PRIMARY selection if owned */
             iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
-            if (iReturn == g_iClipboardWindow) {
+            if (iReturn == iWindow) {
                 winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                          "PRIMARY selection is owned by us.\n");
                 XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
@@ -335,7 +333,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
             /* Release CLIPBOARD selection if owned */
             iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
-            if (iReturn == g_iClipboardWindow) {
+            if (iReturn == iWindow) {
                 winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                          "CLIPBOARD selection is owned by us.\n");
                 XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
@@ -408,8 +406,6 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     case WM_RENDERALLFORMATS:
     {
         int iReturn;
-        Display *pDisplay = g_pClipboardDisplay;
-        Window iWindow = g_iClipboardWindow;
         Bool fConvertToUnicode;
 
         winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index b3f18ae..8eaaf38 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -95,8 +95,6 @@ Bool g_fUnicodeClipboard = TRUE;
 Bool g_fClipboard = TRUE;
 Bool g_fClipboardStarted = FALSE;
 HWND g_hwndClipboard = NULL;
-void *g_pClipboardDisplay = NULL;
-Window g_iClipboardWindow = None;
 #endif
 
 /*
@@ -109,8 +107,6 @@ winInitializeGlobals(void)
 {
     g_dwCurrentThreadID = GetCurrentThreadId();
 #ifdef XWIN_CLIPBOARD
-    g_iClipboardWindow = None;
-    g_pClipboardDisplay = NULL;
     g_hwndClipboard = NULL;
 #endif
 }
commit 229a0a83a44c94ce76eb937d58dc1773a38baa3e
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jun 16 22:13:26 2013 +0100

    hw/xwin: Move winClipboardCreateMessagingWindow() to winclipboardthread.c
    
    Move winClipboardCreateMessagingWindow() from winclipboardinit.c to
    winclipboardthread.c, the only place that uses it, and make it static.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index 503d6ac..2d1b508 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -55,8 +55,6 @@
 #include <X11/Xwindows.h>
 
 /* Clipboard module constants */
-#define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
-#define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
 #ifdef HAS_DEVWINDOWS
 #define WIN_MSG_QUEUE_FNAME			"/dev/windows"
 #endif
@@ -84,8 +82,6 @@ extern void winErrorFVerb(int verb, const char *format, ...);
 Bool
  winInitClipboard(void);
 
-HWND winClipboardCreateMessagingWindow(void);
-
 /*
  * winclipboardtextconv.c
  */
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index e74e2b2..07e57ee 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -131,55 +131,6 @@ winClipboardShutdown(void)
   }
 }
 
-/*
- * Create the Windows window that we use to receive Windows messages
- */
-
-HWND
-winClipboardCreateMessagingWindow(void)
-{
-    WNDCLASSEX wc;
-    HWND hwnd;
-
-    /* Setup our window class */
-    wc.cbSize = sizeof(WNDCLASSEX);
-    wc.style = CS_HREDRAW | CS_VREDRAW;
-    wc.lpfnWndProc = winClipboardWindowProc;
-    wc.cbClsExtra = 0;
-    wc.cbWndExtra = 0;
-    wc.hInstance = GetModuleHandle(NULL);
-    wc.hIcon = 0;
-    wc.hCursor = 0;
-    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
-    wc.lpszMenuName = NULL;
-    wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
-    wc.hIconSm = 0;
-    RegisterClassEx(&wc);
-
-    /* Create the window */
-    hwnd = CreateWindowExA(0,   /* Extended styles */
-                           WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
-                           WIN_CLIPBOARD_WINDOW_TITLE,  /* Window name */
-                           WS_OVERLAPPED,       /* Not visible anyway */
-                           CW_USEDEFAULT,       /* Horizontal position */
-                           CW_USEDEFAULT,       /* Vertical position */
-                           CW_USEDEFAULT,       /* Right edge */
-                           CW_USEDEFAULT,       /* Bottom edge */
-                           (HWND) NULL, /* No parent or owner window */
-                           (HMENU) NULL,        /* No menu */
-                           GetModuleHandle(NULL),       /* Instance handle */
-                           NULL);       /* Creation data */
-    assert(hwnd != NULL);
-
-    /* I'm not sure, but we may need to call this to start message processing */
-    ShowWindow(hwnd, SW_HIDE);
-
-    /* Similarly, we may need a call to this even though we don't paint */
-    UpdateWindow(hwnd);
-
-    return hwnd;
-}
-
 void
 winFixClipboardChain(void)
 {
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 04ab24f..0bffd44 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -48,6 +48,9 @@
 #define WIN_CONNECT_RETRIES			40
 #define WIN_CONNECT_DELAY			4
 
+#define WIN_CLIPBOARD_WINDOW_CLASS		"xwinclip"
+#define WIN_CLIPBOARD_WINDOW_TITLE		"xwinclip"
+
 /*
  * References to external symbols
  */
@@ -74,6 +77,9 @@ int xfixes_error_base;
  * Local function prototypes
  */
 
+static HWND
+winClipboardCreateMessagingWindow(void);
+
 static int
  winClipboardErrorHandler(Display * pDisplay, XErrorEvent * pErr);
 
@@ -421,6 +427,55 @@ winClipboardProc(void *pvNotUsed)
 }
 
 /*
+ * Create the Windows window that we use to receive Windows messages
+ */
+
+static HWND
+winClipboardCreateMessagingWindow(void)
+{
+    WNDCLASSEX wc;
+    HWND hwnd;
+
+    /* Setup our window class */
+    wc.cbSize = sizeof(WNDCLASSEX);
+    wc.style = CS_HREDRAW | CS_VREDRAW;
+    wc.lpfnWndProc = winClipboardWindowProc;
+    wc.cbClsExtra = 0;
+    wc.cbWndExtra = 0;
+    wc.hInstance = GetModuleHandle(NULL);
+    wc.hIcon = 0;
+    wc.hCursor = 0;
+    wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+    wc.lpszMenuName = NULL;
+    wc.lpszClassName = WIN_CLIPBOARD_WINDOW_CLASS;
+    wc.hIconSm = 0;
+    RegisterClassEx(&wc);
+
+    /* Create the window */
+    hwnd = CreateWindowExA(0,   /* Extended styles */
+                           WIN_CLIPBOARD_WINDOW_CLASS,  /* Class name */
+                           WIN_CLIPBOARD_WINDOW_TITLE,  /* Window name */
+                           WS_OVERLAPPED,       /* Not visible anyway */
+                           CW_USEDEFAULT,       /* Horizontal position */
+                           CW_USEDEFAULT,       /* Vertical position */
+                           CW_USEDEFAULT,       /* Right edge */
+                           CW_USEDEFAULT,       /* Bottom edge */
+                           (HWND) NULL, /* No parent or owner window */
+                           (HMENU) NULL,        /* No menu */
+                           GetModuleHandle(NULL),       /* Instance handle */
+                           NULL);       /* Creation data */
+    assert(hwnd != NULL);
+
+    /* I'm not sure, but we may need to call this to start message processing */
+    ShowWindow(hwnd, SW_HIDE);
+
+    /* Similarly, we may need a call to this even though we don't paint */
+    UpdateWindow(hwnd);
+
+    return hwnd;
+}
+
+/*
  * winClipboardErrorHandler - Our application specific error handler
  */
 
commit a70c2384a2689cc0346868bb27366c008c01758d
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Feb 13 19:58:37 2012 +0000

    hw/xwin: Remove SetSelectionOwner wrapper, use XFixesSetSelectionOwnerNotify event instead
    
    Use the XFixesSetSelectionNotify event instead of a SetSelectionOwner wrapper,
    the completely equivalent client-side mechanism.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/configure.ac b/configure.ac
index cba7d24..8dc7198 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2143,7 +2143,7 @@ if test "x$XWIN" = xyes; then
 	AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support])
 	AC_CHECK_TOOL(WINDRES, windres)
 
-	PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau])
+	PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfixes])
 
 	if test "x$WINDOWSWM" = xauto; then
 		PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no])
diff --git a/hw/xwin/InitInput.c b/hw/xwin/InitInput.c
index 38203c9..3e9ee41 100644
--- a/hw/xwin/InitInput.c
+++ b/hw/xwin/InitInput.c
@@ -39,7 +39,6 @@
 
 #ifdef XWIN_CLIPBOARD
 int winProcEstablishConnection(ClientPtr /* client */ );
-int winProcSetSelectionOwner(ClientPtr /* client */ );
 #endif
 
 /*
diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index 63dce73..503d6ac 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -116,7 +116,14 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  */
 
 int
-
 winClipboardFlushXEvents(HWND hwnd,
                          int iWindow, Display * pDisplay, Bool fUnicodeSupport);
+
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(void);
+
+void
+winClipboardInitMonitoredSelections(void);
+
 #endif
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 4912b2e..e74e2b2 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -35,25 +35,16 @@
 #include <unistd.h>
 #include <pthread.h>
 
-#include "dixstruct.h"
+#include "os.h"
 #include "winclipboard.h"
 
 #define WIN_CLIPBOARD_RETRIES			40
 #define WIN_CLIPBOARD_DELAY			1
 
 /*
- * Local typedefs
- */
-
-typedef int (*winDispatchProcPtr) (ClientPtr);
-
-int winProcSetSelectionOwner(ClientPtr /* client */ );
-
-/*
  * References to external symbols
  */
 
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
 extern Bool g_fClipboard;
 extern HWND g_hwndClipboard;
 extern Bool g_fClipboardStarted;
@@ -108,12 +99,6 @@ winInitClipboard(void)
 {
     winDebug("winInitClipboard ()\n");
 
-    /* Wrap some internal server functions */
-    if (ProcVector[X_SetSelectionOwner] != winProcSetSelectionOwner) {
-        winProcSetSelectionOwnerOrig = ProcVector[X_SetSelectionOwner];
-        ProcVector[X_SetSelectionOwner] = winProcSetSelectionOwner;
-    }
-
     /* Spawn a thread for the Clipboard module */
     if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) {
         /* Bail if thread creation failed */
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 2ef73bd..04ab24f 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -43,6 +43,7 @@
 #include <errno.h>
 #endif
 #include "misc.h"
+#include <X11/extensions/Xfixes.h>
 
 #define WIN_CONNECT_RETRIES			40
 #define WIN_CONNECT_DELAY			4
@@ -66,6 +67,8 @@ static XIOErrorHandler g_winClipboardOldIOErrorHandler;
 static pthread_t g_winClipboardProcThread;
 
 Bool g_fUseUnicode = FALSE;
+int xfixes_event_base;
+int xfixes_error_base;
 
 /*
  * Local function prototypes
@@ -206,6 +209,9 @@ winClipboardProc(void *pvNotUsed)
     iMaxDescriptor = iConnectionNumber + 1;
 #endif
 
+    if (!XFixesQueryExtension(pDisplay, &xfixes_event_base, &xfixes_error_base))
+      ErrorF ("winClipboardProc - XFixes extension not present\n");
+
     /* Create atom */
     atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
 
@@ -229,9 +235,26 @@ winClipboardProc(void *pvNotUsed)
         ErrorF("winClipboardProc - XSelectInput generated BadWindow "
                "on messaging window\n");
 
+    XFixesSelectSelectionInput (pDisplay,
+                                iWindow,
+                                XA_PRIMARY,
+                                XFixesSetSelectionOwnerNotifyMask |
+                                XFixesSelectionWindowDestroyNotifyMask |
+                                XFixesSelectionClientCloseNotifyMask);
+
+    XFixesSelectSelectionInput (pDisplay,
+                                iWindow,
+                                XInternAtom (pDisplay, "CLIPBOARD", False),
+                                XFixesSetSelectionOwnerNotifyMask |
+                                XFixesSelectionWindowDestroyNotifyMask |
+                                XFixesSelectionClientCloseNotifyMask);
+
     /* Save the window in the screen privates */
     g_iClipboardWindow = iWindow;
 
+    /* Initialize monitored selection state */
+    winClipboardInitMonitoredSelections();
+
     /* Create Windows messaging window */
     hwnd = winClipboardCreateMessagingWindow();
 
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index 90dc9e0..d73c2db 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -50,7 +50,6 @@
 
 extern void *g_pClipboardDisplay;
 extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
 
 /*
  * Process X events up to specified timeout
@@ -423,7 +422,7 @@ winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
         /* Request the selection contents */
         iReturn = XConvertSelection(pDisplay,
-                                    g_atomLastOwnedSelection,
+                                    winClipboardGetLastOwnedSelectionAtom(),
                                     XInternAtom(pDisplay,
                                                 "COMPOUND_TEXT", False),
                                     XInternAtom(pDisplay,
diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index 99dfc5b..2679f4f 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -33,35 +33,21 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
+
 #include "win.h"
 #include "dixstruct.h"
-#include <X11/Xatom.h>
-
-/*
- * Constants
- */
-
-#define CLIP_NUM_SELECTIONS		2
-#define CLIP_OWN_PRIMARY		0
-#define CLIP_OWN_CLIPBOARD		1
 
 /*
  * Local function prototypes
  */
 
 DISPATCH_PROC(winProcEstablishConnection);
-DISPATCH_PROC(winProcSetSelectionOwner);
 
 /*
  * References to external symbols
  */
 
-extern Bool g_fClipboardStarted;
 extern Bool g_fClipboard;
-extern Window g_iClipboardWindow;
-extern Atom g_atomLastOwnedSelection;
-extern HWND g_hwndClipboard;
-
 
 /*
  * Wrapper for internal EstablishConnection function.
@@ -157,202 +143,3 @@ winProcEstablishConnection(ClientPtr client)
 
     return iReturn;
 }
-
-/*
- * Wrapper for internal SetSelectionOwner function.
- * Grabs ownership of Windows clipboard when X11 clipboard owner changes.
- */
-
-int
-winProcSetSelectionOwner(ClientPtr client)
-{
-    int i;
-    DrawablePtr pDrawable;
-    WindowPtr pWindow = None;
-    Bool fOwnedToNotOwned = FALSE;
-    static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None };
-    static unsigned long s_ulServerGeneration = 0;
-
-    REQUEST(xSetSelectionOwnerReq);
-
-    REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
-
-    winDebug("winProcSetSelectionOwner - Hello.\n");
-
-    /* Watch for server reset */
-    if (s_ulServerGeneration != serverGeneration) {
-        /* Save new generation number */
-        s_ulServerGeneration = serverGeneration;
-
-        /* Initialize static variables */
-        for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
-            s_iOwners[i] = None;
-    }
-
-    /* Abort if clipboard not completely initialized yet */
-    if (!g_fClipboardStarted) {
-        /* ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
-           "aborting.\n"); */
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Grab window if we have one */
-    if (None != stuff->window) {
-        /* Grab the Window from the request */
-        int rc =
-            dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
-        if (rc != Success) {
-            ErrorF("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
-            goto winProcSetSelectionOwner_Done;
-        }
-    }
-
-    /* Now we either have a valid window or None */
-
-    /* Save selection owners for monitored selections, ignore other selections */
-    if (XA_PRIMARY == stuff->selection) {
-        /* Look for owned -> not owned transition */
-        if (None == stuff->window && None != s_iOwners[CLIP_OWN_PRIMARY]) {
-            fOwnedToNotOwned = TRUE;
-
-            winDebug("winProcSetSelectionOwner - PRIMARY - Going from "
-                     "owned to not owned.\n");
-
-            /* Adjust last owned selection */
-            if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
-                g_atomLastOwnedSelection = MakeAtom("CLIPBOARD", 9, TRUE);
-            else
-                g_atomLastOwnedSelection = None;
-        }
-
-        /* Save new selection owner or None */
-        s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;
-
-        winDebug("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
-                 stuff->window);
-    }
-    else if (MakeAtom("CLIPBOARD", 9, TRUE) == stuff->selection) {
-        /* Look for owned -> not owned transition */
-        if (None == stuff->window && None != s_iOwners[CLIP_OWN_CLIPBOARD]) {
-            fOwnedToNotOwned = TRUE;
-
-            winDebug("winProcSetSelectionOwner - CLIPBOARD - Going from "
-                     "owned to not owned.\n");
-
-            /* Adjust last owned selection */
-            if (None != s_iOwners[CLIP_OWN_PRIMARY])
-                g_atomLastOwnedSelection = XA_PRIMARY;
-            else
-                g_atomLastOwnedSelection = None;
-        }
-
-        /* Save new selection owner or None */
-        s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;
-
-        winDebug("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
-                 stuff->window);
-
-    }
-    else
-        goto winProcSetSelectionOwner_Done;
-
-    /*
-     * At this point, if one of the selections is still owned by the 
-     * clipboard manager then it should be marked as unowned since
-     * we will be taking ownership of the Win32 clipboard.
-     */
-    if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
-        s_iOwners[CLIP_OWN_PRIMARY] = None;
-    if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
-        s_iOwners[CLIP_OWN_CLIPBOARD] = None;
-
-    /*
-     * Handle case when selection is being disowned,
-     * WM_DRAWCLIPBOARD did not do the disowning,
-     * both monitored selections are no longer owned,
-     * an owned to not owned transition was detected,
-     * and we currently own the Win32 clipboard.
-     */
-    if (stuff->window == None
-        && s_iOwners[CLIP_OWN_PRIMARY] == None
-        && s_iOwners[CLIP_OWN_CLIPBOARD] == None
-        && fOwnedToNotOwned
-        && g_hwndClipboard != NULL && g_hwndClipboard == GetClipboardOwner()) {
-        winDebug("winProcSetSelectionOwner - We currently own the "
-                 "clipboard and neither the PRIMARY nor the CLIPBOARD "
-                 "selections are owned, releasing ownership of Win32 "
-                 "clipboard.\n");
-
-        /* Release ownership of the Windows clipboard */
-        OpenClipboard(NULL);
-        EmptyClipboard();
-        CloseClipboard();
-
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Abort if no window at this point */
-    if (None == stuff->window) {
-        winDebug("winProcSetSelectionOwner - No window, returning.\n");
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Abort if invalid selection */
-    if (!ValidAtom(stuff->selection)) {
-        ErrorF("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Cast Window to Drawable */
-    pDrawable = (DrawablePtr) pWindow;
-
-    /* Abort if clipboard manager is owning the selection */
-    if (pDrawable->id == g_iClipboardWindow) {
-        winDebug("winProcSetSelectionOwner - We changed ownership, "
-                 "aborting.\n");
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Abort if root window is taking ownership */
-    if (pDrawable->id == 0) {
-        ErrorF("winProcSetSelectionOwner - Root window taking ownership, "
-               "aborting\n");
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Close clipboard if we have it open already */
-    if (GetOpenClipboardWindow() == g_hwndClipboard) {
-        CloseClipboard();
-    }
-
-    /* Access the Windows clipboard */
-    if (!OpenClipboard(g_hwndClipboard)) {
-        ErrorF("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
-               (int) GetLastError());
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Take ownership of the Windows clipboard */
-    if (!EmptyClipboard()) {
-        ErrorF("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
-               (int) GetLastError());
-        goto winProcSetSelectionOwner_Done;
-    }
-
-    /* Advertise regular text and unicode */
-    SetClipboardData(CF_UNICODETEXT, NULL);
-    SetClipboardData(CF_TEXT, NULL);
-
-    /* Save handle to last owned selection */
-    g_atomLastOwnedSelection = stuff->selection;
-
-    /* Release the clipboard */
-    if (!CloseClipboard()) {
-        ErrorF("winProcSetSelectionOwner - CloseClipboard () failed: "
-               "%08x\n", (int) GetLastError());
-        goto winProcSetSelectionOwner_Done;
-    }
-
- winProcSetSelectionOwner_Done:
-    return (*winProcSetSelectionOwnerOrig) (client);
-}
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboardxevents.c
index 7d3c30e..a792467 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboardxevents.c
@@ -33,8 +33,95 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
+
 #include "winclipboard.h"
 #include "misc.h"
+#include <X11/extensions/Xfixes.h>
+
+/*
+ * Constants
+ */
+
+#define CLIP_NUM_SELECTIONS		2
+#define CLIP_OWN_NONE     		-1
+#define CLIP_OWN_PRIMARY		0
+#define CLIP_OWN_CLIPBOARD		1
+
+/*
+ * Global variables
+ */
+
+extern int xfixes_event_base;
+
+/*
+ * Local variables
+ */
+
+static Window s_iOwners[CLIP_NUM_SELECTIONS] = { None, None };
+static const char *szSelectionNames[CLIP_NUM_SELECTIONS] =
+    { "PRIMARY", "CLIPBOARD" };
+
+static unsigned int lastOwnedSelectionIndex = CLIP_OWN_NONE;
+static Atom atomClipboard = None;
+
+static void
+MonitorSelection(XFixesSelectionNotifyEvent * e, unsigned int i)
+{
+    /* Look for owned -> not owned transition */
+    if (None == e->owner && None != s_iOwners[i]) {
+        unsigned int other_index;
+
+        winDebug("MonitorSelection - %s - Going from owned to not owned.\n",
+                 szSelectionNames[i]);
+
+        /* If this selection is not owned, the other monitored selection must be the most
+           recently owned, if it is owned at all */
+        if (i == CLIP_OWN_PRIMARY)
+            other_index = CLIP_OWN_CLIPBOARD;
+        if (i == CLIP_OWN_CLIPBOARD)
+            other_index = CLIP_OWN_PRIMARY;
+        if (None != s_iOwners[other_index])
+            lastOwnedSelectionIndex = other_index;
+        else
+            lastOwnedSelectionIndex = CLIP_OWN_NONE;
+    }
+
+    /* Save last owned selection */
+    if (None != e->owner) {
+        lastOwnedSelectionIndex = i;
+    }
+
+    /* Save new selection owner or None */
+    s_iOwners[i] = e->owner;
+    winDebug("MonitorSelection - %s - Now owned by XID %x\n",
+             szSelectionNames[i], e->owner);
+}
+
+Atom
+winClipboardGetLastOwnedSelectionAtom(void)
+{
+    if (lastOwnedSelectionIndex == CLIP_OWN_NONE)
+        return None;
+
+    if (lastOwnedSelectionIndex == CLIP_OWN_PRIMARY)
+        return XA_PRIMARY;
+
+    if (lastOwnedSelectionIndex == CLIP_OWN_CLIPBOARD)
+        return atomClipboard;
+
+    return None;
+}
+
+
+void
+winClipboardInitMonitoredSelections(void)
+{
+    /* Initialize static variables */
+    for (int i = 0; i < CLIP_NUM_SELECTIONS; ++i)
+      s_iOwners[i] = None;
+
+    lastOwnedSelectionIndex = CLIP_OWN_NONE;
+}
 
 /*
  * Process any pending X events
@@ -52,6 +139,7 @@ winClipboardFlushXEvents(HWND hwnd,
 
     if (generation != serverGeneration) {
         generation = serverGeneration;
+        atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
         atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
         atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
         atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
@@ -77,7 +165,6 @@ winClipboardFlushXEvents(HWND hwnd,
         wchar_t *pwszUnicodeStr = NULL;
         int iUnicodeLen = 0;
         int iReturnDataLen = 0;
-        int i;
         Bool fAbort = FALSE;
         Bool fCloseClipboard = FALSE;
         Bool fSetClipboardData = TRUE;
@@ -525,6 +612,8 @@ winClipboardFlushXEvents(HWND hwnd,
             if (iReturn == Success || iReturn > 0) {
                 /* Conversion succeeded or some unconvertible characters */
                 if (ppszTextList != NULL) {
+                    int i;
+
                     iReturnDataLen = 0;
                     for (i = 0; i < iCount; i++) {
                         iReturnDataLen += strlen(ppszTextList[i]);
@@ -693,8 +782,78 @@ winClipboardFlushXEvents(HWND hwnd,
             break;
 
         default:
-            ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
-                   event.type);
+            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
+                XFixesSelectionNotifyEvent *e =
+                    (XFixesSelectionNotifyEvent *) & event;
+
+                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");
+
+                /* Save selection owners for monitored selections, ignore other selections */
+                if (e->selection == XA_PRIMARY) {
+                    MonitorSelection(e, CLIP_OWN_PRIMARY);
+                }
+                else if (e->selection == atomClipboard) {
+                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
+                }
+                else
+                    break;
+
+                /* Selection is being disowned */
+                if (e->owner == None) {
+                    winDebug
+                        ("winClipboardFlushXEvents - No window, returning.\n");
+                    break;
+                }
+
+                /*
+                   XXX: there are all kinds of wacky edge cases we might need here:
+                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
+                   - root window is taking ownership?
+                 */
+
+                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
+                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
+                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
+                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
+                    break;
+                }
+
+                /* Close clipboard if we have it open already (possible? correct??) */
+                if (GetOpenClipboardWindow() == hwnd) {
+                    CloseClipboard();
+                }
+
+                /* Access the Windows clipboard */
+                if (!OpenClipboard(hwnd)) {
+                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+
+                /* Take ownership of the Windows clipboard */
+                if (!EmptyClipboard()) {
+                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+
+                /* Advertise regular text and unicode */
+                SetClipboardData(CF_UNICODETEXT, NULL);
+                SetClipboardData(CF_TEXT, NULL);
+
+                /* Release the clipboard */
+                if (!CloseClipboard()) {
+                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
+                           (int) GetLastError());
+                    break;
+                }
+            }
+            /* XFixesSelectionWindowDestroyNotifyMask */
+            /* XFixesSelectionClientCloseNotifyMask */
+            else {
+                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
+                       event.type);
+            }
             break;
         }
     }
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index 095ecff..b3f18ae 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -86,7 +86,6 @@ pthread_mutex_t g_pmTerminating = PTHREAD_MUTEX_INITIALIZER;
  * Wrapped DIX functions
  */
 winDispatchProcPtr winProcEstablishConnectionOrig = NULL;
-winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
 
 /*
  * Clipboard variables
@@ -98,7 +97,6 @@ Bool g_fClipboardStarted = FALSE;
 HWND g_hwndClipboard = NULL;
 void *g_pClipboardDisplay = NULL;
 Window g_iClipboardWindow = None;
-Atom g_atomLastOwnedSelection = None;
 #endif
 
 /*
@@ -113,7 +111,6 @@ winInitializeGlobals(void)
 #ifdef XWIN_CLIPBOARD
     g_iClipboardWindow = None;
     g_pClipboardDisplay = NULL;
-    g_atomLastOwnedSelection = None;
     g_hwndClipboard = NULL;
 #endif
 }
diff --git a/hw/xwin/winglobals.h b/hw/xwin/winglobals.h
index 60c00da..5d8e7a0 100644
--- a/hw/xwin/winglobals.h
+++ b/hw/xwin/winglobals.h
@@ -72,7 +72,6 @@ typedef int (*winDispatchProcPtr) (ClientPtr);
  * Wrapped DIX functions
  */
 extern winDispatchProcPtr winProcEstablishConnectionOrig;
-extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
 #endif
 
 /* The global X default icons */
commit ab55746c1b179172a82b7a89ec6429b268a1f166
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 01:55:46 2013 +0100

    hw/xwin: Remove g_fClipboardLaunched, it's value is identical to g_fClipboardStarted
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 0b895cb..4912b2e 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -56,7 +56,6 @@ int winProcSetSelectionOwner(ClientPtr /* client */ );
 extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
 extern Bool g_fClipboard;
 extern HWND g_hwndClipboard;
-extern Bool g_fClipboardLaunched;
 extern Bool g_fClipboardStarted;
 
 /*
@@ -78,13 +77,11 @@ winClipboardThreadProc(void *arg)
       ++clipboardRestarts;
 
       /* Flag that clipboard client has been launched */
-      g_fClipboardLaunched = TRUE;
       g_fClipboardStarted = TRUE;
 
       winClipboardProc(arg);
 
       /* Flag that clipboard client has stopped */
-      g_fClipboardLaunched = FALSE;
       g_fClipboardStarted = FALSE;
 
       /* checking if we need to restart */
@@ -131,7 +128,7 @@ void
 winClipboardShutdown(void)
 {
   /* Close down clipboard resources */
-  if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
+  if (g_fClipboard && g_fClipboardStarted) {
     /* Synchronously destroy the clipboard window */
     if (g_hwndClipboard != NULL) {
       SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
@@ -143,7 +140,6 @@ winClipboardShutdown(void)
     /* Wait for the clipboard thread to exit */
     pthread_join(g_ptClipboardProc, NULL);
 
-    g_fClipboardLaunched = FALSE;
     g_fClipboardStarted = FALSE;
 
     winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index b0d6ffc..095ecff 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -94,7 +94,6 @@ winDispatchProcPtr winProcSetSelectionOwnerOrig = NULL;
 
 Bool g_fUnicodeClipboard = TRUE;
 Bool g_fClipboard = TRUE;
-Bool g_fClipboardLaunched = FALSE;
 Bool g_fClipboardStarted = FALSE;
 HWND g_hwndClipboard = NULL;
 void *g_pClipboardDisplay = NULL;
commit 42d13810822f6b48771d77b09c0ef7cc2356ede5
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 01:30:09 2013 +0100

    hw/xwin: Hoist setting of g_fClipboardStarted flag up one level
    
    Hoist the setting of g_fClipboardStarted flag up one level.
    
    Also move up the clearing of the g_fClipboardLaunched at the end of clipboard
    function.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index a3c1261..0b895cb 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -79,9 +79,14 @@ winClipboardThreadProc(void *arg)
 
       /* Flag that clipboard client has been launched */
       g_fClipboardLaunched = TRUE;
+      g_fClipboardStarted = TRUE;
 
       winClipboardProc(arg);
 
+      /* Flag that clipboard client has stopped */
+      g_fClipboardLaunched = FALSE;
+      g_fClipboardStarted = FALSE;
+
       /* checking if we need to restart */
       if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
         /* terminates clipboard thread but the main server still lives */
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index fd1fc07..2ef73bd 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -52,8 +52,6 @@
  */
 
 extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardStarted;
-extern Bool g_fClipboardLaunched;
 extern Bool g_fClipboard;
 extern HWND g_hwndClipboard;
 extern void *g_pClipboardDisplay;
@@ -274,9 +272,6 @@ winClipboardProc(void *pvNotUsed)
         ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
     }
 
-    /* Signal that the clipboard client has started */
-    g_fClipboardStarted = TRUE;
-
     /* Loop for X events */
     while (1) {
         /* Setup the file descriptor set */
@@ -395,8 +390,6 @@ winClipboardProc(void *pvNotUsed)
 #endif
 
     /* global clipboard variable reset */
-    g_fClipboardLaunched = FALSE;
-    g_fClipboardStarted = FALSE;
     g_iClipboardWindow = None;
     g_pClipboardDisplay = NULL;
     g_hwndClipboard = NULL;
commit 290dbff0753ddf60f04da92d5a408c567a2ee3e0
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 01:55:03 2013 +0100

    hw/xwin: winProcEstablishConnection doesn't need to check if clipboard started
    
    winProcEstablishConnection doesn't need to check if clipboard has already been
    started.
    
    It should be clear that we start the thread only once when the wrapper tells us
    to, as the wrapper unhooks itself thereafter.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index 05a8a28..99dfc5b 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -56,7 +56,6 @@ DISPATCH_PROC(winProcSetSelectionOwner);
  * References to external symbols
  */
 
-extern Bool g_fClipboardLaunched;
 extern Bool g_fClipboardStarted;
 extern Bool g_fClipboard;
 extern Window g_iClipboardWindow;
@@ -127,13 +126,6 @@ winProcEstablishConnection(ClientPtr client)
     /* Clear original function pointer */
     winProcEstablishConnectionOrig = NULL;
 
-    /* If the clipboard client has already been started, abort */
-    if (g_fClipboardLaunched) {
-        ErrorF("winProcEstablishConnection - Clipboard client already "
-               "launched, returning.\n");
-        return iReturn;
-    }
-
     /* Startup the clipboard client if clipboard mode is being used */
     if (g_fClipboard) {
         /*
commit 91e55691ef07735bb866c0f4d3c1a6e2ca167992
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Sun Jun 16 23:57:17 2013 +0100

    hw/xwin: Hoist clipboard thread restart up one level
    
    Hoist clipboard thread restart up one level.
    
    Note that currently g_fClipboardLaunched is set the first time in the
    winProcEstablishConnection wrapper, and subsequent times when the clipboard
    thread restarts itself.
    
    Try to clarify this and just set g_fClipboardLaunched before starting the
    thread.
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboard.h b/hw/xwin/winclipboard.h
index cb77695..63dce73 100644
--- a/hw/xwin/winclipboard.h
+++ b/hw/xwin/winclipboard.h
@@ -60,16 +60,12 @@
 #ifdef HAS_DEVWINDOWS
 #define WIN_MSG_QUEUE_FNAME			"/dev/windows"
 #endif
-#define WIN_CONNECT_RETRIES			40
-#define WIN_CONNECT_DELAY			4
 #define WIN_JMP_OKAY				0
 #define WIN_JMP_ERROR_IO			2
 #define WIN_LOCAL_PROPERTY			"CYGX_CUT_BUFFER"
 #define WIN_XEVENTS_SUCCESS			0
 #define WIN_XEVENTS_CONVERT			2
 #define WIN_XEVENTS_NOTIFY			3
-#define WIN_CLIPBOARD_RETRIES			40
-#define WIN_CLIPBOARD_DELAY			1
 
 #define WM_WM_REINIT                           (WM_USER + 1)
 
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index e6bbf17..a3c1261 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -31,9 +31,16 @@
 #ifdef HAVE_XWIN_CONFIG_H
 #include <xwin-config.h>
 #endif
+
+#include <unistd.h>
+#include <pthread.h>
+
 #include "dixstruct.h"
 #include "winclipboard.h"
 
+#define WIN_CLIPBOARD_RETRIES			40
+#define WIN_CLIPBOARD_DELAY			1
+
 /*
  * Local typedefs
  */
@@ -59,6 +66,38 @@ extern Bool g_fClipboardStarted;
 static pthread_t g_ptClipboardProc;
 
 /*
+ *
+ */
+static void *
+winClipboardThreadProc(void *arg)
+{
+  int clipboardRestarts = 0;
+
+  while (1)
+    {
+      ++clipboardRestarts;
+
+      /* Flag that clipboard client has been launched */
+      g_fClipboardLaunched = TRUE;
+
+      winClipboardProc(arg);
+
+      /* checking if we need to restart */
+      if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
+        /* terminates clipboard thread but the main server still lives */
+        ErrorF("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n", clipboardRestarts);
+        g_fClipboard = FALSE;
+        break;
+      }
+
+      sleep(WIN_CLIPBOARD_DELAY);
+      ErrorF("winClipboardProc - trying to restart clipboard thread \n");
+    }
+
+  return NULL;
+}
+
+/*
  * Intialize the Clipboard module
  */
 
@@ -74,7 +113,7 @@ winInitClipboard(void)
     }
 
     /* Spawn a thread for the Clipboard module */
-    if (pthread_create(&g_ptClipboardProc, NULL, winClipboardProc, NULL)) {
+    if (pthread_create(&g_ptClipboardProc, NULL, winClipboardThreadProc, NULL)) {
         /* Bail if thread creation failed */
         ErrorF("winInitClipboard - pthread_create failed.\n");
         return FALSE;
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 4a9eb4c..fd1fc07 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -44,6 +44,9 @@
 #endif
 #include "misc.h"
 
+#define WIN_CONNECT_RETRIES			40
+#define WIN_CONNECT_DELAY			4
+
 /*
  * References to external symbols
  */
@@ -61,7 +64,6 @@ extern Window g_iClipboardWindow;
  */
 
 static jmp_buf g_jmpEntry;
-static int clipboardRestarts = 0;
 static XIOErrorHandler g_winClipboardOldIOErrorHandler;
 static pthread_t g_winClipboardProcThread;
 
@@ -104,7 +106,6 @@ winClipboardProc(void *pvNotUsed)
     int iSelectError;
 
     winDebug("winClipboardProc - Hello\n");
-    ++clipboardRestarts;
 
     /* Do we use Unicode clipboard? */
     fUseUnicode = g_fUnicodeClipboard;
@@ -400,35 +401,6 @@ winClipboardProc(void *pvNotUsed)
     g_pClipboardDisplay = NULL;
     g_hwndClipboard = NULL;
 
-    /* checking if we need to restart */
-    if (clipboardRestarts >= WIN_CLIPBOARD_RETRIES) {
-        /* terminates clipboard thread but the main server still lives */
-        ErrorF
-            ("winClipboardProc - the clipboard thread has restarted %d times and seems to be unstable, disabling clipboard integration\n",
-             clipboardRestarts);
-        g_fClipboard = FALSE;
-        return NULL;
-    }
-
-    if (g_fClipboard) {
-        sleep(WIN_CLIPBOARD_DELAY);
-        ErrorF("winClipboardProc - trying to restart clipboard thread \n");
-        /* Create the clipboard client thread */
-        if (!winInitClipboard()) {
-            ErrorF("winClipboardProc - winClipboardInit failed.\n");
-            return NULL;
-        }
-
-        winDebug("winClipboardProc - winInitClipboard returned.\n");
-        /* Flag that clipboard client has been launched */
-        g_fClipboardLaunched = TRUE;
-    }
-    else {
-        ErrorF("winClipboardProc - Clipboard disabled  - Exit from server \n");
-        /* clipboard thread has exited, stop server as well */
-        raise(SIGTERM);
-    }
-
     return NULL;
 }
 
diff --git a/hw/xwin/winclipboardwrappers.c b/hw/xwin/winclipboardwrappers.c
index bfd6bff..05a8a28 100644
--- a/hw/xwin/winclipboardwrappers.c
+++ b/hw/xwin/winclipboardwrappers.c
@@ -163,9 +163,6 @@ winProcEstablishConnection(ClientPtr client)
         ErrorF("winProcEstablishConnection - winInitClipboard returned.\n");
     }
 
-    /* Flag that clipboard client has been launched */
-    g_fClipboardLaunched = TRUE;
-
     return iReturn;
 }
 
commit 0bb6eae4e34634abb2679004ace94504a4d65964
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Mon Jun 17 00:07:01 2013 +0100

    hw/xwin: Push winClipboardShutdown() into winclipboardinit.c
    
    Push winClipboardShutdown() into winclipboardinit.c
    This lets us make g_ptClipboardProc static
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/InitOutput.c b/hw/xwin/InitOutput.c
index 6b5c38d..88bc85a 100644
--- a/hw/xwin/InitOutput.c
+++ b/hw/xwin/InitOutput.c
@@ -66,24 +66,11 @@ typedef WINAPI HRESULT(*SHGETFOLDERPATHPROC) (HWND hwndOwner,
 /*
  * References to external symbols
  */
-#ifdef XWIN_CLIPBOARD
-extern Bool g_fUnicodeClipboard;
-extern Bool g_fClipboardLaunched;
-extern Bool g_fClipboardStarted;
-extern pthread_t g_ptClipboardProc;
-extern HWND g_hwndClipboard;
-extern Bool g_fClipboard;
-#endif
 
 /*
  * Function prototypes
  */
 
-#ifdef XWIN_CLIPBOARD
-static void
- winClipboardShutdown(void);
-#endif
-
 static Bool
  winCheckDisplayNumber(void);
 
@@ -125,31 +112,6 @@ static PixmapFormatRec g_PixmapFormats[] = {
 
 const int NUMFORMATS = sizeof(g_PixmapFormats) / sizeof(g_PixmapFormats[0]);
 
-#ifdef XWIN_CLIPBOARD
-static void
-winClipboardShutdown(void)
-{
-    /* Close down clipboard resources */
-    if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
-        /* Synchronously destroy the clipboard window */
-        if (g_hwndClipboard != NULL) {
-            SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
-            /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
-        }
-        else
-            return;
-
-        /* Wait for the clipboard thread to exit */
-        pthread_join(g_ptClipboardProc, NULL);
-
-        g_fClipboardLaunched = FALSE;
-        g_fClipboardStarted = FALSE;
-
-        winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
-    }
-}
-#endif
-
 static const ExtensionModule xwinExtensions[] = {
 #ifdef GLXEXT
   { GlxExtensionInit, "GLX", &noGlxExtension },
diff --git a/hw/xwin/win.h b/hw/xwin/win.h
index a738a59..1a882f4 100644
--- a/hw/xwin/win.h
+++ b/hw/xwin/win.h
@@ -794,6 +794,9 @@ Bool
 
 void
  winFixClipboardChain(void);
+
+void
+ winClipboardShutdown(void);
 #endif
 
 /*
diff --git a/hw/xwin/winclipboardinit.c b/hw/xwin/winclipboardinit.c
index 157006d..e6bbf17 100644
--- a/hw/xwin/winclipboardinit.c
+++ b/hw/xwin/winclipboardinit.c
@@ -46,10 +46,17 @@ int winProcSetSelectionOwner(ClientPtr /* client */ );
  * References to external symbols
  */
 
-extern pthread_t g_ptClipboardProc;
 extern winDispatchProcPtr winProcSetSelectionOwnerOrig;
 extern Bool g_fClipboard;
 extern HWND g_hwndClipboard;
+extern Bool g_fClipboardLaunched;
+extern Bool g_fClipboardStarted;
+
+/*
+ * Local variables
+ */
+
+static pthread_t g_ptClipboardProc;
 
 /*
  * Intialize the Clipboard module
@@ -76,6 +83,29 @@ winInitClipboard(void)
     return TRUE;
 }
 
+void
+winClipboardShutdown(void)
+{
+  /* Close down clipboard resources */
+  if (g_fClipboard && g_fClipboardLaunched && g_fClipboardStarted) {
+    /* Synchronously destroy the clipboard window */
+    if (g_hwndClipboard != NULL) {
+      SendMessage(g_hwndClipboard, WM_DESTROY, 0, 0);
+      /* NOTE: g_hwndClipboard is set to NULL in winclipboardthread.c */
+    }
+    else
+      return;
+
+    /* Wait for the clipboard thread to exit */
+    pthread_join(g_ptClipboardProc, NULL);
+
+    g_fClipboardLaunched = FALSE;
+    g_fClipboardStarted = FALSE;
+
+    winDebug("winClipboardShutdown - Clipboard thread has exited.\n");
+  }
+}
+
 /*
  * Create the Windows window that we use to receive Windows messages
  */
diff --git a/hw/xwin/winglobals.c b/hw/xwin/winglobals.c
index b9ad294..b0d6ffc 100644
--- a/hw/xwin/winglobals.c
+++ b/hw/xwin/winglobals.c
@@ -96,7 +96,6 @@ Bool g_fUnicodeClipboard = TRUE;
 Bool g_fClipboard = TRUE;
 Bool g_fClipboardLaunched = FALSE;
 Bool g_fClipboardStarted = FALSE;
-pthread_t g_ptClipboardProc;
 HWND g_hwndClipboard = NULL;
 void *g_pClipboardDisplay = NULL;
 Window g_iClipboardWindow = None;
commit 6343b531d786dd4a9bb52050c9ef267a04374b57
Author: Jon TURNEY <jon.turney at dronecode.org.uk>
Date:   Wed Jan 1 17:54:48 2014 +0000

    hw/xwin: Remove left-over pthread_exit() in clipboard code
    
    Commit c1bf3baa44fbd8af33a2b3ce045324485b85a7a7 removed all but one of the
    pthread_exit() calls which used to call winClipboardThreadExit()
    
    Fix the final remaining one to exit via done label on IOError instead.
    
    Also fix a comment and report pre-flush failure to log, but do not exit
    
    Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    Reviewed-by: Colin Harrison <colin.harrison at virgin.net>

diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index e708960..4a9eb4c 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -141,7 +141,7 @@ winClipboardProc(void *pvNotUsed)
     else if (iReturn == WIN_JMP_ERROR_IO) {
         /* TODO: Cleanup the Win32 window and free any allocated memory */
         ErrorF("winClipboardProc - setjmp returned for IO Error Handler.\n");
-        pthread_exit(NULL);
+        goto winClipboardProc_Done;
     }
 
     /* Use our generated cookie for authentication */
@@ -184,7 +184,7 @@ winClipboardProc(void *pvNotUsed)
         goto winClipboardProc_Done;
     }
 
-    /* Save the display in the screen privates */
+    /* Save the display in a global used by the wndproc */
     g_pClipboardDisplay = pDisplay;
 
     ErrorF("winClipboardProc - XOpenDisplay () returned and "
@@ -269,8 +269,9 @@ winClipboardProc(void *pvNotUsed)
     winClipboardFlushXEvents(hwnd, iWindow, pDisplay, fUseUnicode);
 
     /* Pre-flush Windows messages */
-    if (!winClipboardFlushWindowsMessageQueue(hwnd))
-        return 0;
+    if (!winClipboardFlushWindowsMessageQueue(hwnd)) {
+        ErrorF("winClipboardProc - winClipboardFlushWindowsMessageQueue failed\n");
+    }
 
     /* Signal that the clipboard client has started */
     g_fClipboardStarted = TRUE;


More information about the xorg-commit mailing list