From 38dcfd7e18eddd28309458a63d10eb5692e4e2ea Mon Sep 17 00:00:00 2001 From: Jon TURNEY Date: Thu, 13 Jun 2013 14:01:33 +0100 Subject: xwinclip 1.2.0 import --- .gitignore | 24 ++ AUTHORS | 17 ++ COPYING | 20 ++ ChangeLog | 102 ++++++++ Makefile.am | 11 + NEWS | 1 + README | 1 + autogen.sh | 14 ++ configure.ac | 34 +++ textconv.c | 152 ++++++++++++ textconv.h | 44 ++++ wndproc.c | 86 +++++++ wndproc.h | 61 +++++ xevents.c | 744 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ xevents.h | 44 ++++ xwinclip.c | 578 ++++++++++++++++++++++++++++++++++++++++++++++ xwinclip.man | 4 + 17 files changed, 1937 insertions(+) create mode 100644 .gitignore create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 textconv.c create mode 100644 textconv.h create mode 100644 wndproc.c create mode 100644 wndproc.h create mode 100644 xevents.c create mode 100644 xevents.h create mode 100644 xwinclip.c create mode 100644 xwinclip.man 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 + * 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 + * 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 + * general Add support for -display and --display command-line + parameters. + +2003-12-29 Benjamin Riefenstahl + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 +#include + + +/* + * 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 +#include + + +/* + * 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 +#include +#include + + +/* X headers */ +#include +#include +#include +#include +#include + + +/* 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 +#include + + +/* 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 +#include +#include +#include +#include + +/* X headers */ +#include +#include +#include +#include +#include +#ifdef X_LOCALE +#include +#else /* X_LOCALE */ +#include +#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 +#include + +/* Other headers */ +#include + +/* 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 + -- cgit v1.2.3