summaryrefslogtreecommitdiff
path: root/xwinclip.c
diff options
context:
space:
mode:
Diffstat (limited to 'xwinclip.c')
-rw-r--r--xwinclip.c578
1 files changed, 578 insertions, 0 deletions
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;
+}