diff options
-rw-r--r-- | .gitignore | 24 | ||||
-rw-r--r-- | AUTHORS | 17 | ||||
-rw-r--r-- | COPYING | 20 | ||||
-rw-r--r-- | ChangeLog | 102 | ||||
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | README | 1 | ||||
-rwxr-xr-x | autogen.sh | 14 | ||||
-rw-r--r-- | configure.ac | 34 | ||||
-rw-r--r-- | textconv.c | 152 | ||||
-rw-r--r-- | textconv.h | 44 | ||||
-rw-r--r-- | wndproc.c | 86 | ||||
-rw-r--r-- | wndproc.h | 61 | ||||
-rw-r--r-- | xevents.c | 744 | ||||
-rw-r--r-- | xevents.h | 44 | ||||
-rw-r--r-- | xwinclip.c | 578 | ||||
-rw-r--r-- | xwinclip.man | 4 |
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 @@ -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. @@ -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 @@ -0,0 +1 @@ + @@ -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 + |