summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore24
-rw-r--r--AUTHORS17
-rw-r--r--COPYING20
-rw-r--r--ChangeLog102
-rw-r--r--Makefile.am11
-rw-r--r--NEWS1
-rw-r--r--README1
-rwxr-xr-xautogen.sh14
-rw-r--r--configure.ac34
-rw-r--r--textconv.c152
-rw-r--r--textconv.h44
-rw-r--r--wndproc.c86
-rw-r--r--wndproc.h61
-rw-r--r--xevents.c744
-rw-r--r--xevents.h44
-rw-r--r--xwinclip.c578
-rw-r--r--xwinclip.man4
17 files changed, 1937 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d56144d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+*.la
+*.lo
+*.o
+.deps/
+.libs/
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+mkinstalldirs
+stamp-h1
+xwinclip.exe
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..27ef345
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,17 @@
+Harold L Hunt II:
+Initial author.
+
+Brian Genisio:
+DOS to UNIX and vice versa functions.
+
+Kensuke Matsuzaki:
+Non-U.S. text support.
+
+Chris Twiner:
+Use setjmp and lngjmp to catch server shutdown/reset.
+
+Benjamin Riefenstahl:
+Bug fix for call to PeekMessage.
+
+Jeremy Wilkins:
+Add support for -display and --display command-line parameters.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..58c120e
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright (C) 2000-2003 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.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..86cd0c5
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,102 @@
+2003-10-29 Kensuke Matsuzaki <zakki@peppermint.jp>
+ * xevents.c, xwinclip.c Backport of the patch that fixes the crash
+ with large text, enables non-ascii copy and paste, and adds
+ -nounicodeclipboard command-line parameter.
+
+2003-10-29 Harold L Hunt II <huntharo@msu.edu>
+ * general Fix compilation warnings for printf () calls.
+ * Imakefile Enable builds outside the xc/programs try (use xmkmf).
+ * configure.ac, Makefile.am, AUTHORS, ChangeLog, COPYING, INSTALL,
+ NEWS, README, VERSION
+ New automake/autoconf build system.
+
+2003-01-12 Jeremy Wilkins <jeb@jeremywilkins.freeserve.co.uk>
+ * general Add support for -display and --display command-line
+ parameters.
+
+2003-12-29 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
+ * wndproc.c Pass NULL to PeekMessage instead of the hwnd for our
+ messaging window, since this was causing some vital messages to be
+ filtered out.
+
+2003-12-29 Chris Twiner <>
+ * xwinclip.c Use setjmp and longjmp to gracefully catch IO Errors
+ and restart the process from the entry point. This should allow
+ xwinclip to continue running when the X Server resets.
+
+2002-06-22 Kensuke Matsuzaki <zakki@peppermint.jp>
+ * xevents.c, xevents.h, xwinclip.c Add real support for
+ COMPOUND_TEXT, TARGETS, and UTF8_STRING selection types. Grab
+ clipboard contents in Unicode, if supported, convert to multi-byte
+ character set, then stick the result into the appropriate
+ target. This allows Japanese text to be transferred via
+ xwinclip. Other eastern languages (Korean, Chinese, etc.) may also
+ work.
+
+2002-06-22 Harold L Hunt II <huntharo@msu.edu>
+ * xwinclip.c Add a UnicodeSupport function to check if we have
+ Unicode support or not. Currently this is done by just checking if
+ we are on an NT-based platform or not.
+
+2002-06-12 Harold L Hunt II <huntharo@msu.edu>
+ * xwinclip.c Break this single source file into xwinclip.c,
+ textconv.c, textconv.h, wndproc.c, wndproc.h, xevents.c, and
+ xevents.h.
+ * xwinclip.c Pause and loop to retry, after a delay, if we fail
+ while opening the display.
+ * xwinclip.c Remove a call to XSelectInput that was operating on
+ our own window and always returning BadWindow. Apparently the
+ event mask for our own window has to be changed with
+ XChangeWindowAttributes. I've put a #if0'd example of using
+ XChangeWindowAttributes into the file.
+ * xwinclip.c Remove a call to XFlush. It doesn't seem necessary
+ to flush any events in our queue before we start processing
+ events. However, I may have read somewhere that we have to do
+ this, so I may have to re-add this call to XFlush later.
+ * xwinclip.c Create an atom for WM_DELETE_WINDOW. This will get is
+ an X event when a window manager is about to kill us. However, it
+ does nothing for the case where the server is told to GiveUp ().
+ * xwinclip.c In CreateMessagingWindow, add a call to ShowWindow
+ passing SW_HIDE and add a call to UpdateWindow. I'm not sure, but
+ these may be necessary to kick off Windows event processing. On a
+ strange note - the current xwinclip doesn't process any Windows
+ messages.
+ * xevents.c Add handling for WM_DELETE_WINDOW.
+
+2002-06-10 Harold L Hunt II <huntharo@msu.edu>
+ * xwinclip.c Use select () in ConnectionNumber(pDisplay) and
+ /dev/windows instead of calling XNextEvent, which blocks until the
+ next event. This has many benefits: Windows messages are now
+ processed almost immediately after they come in (the old approach
+ could take minutes), we can catch the X shutdown and restart
+ messages rather than having XNextEvent call exit () when it sees
+ that the connection has closed (we don't currently catch these
+ events), and the clipboard integration code can now be rewritten
+ with the assumption that we can and will see the Windows events
+ when they arrive without an X event immediately preceeding them
+ (which may allow us to stop stealing ownership of the X
+ selection).
+ * xwinclip.c Move the X event loop into new function
+ FlushXEventQueue.
+
+2001-10-23 Harold L Hunt II <huntharo@msu.edu>
+ * xwinclip.c Add UNIXtoDOS () function to change \n to \r\n when
+ copying text from an X client to the Windows clipboard. Call the
+ function right before calling OpenClipboard ().
+
+2001-10-22 Brian Genisio <>
+ * xwinclip.c Line 327 - Pass strlen (pszGlobalData) instead of
+ strlen (pszGlobalData) + 1 to XChangeProperty (). This eliminates
+ the trailing ^@ when pasting to certain X applications, such as
+ Emacs.
+
+2001-10-22 Harold L Hunt II, Brian Genisio, Cygwin Project
+ * xwinclip.c Add DOStoUNIX () function to change \r\n to \n when
+ copying text from the Windows clipboard to an X client. Call the
+ function right before calling XChangeProperty ().
+
+2001-09-02 Harold L Hunt II <huntharo@msu.edu>
+ * general Copy text selections from Windows into Cygwin/XFree86
+ when requested.
+ * general Copy text selections from Cygwin/XFree86 into Windows
+ when requested.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..85f7bc1
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,11 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+
+SUBDIRS = .
+
+man_MANS = xwinclip.man
+EXTRA_DIST = $(man_MANS)
+
+bin_PROGRAMS = xwinclip
+xwinclip_SOURCES = xwinclip.c textconv.c wndproc.c xevents.c \
+ textconv.h wndproc.h xevents.h
+xwinclip_LDADD = $(X_LIBS) -lX11 -lgdi32
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+
diff --git a/README b/README
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..dd0731a
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf --force -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+if test -z "$NOCONFIGURE"; then
+ exec $srcdir/configure "$@"
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..cfbd6ee
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,34 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl Auto* initialization
+AC_INIT(xwinclip, 1.2.0)
+AC_CONFIG_SRCDIR(xwinclip.c)
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+dnl Checks for libraries.
+
+
+
+dnl Checks for header files.
+
+
+
+dnl Checks for library functions.
+AC_PATH_X
+AC_PATH_XTRA
+
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+
+
diff --git a/textconv.c b/textconv.c
new file mode 100644
index 0000000..df02006
--- /dev/null
+++ b/textconv.c
@@ -0,0 +1,152 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#include "textconv.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*
+ * Convert \r\n to \n
+ *
+ * NOTE: This was heavily inspired by, if not down right stolen from,
+ * Cygwin's winsup/cygwin/fhandler.cc/fhandler_base::read ()
+ */
+
+void
+DOStoUNIX (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
+UNIXtoDOS (unsigned char **ppszData, int iLength)
+{
+ int iNewlineCount = 0;
+ unsigned char *pszSrc = *ppszData;
+ unsigned char *pszEnd = pszSrc + iLength;
+ unsigned char *pszDest = NULL, *pszDestBegin = NULL;
+
+#if 0
+ printf ("UNIXtoDOS () - Original data:\n%s\n", *ppszData);
+#endif
+
+ /* 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;
+
+#if 0
+ printf ("UNIXtoDOS () - Final string:\n%s\n", pszDestBegin);
+#endif
+}
diff --git a/textconv.h b/textconv.h
new file mode 100644
index 0000000..3d7463e
--- /dev/null
+++ b/textconv.h
@@ -0,0 +1,44 @@
+#if !defined(TEXTCONV_H)
+#define TEXTCONV_H 1
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+
+/*
+ * Function prototypes
+ */
+
+void
+DOStoUNIX (char *pszData, int iLength);
+
+void
+UNIXtoDOS (unsigned char **ppszData, int iLength);
+
+#endif
diff --git a/wndproc.c b/wndproc.c
new file mode 100644
index 0000000..6a9b672
--- /dev/null
+++ b/wndproc.c
@@ -0,0 +1,86 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+#include "wndproc.h"
+
+
+/*
+ * Process a given Windows message
+ */
+
+LRESULT CALLBACK
+WindowProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ /* Branch on message type */
+ switch (message)
+ {
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ return 0;
+
+ case WM_CREATE:
+#if 0
+ printf ("WindowProc - WM_CREATE\n");
+#endif
+ return 0;
+ }
+
+ /* Let Windows perform default processing for unhandled messages */
+ return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+
+/*
+ * Process any pending Windows messages
+ */
+
+BOOL
+FlushWindowsMessageQueue (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/wndproc.h b/wndproc.h
new file mode 100644
index 0000000..eb1adf3
--- /dev/null
+++ b/wndproc.h
@@ -0,0 +1,61 @@
+#if !defined (WNDPROC_H)
+#define WNDPROC_H 1
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+/* Fixups to prevent collisions between Windows and X headers */
+#undef MINSHORT
+#undef MAXSHORT
+
+/* Flags for Windows header options */
+#define NONAMELESSUNION
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+/* Windows headers */
+#include <windows.h>
+#include <windowsx.h>
+
+
+/*
+ * Function prototypes
+ */
+
+BOOL
+FlushWindowsMessageQueue (HWND hwnd);
+
+LRESULT CALLBACK
+WindowProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+#endif
+
+
diff --git a/xevents.c b/xevents.c
new file mode 100644
index 0000000..cee49a7
--- /dev/null
+++ b/xevents.c
@@ -0,0 +1,744 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+
+/* Standard library headers */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* X headers */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+
+/* Fixups to prevent collisions between Windows and X headers */
+#undef MINSHORT
+#undef MAXSHORT
+
+/* Flags for Windows header options */
+#define NONAMELESSUNION
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+/* Windows headers */
+#include <windows.h>
+#include <windowsx.h>
+
+
+/* Application constants */
+#define WINDOW_CLASS "xwinclip"
+#define WINDOW_TITLE "xwinclip"
+#define WIN_MSG_QUEUE_FNAME "/dev/windows"
+#define WIN_USE_SELECT 1
+
+
+/* Local headers */
+#include "xevents.h"
+#include "textconv.h"
+
+
+extern Atom atomClipboard;
+
+
+/*
+ * Process any pending X events
+ */
+
+Bool
+FlushXEvents (HWND hwnd, Atom atomLocalProperty, Atom atomUTF8String,
+ Atom atomCompoundText, Atom atomTargets, Atom atomDeleteWindow,
+ int iWindow, Display *pDisplay,
+ Bool fUnicodeSupport)
+{
+#if 0
+ Atom atomReturnType;
+ int iReturnFormat;
+ unsigned long ulReturnItems;
+#endif
+ XTextProperty xtpText;
+ XEvent event;
+ XSelectionEvent eventSelection;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+ char *pszGlobalData = NULL;
+ int iReturn;
+ HGLOBAL hGlobal;
+ Bool fReturn = TRUE;
+ XICCEncodingStyle xiccesStyle;
+ int iConvertDataLen = 0;
+ char *pszConvertData = NULL;
+ char *pszTextList[2];
+ int iCount;
+ char **ppszTextList = NULL;
+ wchar_t *pwszUnicodeStr = NULL;
+ int iUnicodeLen = 0;
+ int iReturnDataLen = 0;
+ int i;
+
+ /* Process all pending events */
+ while (XPending (pDisplay))
+ {
+ /* Get the next event - will not block because one is ready */
+ XNextEvent (pDisplay, &event);
+
+ /* Branch on the event type */
+ switch (event.type)
+ {
+ case ClientMessage:
+ if (event.xclient.data.l[0] == atomDeleteWindow)
+ {
+ printf ("\nReceived WM_DELETE_WINDOW\n\n");
+ fReturn = FALSE;
+ }
+ else
+ printf ("\nUnknown ClientMessage\n\n");
+ break;
+
+ case SelectionClear:
+ /* Request the lost selection contents */
+ iReturn = XConvertSelection (pDisplay,
+ event.xselectionclear.selection,
+ atomCompoundText,
+ atomLocalProperty,
+ iWindow,
+ CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("SelectionClear - XConvertSelection () failed\n");
+ exit (1);
+ }
+ break;
+
+
+ /*
+ * SelectionRequest
+ */
+
+ case SelectionRequest:
+#if 0
+ printf ("SelectionRequest - target %d\n",
+ event.xselectionrequest.target);
+ printf ("SelectionRequest - Target atom name %s\n",
+ XGetAtomName (pDisplay, event.xselectionrequest.target));
+#endif
+
+ /* Abort if invalid target type */
+ if (event.xselectionrequest.target != XA_STRING
+ && event.xselectionrequest.target != atomUTF8String
+ && event.xselectionrequest.target != atomCompoundText
+ && event.xselectionrequest.target != atomTargets)
+ {
+ /* 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)
+ {
+ printf ("XSendEvent () failed\n");
+ exit (1);
+ }
+
+ break;
+ }
+
+ /* Handle targets type of request */
+ if (event.xselectionrequest.target == atomTargets)
+ {
+ Atom atomTargetArr[4] = {atomTargets,
+ atomCompoundText,
+ atomUTF8String,
+ XA_STRING};
+
+ /* Try to change the property */
+ iReturn = XChangeProperty (pDisplay,
+ event.xselectionrequest.requestor,
+ event.xselectionrequest.property,
+ event.xselectionrequest.target,
+ 8,
+ PropModeReplace,
+ (char *) atomTargetArr,
+ sizeof (atomTargetArr));
+ if (iReturn == BadAlloc
+ || iReturn == BadAtom
+ || iReturn == BadMatch
+ || iReturn == BadValue
+ || iReturn == BadWindow)
+ {
+ printf ("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)
+ {
+ printf ("XSendEvent () failed\n");
+ }
+ break;
+ }
+
+ /* Access the clipboard */
+ if (!OpenClipboard (hwnd))
+ {
+ printf ("OpenClipboard () failed: %08x\n",
+ (unsigned int) GetLastError ());
+ exit (1);
+ }
+
+ /* Setup the string style */
+ if (event.xselectionrequest.target == XA_STRING)
+ xiccesStyle = XStringStyle;
+ else if (event.xselectionrequest.target == atomUTF8String)
+ xiccesStyle = XUTF8StringStyle;
+ else if (event.xselectionrequest.target == atomCompoundText)
+ xiccesStyle = XCompoundTextStyle;
+ else
+ xiccesStyle = XStringStyle;
+
+ /*
+ * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
+ */
+
+ /* Get a pointer to the clipboard text */
+ if (fUnicodeSupport)
+ hGlobal = GetClipboardData (CF_UNICODETEXT);
+ else
+ hGlobal = GetClipboardData (CF_TEXT);
+ if (!hGlobal)
+ {
+ printf ("GetClipboardData () failed: %08x\n",
+ (unsigned int) GetLastError ());
+ exit (1);
+ }
+ pszGlobalData = (char *) GlobalLock (hGlobal);
+
+ /* Convert the Unicode string to UTF8 (MBCS) */
+ if (fUnicodeSupport)
+ {
+ iConvertDataLen = WideCharToMultiByte (CP_UTF8,
+ 0,
+ (LPCWSTR)pszGlobalData,
+ -1,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ pszConvertData = (char *) malloc (iConvertDataLen); /* Don't need +1 */
+ 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 */
+ DOStoUNIX (pszConvertData, strlen (pszConvertData));
+
+ /* Setup our text list */
+ pszTextList[0] = pszConvertData;
+ pszTextList[1] = NULL;
+
+ /* Initialize the text property */
+ xtpText.value = NULL;
+
+ /* Create the text property from the text list */
+ if (fUnicodeSupport)
+ {
+ iReturn = Xutf8TextListToTextProperty (pDisplay,
+ pszTextList,
+ 1,
+ xiccesStyle,
+ &xtpText);
+ }
+ else
+ {
+ iReturn = XmbTextListToTextProperty (pDisplay,
+ pszTextList,
+ 1,
+ xiccesStyle,
+ &xtpText);
+ }
+ if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
+ {
+ printf ("SelectionRequest - X*TextListToTextProperty "
+ "failed: %d\n",
+ iReturn);
+ exit(1);
+ }
+
+ /* Free the converted string */
+ free (pszConvertData);
+
+ /*
+ * FIXME: Pass pszGlobalData and strlen (pszGlobalData(
+ * on 1 byte, pass xtpText.value and xtpText.nitems
+ * on 2 byte.
+ */
+
+ /* 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)
+ {
+ printf ("SelectionRequest - XChangeProperty failed: %d\n",
+ iReturn);
+ exit (1);
+ }
+
+ /* Release the clipboard data */
+ GlobalUnlock (hGlobal);
+ pszGlobalData = NULL;
+ CloseClipboard ();
+
+ /* FIXME: Don't clean up on 1 byte. */
+ XFree (xtpText.value);
+ xtpText.value = NULL;
+
+ /* 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)
+ {
+ printf ("XSendEvent () failed\n");
+ exit (1);
+ }
+ break;
+
+
+ /*
+ * SelectionNotify
+ */
+
+ case SelectionNotify:
+#if 0
+ printf ("SelectionNotify\n");
+#endif
+
+#if 0
+ /*
+ * TEMP: Bail if selection is anything other than CLIPBOARD
+ */
+
+ if (event.xselection.selection != atomClipboard)
+ break;
+#endif
+
+ /*
+ *
+ * What are we doing here?
+ *
+ */
+ if (event.xselection.property == None)
+ {
+ if(event.xselection.target == XA_STRING)
+ {
+#if 0
+ printf ("SelectionNotify XA_STRING\n");
+#endif
+ return fReturn;
+ }
+ else if (event.xselection.target == atomUTF8String)
+ {
+ printf ("SelectionNotify UTF8\n");
+ iReturn = XConvertSelection (pDisplay,
+ event.xselection.selection,
+ XA_STRING,
+ atomLocalProperty,
+ iWindow,
+ CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("SelectionNotify - XConvertSelection () "
+ "failed\n");
+ exit (1);
+ }
+ return fReturn;
+ }
+ else if (event.xselection.target == atomCompoundText)
+ {
+ printf ("SelectionNotify CompoundText\n");
+ iReturn = XConvertSelection (pDisplay,
+ event.xselection.selection,
+ atomUTF8String,
+ atomLocalProperty,
+ iWindow,
+ CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("SelectionNotify - XConvertSelection () "
+ "failed\n");
+ exit (1);
+ }
+ return fReturn;
+ }
+ else
+ {
+ printf("Unknown format\n");
+ return fReturn;
+ }
+ }
+
+ /* 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)
+ {
+ printf ("SelectionNotify - XGetWindowProperty () failed\n");
+ exit (1);
+ }
+
+#if 0
+ printf ("SelectionNotify - returned data %d left %d\n",
+ xtpText.nitems, ulReturnBytesLeft);
+#endif
+
+ /* 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)
+ {
+ printf ("SelectionNotify - XGetWindowProperty () failed\n");
+ exit (1);
+ }
+
+#if 0
+ {
+ char *pszAtomName = NULL;
+
+ printf ("SelectionNotify - returned data %d left %d\n",
+ prop.nitems, ulReturnBytesLeft);
+
+ pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
+ ErrorF ("Notify atom name %s\n", pszAtomName);
+ XFree (pszAtomName);
+ pszAtomName = NULL;
+ }
+#endif
+
+ /* Convert the text property to a text list */
+ if (fUnicodeSupport)
+ {
+ iReturn = Xutf8TextPropertyToTextList (pDisplay,
+ &xtpText,
+ &ppszTextList,
+ &iCount);
+ }
+ else
+ {
+ iReturn = XmbTextPropertyToTextList (pDisplay,
+ &xtpText,
+ &ppszTextList,
+ &iCount);
+ }
+ if (iReturn == Success || iReturn > 0)
+ {
+ /* Conversion succeeded or some unconvertible characters */
+ if (ppszTextList != NULL)
+ {
+ 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
+ {
+ printf ("winClipboardFlushXEvents - SelectionNotify - "
+ "X*TextPropertyToTextList list_return is NULL\n");
+ pszReturnData = malloc (1);
+ pszReturnData[0] = '\0';
+ }
+ }
+ else
+ {
+ switch (iReturn)
+ {
+ case XNoMemory:
+ printf ("winClipboardFlushXEvents - SelectionNotify - XNoMemory\n");
+ break;
+ case XConverterNotFound:
+ printf ("winClipboardFlushXEvents - SelectionNotify - XConverterNotFound\n");
+ break;
+ default:
+ printf ("winClipboardFlushXEvents - SelectionNotify - Unknown Error\n");
+ break;
+ }
+ pszReturnData = malloc (1);
+ pszReturnData[0] = '\0';
+ }
+
+ /* Free the data returned from XGetWindowProperty */
+ XFreeStringList (ppszTextList);
+ XFree (xtpText.value);
+
+ /* Convert the X clipboard string to DOS format */
+ UNIXtoDOS (&pszReturnData, strlen (pszReturnData));
+
+ if (fUnicodeSupport)
+ {
+ /* 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
+ = (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
+
+ /* Do the actual conversion */
+ MultiByteToWideChar (CP_UTF8,
+ 0,
+ pszReturnData,
+ -1,
+ pwszUnicodeStr,
+ iUnicodeLen);
+ }
+ else
+ {
+ pszConvertData = strdup (pszReturnData);
+ iConvertDataLen = strlen (pszConvertData) + 1;
+ }
+
+ /* Access the Windows clipboard */
+ if (!OpenClipboard (hwnd))
+ {
+ printf ("OpenClipboard () failed: %08x\n",
+ (unsigned int) GetLastError ());
+ exit (1);
+ }
+
+ /* Take ownership of the Window clipboard */
+ if (!EmptyClipboard ())
+ {
+ printf ("EmptyClipboard () failed: %08x\n",
+ (unsigned int) GetLastError ());
+ exit (1);
+ }
+
+ /* Allocate global memory for the X clipboard data */
+ if (fUnicodeSupport)
+ hGlobal = GlobalAlloc (GMEM_MOVEABLE,
+ sizeof (wchar_t) * (iUnicodeLen + 1));
+ else
+ hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
+
+ /* Obtain a pointer to the global memory */
+ pszGlobalData = GlobalLock (hGlobal);
+ if (pszGlobalData == NULL)
+ {
+ printf ("Could not lock global memory for clipboard transfer\n");
+ exit (1);
+ }
+
+ /* Copy the returned string into the global memory */
+ if (fUnicodeSupport)
+ memcpy (pszGlobalData,
+ pwszUnicodeStr,
+ sizeof (wchar_t) * (iUnicodeLen + 1));
+ else
+ strcpy (pszGlobalData, pszConvertData);
+
+ /* Free the data returned from XGetWindowProperty */
+ if (fUnicodeSupport)
+ {
+ free (pwszUnicodeStr);
+ pwszUnicodeStr = NULL;
+ }
+ else
+ {
+ free (pszConvertData);
+ pszConvertData = NULL;
+ }
+
+ /* Release the pointer to the global memory */
+ GlobalUnlock (hGlobal);
+ pszGlobalData = NULL;
+
+ /* Push the selection data to the Windows clipboard */
+ if (fUnicodeSupport)
+ SetClipboardData (CF_UNICODETEXT, hGlobal);
+ else
+ SetClipboardData (CF_TEXT, hGlobal);
+
+ /*
+ * NOTE: Do not try to free pszGlobalData, it is owned by
+ * Windows after the call to SetClipboardData ().
+ */
+
+ /* Release the clipboard */
+ if (!CloseClipboard ())
+ {
+ printf ("CloseClipboard () failed: %08x\n",
+ (unsigned int) GetLastError ());
+ exit (1);
+ }
+
+ /* Reassert ownership of the selection */
+ iReturn = XSetSelectionOwner (pDisplay,
+ event.xselection.selection,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("SelectionNotify - Could not reassert ownership "
+ "of selection ATOM: %s\n",
+ XGetAtomName (pDisplay,
+ event.xselection.selection));
+ exit (1);
+ }
+ else
+ {
+ printf ("SelectionNotify - Reasserted ownership of ATOM: %s\n",
+ XGetAtomName (pDisplay,
+ event.xselection.selection));
+ }
+#if 0
+ /* Reassert ownership of the CLIPBOARD */
+ iReturn = XSetSelectionOwner (pDisplay,
+ atomClipboard,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("Could not reassert ownership of selection\n");
+ exit (1);
+ }
+#endif
+ break;
+
+#if 0
+ case CreateNotify:
+ printf ("FlushXEvents - CreateNotify parent: %ld\twindow: %ld\n",
+ event.xcreatewindow.parent, event.xcreatewindow.window);
+ break;
+
+ case DestroyNotify:
+ printf ("FlushXEvents - DestroyNotify window: %ld\tevent: %ld\n",
+ event.xdestroywindow.window, event.xdestroywindow.event);
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ return fReturn;
+}
diff --git a/xevents.h b/xevents.h
new file mode 100644
index 0000000..95fad29
--- /dev/null
+++ b/xevents.h
@@ -0,0 +1,44 @@
+#if !defined (XEVENTS_H)
+#define XEVENTS_H 1
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+
+/*
+ * Function prototypes
+ */
+
+Bool
+FlushXEvents (HWND hwnd, Atom atomLocalProperty, Atom atomUTF8String,
+ Atom atomCompoundText, Atom atomTargets, Atom atomDeleteWindow,
+ int iWindow, Display *pDisplay,
+ Bool fUnicodeSupport);
+
+#endif
diff --git a/xwinclip.c b/xwinclip.c
new file mode 100644
index 0000000..fa78243
--- /dev/null
+++ b/xwinclip.c
@@ -0,0 +1,578 @@
+/*
+ *Copyright (C) 1994-2000 The XFree86 Project, Inc. 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 THE XFREE86 PROJECT 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 XFree86 Project
+ *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 XFree86 Project.
+ *
+ * Authors: Harold L Hunt II
+ */
+
+
+/* Standard library headers */
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+
+/* X headers */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#ifdef X_LOCALE
+#include <X11/Xlocale.h>
+#else /* X_LOCALE */
+#include <locale.h>
+#endif /* X_LOCALE */
+
+
+/* Fixups to prevent collisions between Windows and X headers */
+#undef MINSHORT
+#undef MAXSHORT
+
+/* Flags for Windows header options */
+#define NONAMELESSUNION
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+/* Windows headers */
+#include <windows.h>
+#include <windowsx.h>
+
+/* Other headers */
+#include <setjmp.h>
+
+/* Application constants */
+#define WINDOW_CLASS "xwinclip"
+#define WINDOW_TITLE "xwinclip"
+#define WIN_MSG_QUEUE_FNAME "/dev/windows"
+#define WIN_USE_SELECT 1
+#define WIN_CONNECT_RETRIES 3
+#define WIN_CONNECT_DELAY 4
+#define WIN_JMP_OKAY 0
+#define WIN_JMP_ERROR_IO 2
+
+
+/* Local headers */
+#include "textconv.h"
+#include "wndproc.h"
+#include "xevents.h"
+
+
+/*
+ * Global variables
+ */
+
+jmp_buf g_jmpEntry;
+Bool g_fUnicodeClipboard = TRUE;
+
+
+/*
+ * Function prototypes
+ */
+
+HWND
+CreateMessagingWindow ();
+
+Bool
+UnicodeSupport ();
+
+
+/*
+ * Local functions
+ */
+
+#if 0
+void
+handle_kill (int i)
+{
+ printf ("\nhandle_kill!\n\n");
+}
+
+int
+error_handler (Display *pDisplay, XErrorEvent *pErrorEvent)
+{
+ printf ("\nerror_handler!\n\n");
+ return 0;
+}
+#endif
+
+int
+error_handler_io (Display *pDisplay)
+{
+ printf ("\nerror_handler_io!\n\n");
+
+ /* Restart at the main entry point */
+ longjmp (g_jmpEntry, WIN_JMP_ERROR_IO);
+
+ return 0;
+}
+
+
+Atom atomClipboard, atomClipboardManager;
+
+
+/*
+ * Main function
+ */
+
+int
+main (int argc, char *argv[])
+{
+#if 0
+ Atom atomClipboard, atomClipboardManager;
+#endif
+ Atom atomLocalProperty, atomCompoundText;
+ Atom atomUTF8String, atomTargets;
+ int iReturn;
+ HWND hwnd = NULL;
+ int iConnectionNumber;
+ int fdMessageQueue;
+ fd_set fdsRead;
+ int iMaxDescriptor;
+ Display *pDisplay;
+ Window iWindow;
+ Atom atomDeleteWindow;
+ Bool fReturn;
+ int iRetries;
+ Bool fUnicodeSupport;
+ char *pszDisplay = NULL;
+ int i;
+
+ /* 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"))
+ {
+ g_fUnicodeClipboard = FALSE;
+ continue;
+ }
+
+ /* Yack when we find a parameter that we don't know about */
+ printf ("Unknown parameter: %s\nExiting.\n", argv[i]);
+ exit (1);
+ }
+
+ /* Set jump point for IO 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 */
+ printf ("setjmp returned: %d exiting\n",
+ iReturn);
+ exit (1);
+ }
+ else if (iReturn == WIN_JMP_ERROR_IO)
+ {
+ printf ("setjmp returned and hwnd: %08x\n", (unsigned int)hwnd);
+ }
+
+ /* Initialize retry count */
+ iRetries = 0;
+
+ /* Do we have Unicode support? */
+ fUnicodeSupport = g_fUnicodeClipboard && UnicodeSupport ();
+ if (fUnicodeSupport)
+ {
+ printf ("Unicode clipboard I/O\n");
+ }
+ else
+ {
+ printf ("Non Unicode clipboard I/O\n");
+ }
+
+#if 0
+ /* Specify our signal handlers */
+ signal (SIGQUIT, handle_kill);
+#endif
+
+ /* Set the current locale? What does this do? */
+ 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\n");
+ exit (1);
+ }
+
+ /* Open the X display */
+ do
+ {
+ pDisplay = XOpenDisplay (pszDisplay);
+ if (pDisplay == NULL)
+ {
+ printf ("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)
+ {
+ printf ("Failed opening the display, giving up\n");
+ return 1;
+ }
+
+ /* Create Windows messaging window */
+ hwnd = CreateMessagingWindow ();
+
+ /* Get our connection number */
+ iConnectionNumber = ConnectionNumber (pDisplay);
+
+ /* Open a file descriptor for the windows message queue */
+ fdMessageQueue = open (WIN_MSG_QUEUE_FNAME, O_RDONLY);
+ if (fdMessageQueue == -1)
+ {
+ printf ("Failed opening %s\n", WIN_MSG_QUEUE_FNAME);
+ exit (1);
+ }
+
+ /* Find max of our file descriptors */
+ iMaxDescriptor = max (fdMessageQueue, iConnectionNumber) + 1;
+
+ /* Select event types to watch */
+ if (XSelectInput (pDisplay,
+ DefaultRootWindow (pDisplay),
+ SubstructureNotifyMask |
+ StructureNotifyMask |
+ PropertyChangeMask) == BadWindow)
+ printf ("XSelectInput generated BadWindow on RootWindow\n\n");
+
+ /* Create a messaging window */
+ iWindow = XCreateSimpleWindow (pDisplay,
+ DefaultRootWindow (pDisplay),
+ 1, 1,
+ 500, 500,
+ 0,
+ BlackPixel (pDisplay, 0),
+ BlackPixel (pDisplay, 0));
+ if (iWindow == 0)
+ {
+ printf ("Could not create a window\n");
+ exit (1);
+ }
+
+#if 0
+ /* Print out our window number */
+ printf ("Window number: %d\n", iWindow);
+#endif
+
+#if 0
+ /* Display the messaging window, as a test */
+ XMapWindow (pDisplay, iWindow);
+#endif
+
+ /* ChangeWindowAttributes can change own window's event mask */
+#if 0
+ attrib.event_mask = StructureNotifyMask;
+ iReturn = XChangeWindowAttributes (pDisplay, iWindow, CWEventMask, &attrib);
+ if (iReturn == BadWindow)
+ printf ("XChangeWindowAttributes gave BadWindow\n");
+ else if (iReturn == BadAccess)
+ printf ("XChangeWindowAttributes gave BadAccess\n");
+ else if (iReturn == BadValue)
+ printf ("XChangeWindowAttributes gave BadValue\n");
+#endif
+
+ /* This looks like our only hope for getting a message before shutdown */
+ /* Register for WM_DELETE_WINDOW message from window manager */
+ atomDeleteWindow = XInternAtom (pDisplay, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols (pDisplay, iWindow, &atomDeleteWindow, 1);
+
+ /* Set error handler */
+#if 0
+ XSetErrorHandler (error_handler);
+#endif
+ XSetIOErrorHandler (error_handler_io);
+
+ /* Create an atom for CLIPBOARD_MANAGER */
+ atomClipboardManager = XInternAtom (pDisplay, "CLIPBOARD_MANAGER", False);
+ if (atomClipboardManager == None)
+ {
+ printf ("Could not create CLIPBOARD_MANAGER atom\n");
+ exit (1);
+ }
+
+ /* Assert ownership of CLIPBOARD_MANAGER */
+ iReturn = XSetSelectionOwner (pDisplay, atomClipboardManager,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("Could not set CLIPBOARD_MANAGER owner\n");
+ exit (1);
+ }
+
+ /* Create an atom for CLIPBOARD */
+ atomClipboard = XInternAtom (pDisplay, "CLIPBOARD", False);
+ if (atomClipboard == None)
+ {
+ printf ("Could not create CLIPBOARD atom\n");
+ exit (1);
+ }
+
+ /* Assert ownership of CLIPBOARD */
+ iReturn = XSetSelectionOwner (pDisplay, atomClipboard,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("Could not set CLIPBOARD owner\n");
+ exit (1);
+ }
+
+ /* Assert ownership of PRIMARY */
+ iReturn = XSetSelectionOwner (pDisplay, XA_PRIMARY,
+ iWindow, CurrentTime);
+ if (iReturn == BadAtom || iReturn == BadWindow)
+ {
+ printf ("Could not set PRIMARY owner\n");
+ exit (1);
+ }
+
+ /* Local property to hold pasted data */
+ atomLocalProperty = XInternAtom (pDisplay, "CYGX_CUT_BUFFER", False);
+ if (atomLocalProperty == None)
+ {
+ printf ("Could not create CYGX_CUT_BUFFER atom\n");
+ exit (1);
+ }
+
+ /* Create an atom for UTF8_STRING */
+ atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
+ if (atomUTF8String == None)
+ {
+ printf ("Could not create UTF8_STRING atom\n");
+ exit (1);
+ }
+
+ /* Create an atom for COMPOUND_TEXT */
+ atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
+ if (atomCompoundText == None)
+ {
+ printf ("Could not create COMPOUND_TEXT atom\n");
+ exit (1);
+ }
+
+ /* Create an atom for TARGETS */
+ atomTargets = XInternAtom (pDisplay, "TARGETS", False);
+ if (atomTargets == None)
+ {
+ printf ("Could not create TARGETS atom\n");
+ exit (1);
+ }
+
+ /* 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.
+ */
+ FlushXEvents (hwnd, atomLocalProperty, atomUTF8String,
+ atomCompoundText, atomTargets, atomDeleteWindow,
+ iWindow, pDisplay,
+ fUnicodeSupport);
+
+ /* Pre-flush Windows messages */
+ if (!FlushWindowsMessageQueue (hwnd))
+ return 0;
+
+ /* 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 (fdMessageQueue, &fdsRead);
+ FD_SET (iConnectionNumber, &fdsRead);
+
+ /* 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 */
+ NULL); /* No timeout */
+ if (iReturn <= 0)
+ {
+ printf ("Call to select () failed: %d. Bailing.\n", iReturn);
+ break;
+ }
+
+ /* Branch on which descriptor became active */
+ if (FD_ISSET (iConnectionNumber, &fdsRead))
+ {
+ /* X event ready */
+#if 0
+ printf ("X event ready\n");
+#endif
+
+ /* Process X events */
+ /* Exit when we see that server is shutting down */
+ fReturn = FlushXEvents (hwnd,
+ atomLocalProperty,
+ atomUTF8String,
+ atomCompoundText,
+ atomTargets,
+ atomDeleteWindow,
+ iWindow, pDisplay,
+ fUnicodeSupport);
+ if (!fReturn)
+ {
+ printf ("Caught WM_DELETE_WINDOW - shutting down\n");
+ break;
+ }
+ }
+
+ /* Check for Windows event ready */
+ if (FD_ISSET (fdMessageQueue, &fdsRead))
+ {
+ /* Windows event ready */
+#if 0
+ printf ("Windows event ready\n");
+#endif
+
+ /* Process Windows messages */
+ if (!FlushWindowsMessageQueue (hwnd))
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Create the Windows window that we use to recieve Windows messages
+ */
+
+HWND
+CreateMessagingWindow ()
+{
+ WNDCLASS wc;
+ HWND hwnd;
+
+ /* Setup our window class */
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = WindowProc;
+ 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 = WINDOW_CLASS;
+ RegisterClass (&wc);
+
+ /* Create the window */
+ hwnd = CreateWindowExA (0, /* Extended styles */
+ WINDOW_CLASS, /* Class name */
+ 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); /* ScreenPrivates */
+ 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;
+}
+
+
+/*
+ * Determine whether we suport Unicode or not.
+ * NOTE: Currently, just check if we are on an NT-based platform or not.
+ */
+
+Bool
+UnicodeSupport ()
+{
+ Bool fReturn = FALSE;
+ OSVERSIONINFO osvi;
+
+ /* Get operating system version information */
+ ZeroMemory (&osvi, sizeof (osvi));
+ osvi.dwOSVersionInfoSize = sizeof (osvi);
+ GetVersionEx (&osvi);
+
+ /* Branch on platform ID */
+ switch (osvi.dwPlatformId)
+ {
+ case VER_PLATFORM_WIN32_NT:
+ /* Engine 4 is supported on NT only */
+ printf ("UnicodeSupport - Windows NT/2000/XP\n");
+ fReturn = TRUE;
+ break;
+
+ case VER_PLATFORM_WIN32_WINDOWS:
+ /* Engine 4 is supported on NT only */
+ printf ("UnicodeSupport - Windows 95/98/Me\n");
+ fReturn = FALSE;
+ break;
+ }
+
+ return fReturn;
+}
diff --git a/xwinclip.man b/xwinclip.man
new file mode 100644
index 0000000..71d791f
--- /dev/null
+++ b/xwinclip.man
@@ -0,0 +1,4 @@
+.TH XWINCLIP 1 __xorgversion__
+.SH NAME
+xwinclip
+