Пример #1
0
// retrieve a text property from a window
// technically we could use window_get_prop(), but this is better for character set support
char* window_get_text_prop ( Display *display, Window w, Atom atom )
{
    XTextProperty prop;
    char          *res   = NULL;
    char          **list = NULL;
    int           count;

    if ( XGetTextProperty ( display, w, &prop, atom ) && prop.value && prop.nitems ) {
        if ( prop.encoding == XA_STRING ) {
            size_t l = strlen ( ( char *) prop.value ) + 1;
            res = g_malloc ( l );
            // make clang-check happy.
            if ( res ) {
                g_strlcpy ( res, ( char * ) prop.value, l );
            }
        }
        else if ( Xutf8TextPropertyToTextList ( display, &prop, &list, &count ) >= Success && count > 0 && *list ) {
            size_t l = strlen ( *list ) + 1;
            res = g_malloc ( l );
            // make clang-check happy.
            if ( res ) {
                g_strlcpy ( res, *list, l );
            }
            XFreeStringList ( list );
        }
    }

    if ( prop.value ) {
        XFree ( prop.value );
    }

    return res;
}
Пример #2
0
// Thanks zcodes!
char *get_window_name(Window win)
{
    XTextProperty text_property;
    Status status = XGetWMName(server.display, win, &text_property);
    if (!status || !text_property.value || !text_property.nitems) {
        return strdup("");
    }

    char **name_list;
    int count;
    status = Xutf8TextPropertyToTextList(server.display, &text_property, &name_list, &count);
    if (status < Success || !count) {
        XFree(text_property.value);
        return strdup("");
    }

    if (!name_list[0]) {
        XFreeStringList(name_list);
        XFree(text_property.value);
        return strdup("");
    }

    char *result = strdup(name_list[0]);
    XFreeStringList(name_list);
    XFree(text_property.value);
    return result;
}
Пример #3
0
char *ICCCM::get_title(Frame *f)
{
    XTextProperty xtp;
    char *title = 0;

    if(XGetWMName(fl_display, f->window(), &xtp))
    {
        if(xtp.encoding == XA_STRING) {
            title = strdup((const char*)xtp.value);
        } else {
#if HAVE_X11_UTF_TEXT_PROP
            int items;
            char **list=0;
            Status s;
            s = Xutf8TextPropertyToTextList(fl_display, &xtp, &list, &items);
            if((s == Success) && (items > 0)) {
                title = strdup((const char *)*list);
            } else
                title = strdup((const char *)xtp.value);
            if(list) XFreeStringList(list);
#else
            title = strdup((const char*)xtp.value);
#endif
        }
        XFree(xtp.value);
    }
    return title;
}
Пример #4
0
int
xu_getstrprop(Window win, Atom atm, char **text) {
	XTextProperty	 prop;
	char		**list;
	int		 nitems = 0;

	*text = NULL;

	XGetTextProperty(X_Dpy, win, &prop, atm);
	if (!prop.nitems)
		return (0);

	if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list,
	    &nitems) == Success && nitems > 0 && *list) {
		if (nitems > 1) {
			XTextProperty    prop2;
			if (Xutf8TextListToTextProperty(X_Dpy, list, nitems,
			    XUTF8StringStyle, &prop2) == Success) {
				*text = xstrdup((const char *)prop2.value);
				XFree(prop2.value);
			}
		} else {
			*text = xstrdup(*list);
		}
		XFreeStringList(list);
	}

	XFree(prop.value);

	return (nitems);
}
Пример #5
0
/**
 * Get a window icon name.
 * @param win The window
 * @return The windows icon name string
 *
 * Return the icon name of a window. String must be free'd when done with.
 */
EAPI char *
ecore_x_icccm_icon_name_get(Ecore_X_Window win)
{
   XTextProperty xprop;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   xprop.value = NULL;
   if (XGetWMIconName(_ecore_x_disp, win, &xprop) >= Success)
     {
        if (_ecore_xlib_sync) ecore_x_sync();
        if (xprop.value)
          {
             char **list = NULL;
             char *t = NULL;
             int num = 0;
             int ret;

             if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
               t = strdup((char *)xprop.value);
             else
               {
                  /* convert to utf8 */
#ifdef X_HAVE_UTF8_STRING
                  ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
                                                    &list, &num);
#else /* ifdef X_HAVE_UTF8_STRING */
                  ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
                                                  &list, &num);
#endif /* ifdef X_HAVE_UTF8_STRING */
                  if (_ecore_xlib_sync) ecore_x_sync();

                  if ((ret == XLocaleNotSupported) ||
                      (ret == XNoMemory) || (ret == XConverterNotFound))
                    t = strdup((char *)xprop.value);
                  else if (ret >= Success)
                    {
                       if ((num >= 1) && (list))
                         t = strdup(list[0]);

                       if (list)
                         XFreeStringList(list);
                    }
               }

             if (xprop.value)
               XFree(xprop.value);

             return t;
          }
     }
   else
     {
        if (_ecore_xlib_sync) ecore_x_sync();
     }

   return NULL;
}
Пример #6
0
/**
 * @brief Get the first string in a UTF-8 string property on a window.
 */
char *
wm_wid_get_prop_utf8(session_t *ps, Window wid, Atom prop) {
	XTextProperty text_prop = { };
	char *ret = NULL;
	if (XGetTextProperty(ps->dpy, wid, &text_prop, prop)) {
		char **strlst = NULL;
		int cstr = 0;
		Xutf8TextPropertyToTextList(ps->dpy, &text_prop, &strlst, &cstr);
		if (cstr) ret = mstrdup(strlst[0]);
		if (strlst) XFreeStringList(strlst);
	}
	sxfree(text_prop.value);
	return ret;
}
Пример #7
0
bool hc_next_hook(HCConnection* con, int* argc, char** argv[]) {
    if (!hc_hook_window_connect(con)) {
        return false;
    }
    // get window to listen at
    Window win = con->hook_window;
    // listen on window
    XEvent next_event;
    bool received_hook = false;
    while (!received_hook) {
        XNextEvent(con->display, &next_event);
        if (next_event.type == DestroyNotify) {
            if (next_event.xdestroywindow.window == win) {
                // hook window was destroyed
                // so quit idling
                return false;
            }
        }
        if (next_event.type != PropertyNotify) {
            fprintf(stderr, "Warning: got other event than PropertyNotify\n");
            continue;
        }
        XPropertyEvent* pe = &next_event.xproperty;
        if (pe->state == PropertyDelete) {
            // just ignore property delete events
            continue;
        }
        if (pe->window != win) {
            fprintf(stderr, "Warning: expected event from window %u", (unsigned int)win);
            fprintf(stderr, " but got something from %u\n", (unsigned int)pe->window);
            continue;
        }
        XTextProperty text_prop;
        XGetTextProperty(con->display, win, &text_prop, pe->atom);
        char** list_return;
        int count;
        if (Success != Xutf8TextPropertyToTextList(con->display, &text_prop,
                                                   &list_return, &count)) {
            XFree(text_prop.value);
            return false;
        }
        *argc = count;
        *argv = argv_duplicate(count, list_return);
        received_hook = true;
        // cleanup
        XFreeStringList(list_return);
        XFree(text_prop.value);
    }
    return true;
}
Пример #8
0
int
getprop_textlist(Window *w, const char *name, char **ret[]) {
	XTextProperty prop;
	char **list;
	int n;

	*ret = nil;
	n = 0;

	XGetTextProperty(display, w->xid, &prop, xatom(name));
	if(prop.nitems > 0) {
		if(Xutf8TextPropertyToTextList(display, &prop, &list, &n) == Success)
			*ret = list;
		XFree(prop.value);
	}
	return n;
}
Пример #9
0
int 
dwbremote_get_property(Display *dpy, Window win, Atom atom, char ***list, int *count)
{
    int result = True;
    XTextProperty prop;
    if (!XGetTextProperty(dpy, win, &prop, atom))
    {
        return False;
    }
    if (Xutf8TextPropertyToTextList(dpy, &prop, list, count) != Success)
    {
        result = False;
    }
    XFree(prop.value);

    return result;
}
Пример #10
0
/**
 * Get a window string property.
 * @param win The window
 * @param type The property
 * @return Window string property of a window. String must be free'd when done.
 */
EAPI char *
ecore_x_window_prop_string_get(Ecore_X_Window win,
                               Ecore_X_Atom type)
{
   XTextProperty xtp;
   char *str = NULL;

   LOGFN(__FILE__, __LINE__, __FUNCTION__);
   if (win == 0)
     win = DefaultRootWindow(_ecore_x_disp);

   if (XGetTextProperty(_ecore_x_disp, win, &xtp, type))
     {
        int items;
        char **list = NULL;
        Status s;

        if (_ecore_xlib_sync) ecore_x_sync();
        if (xtp.encoding == ECORE_X_ATOM_UTF8_STRING)
          str = strdup((char *)xtp.value);
        else
          {
#ifdef X_HAVE_UTF8_STRING
             s = Xutf8TextPropertyToTextList(_ecore_x_disp, &xtp,
                                             &list, &items);
#else /* ifdef X_HAVE_UTF8_STRING */
             s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp,
                                           &list, &items);
#endif /* ifdef X_HAVE_UTF8_STRING */
             if (_ecore_xlib_sync) ecore_x_sync();
             if ((s == XLocaleNotSupported) ||
                 (s == XNoMemory) || (s == XConverterNotFound))
               str = strdup((char *)xtp.value);
             else if ((s >= Success) && (items > 0))
               str = strdup(list[0]);

             if (list)
               XFreeStringList(list);
          }

        XFree(xtp.value);
     }
   return str;
}
Пример #11
0
/** Convert a STRING XTextProperty to a string in the specified codepage.
 *
 * @return the string that the caller must free with mem_free(),
 * or NULL on error.  */
static unsigned char *
xprop_to_string(Display *display, const XTextProperty *text_prop, int to_cp)
{
	int from_cp;
	char **list = NULL;
	int count = 0;
	struct conv_table *convert_table;
	unsigned char *ret = NULL;

	/* <X11/Xlib.h> defines X_HAVE_UTF8_STRING if
	 * Xutf8TextPropertyToTextList is available.
	 *
	 * The X...TextPropertyToTextList functions return a negative
	 * error code, or Success=0, or the number of unconvertible
	 * characters.  Use the result even if some characters were
	 * unconvertible, because convert_string() can be lossy too,
	 * and it seems better to restore an approximation of the
	 * original title than to restore a default title that may be
	 * entirely different.  */
#if defined(CONFIG_UTF8) && defined(X_HAVE_UTF8_STRING)

	from_cp = get_cp_index((const unsigned char *)"UTF-8");
	if (Xutf8TextPropertyToTextList(display, text_prop, &list,
					&count) < 0)
		return NULL;

#else  /* !defined(X_HAVE_UTF8_STRING) || !defined(CONFIG_UTF8) */

	from_cp = get_cp_index((const unsigned char *)"System");
	if (XmbTextPropertyToTextList(display, text_prop, &list,
				      &count) < 0)
		return NULL;

#endif /* !defined(X_HAVE_UTF8_STRING) || !defined(CONFIG_UTF8) */

	convert_table = get_translation_table(from_cp, to_cp);
	if (count >= 1 && convert_table)
		ret = convert_string(convert_table, (unsigned char *)list[0], strlen((const char *)list[0]),
				     to_cp, CSM_NONE, NULL, NULL, NULL);

	XFreeStringList(list);
	return ret;
}
int
winClipboardFlushXEvents (HWND hwnd,
			  int iWindow,
			  Display *pDisplay,
			  Bool fUseUnicode)
{
  static Atom atomLocalProperty;
  static Atom atomCompoundText;
  static Atom atomUTF8String;
  static Atom atomTargets;
  static int generation;

  if (generation != serverGeneration)
    {
      generation = serverGeneration;
      atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
      atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
      atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
      atomTargets = XInternAtom (pDisplay, "TARGETS", False);
    }

  /* Process all pending events */
  while (XPending (pDisplay))
    {
      XTextProperty		xtpText = {0};
      XEvent			event;
      XSelectionEvent		eventSelection;
      unsigned long		ulReturnBytesLeft;
      char			*pszReturnData = NULL;
      char			*pszGlobalData = NULL;
      int			iReturn;
      HGLOBAL			hGlobal = NULL;
      XICCEncodingStyle		xiccesStyle;
      int			iConvertDataLen = 0;
      char			*pszConvertData = NULL;
      char			*pszTextList[2] = {NULL};
      int			iCount;
      char			**ppszTextList = NULL;
      wchar_t			*pwszUnicodeStr = NULL;
      int			iUnicodeLen = 0;
      int			iReturnDataLen = 0;
      int			i;
      Bool			fAbort = FALSE;
      Bool			fCloseClipboard = FALSE;
      Bool			fSetClipboardData = TRUE;

      /* Get the next event - will not block because one is ready */
      XNextEvent (pDisplay, &event);

      /* Branch on the event type */
      switch (event.type)
	{
	  /*
	   * SelectionRequest
	   */

	case SelectionRequest:
	  {
	    char			*pszAtomName = NULL;
	    winDebug("SelectionRequest - target %d\n",
                     event.xselectionrequest.target);

	    pszAtomName = XGetAtomName (pDisplay,
					event.xselectionrequest.target);
	    winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
	    XFree (pszAtomName);
	    pszAtomName = NULL;
	  }

	  /* Abort if invalid target type */
	  if (event.xselectionrequest.target != XA_STRING
	      && event.xselectionrequest.target != atomUTF8String
	      && event.xselectionrequest.target != atomCompoundText
	      && event.xselectionrequest.target != atomTargets)
	    {
	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Handle targets type of request */
	  if (event.xselectionrequest.target == atomTargets)
	    {
	      Atom atomTargetArr[] = {atomTargets,
				      atomCompoundText,
				      atomUTF8String,
				      XA_STRING};

	      /* Try to change the property */
	      iReturn = XChangeProperty (pDisplay,
					 event.xselectionrequest.requestor,
					 event.xselectionrequest.property,
					 XA_ATOM,
					 32,
					 PropModeReplace,
					 (unsigned char *) atomTargetArr,
					 (sizeof (atomTargetArr)
					  / sizeof (atomTargetArr[0])));
	      if (iReturn == BadAlloc
		  || iReturn == BadAtom
		  || iReturn == BadMatch
		  || iReturn == BadValue
		  || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XChangeProperty failed: %d\n",
			  iReturn);
		}

	      /* Setup selection notify xevent */
	      eventSelection.type	= SelectionNotify;
	      eventSelection.send_event	= True;
	      eventSelection.display	= pDisplay;
	      eventSelection.requestor	= event.xselectionrequest.requestor;
	      eventSelection.selection	= event.xselectionrequest.selection;
	      eventSelection.target	= event.xselectionrequest.target;
	      eventSelection.property	= event.xselectionrequest.property;
	      eventSelection.time	= event.xselectionrequest.time;

	      /*
	       * Notify the requesting window that
	       * the operation has completed
	       */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed\n");
		}
	      break;
	    }

	  /* Check that clipboard format is available */
	  if (fUseUnicode
	      && !IsClipboardFormatAvailable (CF_UNICODETEXT))
	    {
	      static int count; /* Hack to stop acroread spamming the log */
	      static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
	      if (hwnd != lasthwnd) count = 0;
	      count++;
	      if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
		      "available from Win32 clipboard.  Aborting %d.\n", count);
	      lasthwnd = hwnd;

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  else if (!fUseUnicode
		   && !IsClipboardFormatAvailable (CF_TEXT))
	    {
	      ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
		      "available from Win32 clipboard.  Aborting.\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Close clipboard if we have it open already */
	  if (GetOpenClipboardWindow () == hwnd)
	    {
	      CloseClipboard ();
	    }

	  /* Access the clipboard */
	  if (!OpenClipboard (hwnd))
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "OpenClipboard () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Indicate that clipboard was opened */
	  fCloseClipboard = TRUE;

	  /* Setup the string style */
	  if (event.xselectionrequest.target == XA_STRING)
	    xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
	  else if (event.xselectionrequest.target == atomUTF8String)
	    xiccesStyle = XUTF8StringStyle;
#endif
	  else if (event.xselectionrequest.target == atomCompoundText)
	    xiccesStyle = XCompoundTextStyle;
	  else
	    xiccesStyle = XStringStyle;

	  /*
	   * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
	   */
	  
	  /* Get a pointer to the clipboard text, in desired format */
	  if (fUseUnicode)
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_UNICODETEXT);
	    }
	  else
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_TEXT);
	    }
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "GetClipboardData () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  pszGlobalData = (char *) GlobalLock (hGlobal);

	  /* Convert the Unicode string to UTF8 (MBCS) */
	  if (fUseUnicode)
	    {
	      iConvertDataLen = WideCharToMultiByte (CP_UTF8,
						     0,
						     (LPCWSTR)pszGlobalData,
						     -1,
						     NULL,
						     0,
						     NULL,
						     NULL);
	      /* NOTE: iConvertDataLen includes space for null terminator */
	      pszConvertData = (char *) malloc (iConvertDataLen);
	      WideCharToMultiByte (CP_UTF8,
				   0,
				   (LPCWSTR)pszGlobalData,
				   -1,
				   pszConvertData,
				   iConvertDataLen,
				   NULL,
				   NULL);
	    }
	  else
	    {
	      pszConvertData = strdup (pszGlobalData);
	      iConvertDataLen = strlen (pszConvertData) + 1;
	    }

	  /* Convert DOS string to UNIX string */
	  winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));

	  /* Setup our text list */
	  pszTextList[0] = pszConvertData;
	  pszTextList[1] = NULL;

	  /* Initialize the text property */
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Create the text property from the text list */
	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      iReturn = Xutf8TextListToTextProperty (pDisplay,
						     pszTextList,
						     1,
						     xiccesStyle,
						     &xtpText);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextListToTextProperty (pDisplay,
						   pszTextList,
						   1,
						   xiccesStyle,
						   &xtpText);
	    }
	  if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "X*TextListToTextProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Free the converted string */
	  free (pszConvertData);
	  pszConvertData = NULL;

	  /* Copy the clipboard text to the requesting window */
	  iReturn = XChangeProperty (pDisplay,
				     event.xselectionrequest.requestor,
				     event.xselectionrequest.property,
				     event.xselectionrequest.target,
				     8,
				     PropModeReplace,
				     xtpText.value,
				     xtpText.nitems);
	  if (iReturn == BadAlloc || iReturn == BadAtom
	      || iReturn == BadMatch || iReturn == BadValue
	      || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XChangeProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Release the clipboard data */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;
	  fCloseClipboard = FALSE;
	  CloseClipboard ();

	  /* Clean up */
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Setup selection notify event */
	  eventSelection.type = SelectionNotify;
	  eventSelection.send_event = True;
	  eventSelection.display = pDisplay;
	  eventSelection.requestor = event.xselectionrequest.requestor;
	  eventSelection.selection = event.xselectionrequest.selection;
	  eventSelection.target = event.xselectionrequest.target;
	  eventSelection.property = event.xselectionrequest.property;
	  eventSelection.time = event.xselectionrequest.time;

	  /* Notify the requesting window that the operation has completed */
	  iReturn = XSendEvent (pDisplay,
				eventSelection.requestor,
				False,
				0L,
				(XEvent *) &eventSelection);
	  if (iReturn == BadValue || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XSendEvent () failed\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	winClipboardFlushXEvents_SelectionRequest_Done:
	  /* Free allocated resources */
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  
	  /*
	   * Send a SelectionNotify event to the requesting
	   * client when we abort.
	   */
	  if (fAbort)
	    {
	      /* Setup selection notify event */
	      eventSelection.type = SelectionNotify;
	      eventSelection.send_event = True;
	      eventSelection.display = pDisplay;
	      eventSelection.requestor = event.xselectionrequest.requestor;
	      eventSelection.selection = event.xselectionrequest.selection;
	      eventSelection.target = event.xselectionrequest.target;
	      eventSelection.property = None;
	      eventSelection.time = event.xselectionrequest.time;

	      /* Notify the requesting window that the operation is complete */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  /*
		   * Should not be a problem if XSendEvent fails because
		   * the client may simply have exited.
		   */
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed for abort event.\n");
		}
	    }

	  /* Close clipboard if it was opened */
	  if (fCloseClipboard)
	  {
	    fCloseClipboard = FALSE;
	    CloseClipboard ();
	  }
	  break;


	  /*
	   * SelectionNotify
	   */ 

	case SelectionNotify:

	  winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
	  {
	    char		*pszAtomName;
	    pszAtomName = XGetAtomName (pDisplay,
					event.xselection.selection);

	    winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
	    XFree (pszAtomName);
	  }

	  /*
	   * Request conversion of UTF8 and CompoundText targets.
	   */
	  if (event.xselection.property == None)
	    {
	      if (event.xselection.target == XA_STRING)
		{
		  winDebug ("winClipboardFlushXEvents - SelectionNotify - "
                            "XA_STRING\n");

		  return WIN_XEVENTS_CONVERT;
		}
	      else if (event.xselection.target == atomUTF8String)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of UTF8 target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     XA_STRING,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#ifdef X_HAVE_UTF8_STRING
	      else if (event.xselection.target == atomCompoundText)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of CompoundText target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     atomUTF8String,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#endif
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "Unknown format.  Cannot request conversion, "
			  "aborting.\n");
		  break;
		}
	    }

	  /* Retrieve the size of the stored data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					0, /* Don't get data, just size */
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	  winDebug("SelectionNotify - returned data %d left %d\n",
                   xtpText.nitems, ulReturnBytesLeft);

	  /* Request the selection data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					ulReturnBytesLeft,
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	    {
	      char		*pszAtomName = NULL;

	      winDebug("SelectionNotify - returned data %d left %d\n",
                       xtpText.nitems, ulReturnBytesLeft);
	      pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
	      winDebug("Notify atom name %s\n", pszAtomName);
	      XFree (pszAtomName);
	      pszAtomName = NULL;
	    }

	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      /* Convert the text property to a text list */
	      iReturn = Xutf8TextPropertyToTextList (pDisplay,
						     &xtpText,
						     &ppszTextList,
						     &iCount);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextPropertyToTextList (pDisplay,
						   &xtpText,
						   &ppszTextList,
						   &iCount);
	    }
	  if (iReturn == Success || iReturn > 0)
	    {
	      /* Conversion succeeded or some unconvertible characters */
	      if (ppszTextList != NULL)
		{
		  iReturnDataLen = 0;
		  for (i = 0; i < iCount; i++)
		    {
		      iReturnDataLen += strlen(ppszTextList[i]);
		    }
		  pszReturnData = malloc (iReturnDataLen + 1);
		  pszReturnData[0] = '\0';
		  for (i = 0; i < iCount; i++)
		    {
		      strcat (pszReturnData, ppszTextList[i]);
		    }
		}
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "X*TextPropertyToTextList list_return is NULL.\n");
		  pszReturnData = malloc (1);
		  pszReturnData[0] = '\0';
		}
	    }
	  else
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "X*TextPropertyToTextList returned: ");
	      switch (iReturn)
		{
		case XNoMemory:
		  ErrorF ("XNoMemory\n");
		  break;
		case XConverterNotFound:
		  ErrorF ("XConverterNotFound\n");
		  break;
		default:
		  ErrorF ("%d", iReturn);
		  break;
		}
	      pszReturnData = malloc (1);
	      pszReturnData[0] = '\0';
	    }

	  /* Free the data returned from XGetWindowProperty */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  ppszTextList = NULL;
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Convert the X clipboard string to DOS format */
	  winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));

	  if (fUseUnicode)
	    {
	      /* Find out how much space needed to convert MBCS to Unicode */
	      iUnicodeLen = MultiByteToWideChar (CP_UTF8,
						 0,
						 pszReturnData,
						 -1,
						 NULL,
						 0);

	      /* Allocate memory for the Unicode string */
	      pwszUnicodeStr
		= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
	      if (!pwszUnicodeStr)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify "
			  "malloc failed for pwszUnicodeStr, aborting.\n");

		  /* Abort */
		  fAbort = TRUE;
		  goto winClipboardFlushXEvents_SelectionNotify_Done;
		}

	      /* Do the actual conversion */
	      MultiByteToWideChar (CP_UTF8,
				   0,
				   pszReturnData,
				   -1,
				   pwszUnicodeStr,
				   iUnicodeLen);
	      
	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE,
				     sizeof (wchar_t) * (iUnicodeLen + 1));
	    }
	  else
	    {
	      pszConvertData = strdup (pszReturnData);
	      iConvertDataLen = strlen (pszConvertData) + 1;

	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
	    }

	  free (pszReturnData);

	  /* Check that global memory was allocated */
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify "
		      "GlobalAlloc failed, aborting: %ld\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Obtain a pointer to the global memory */
	  pszGlobalData = GlobalLock (hGlobal);
	  if (pszGlobalData == NULL)
	    {
	      ErrorF ("winClipboardFlushXEvents - Could not lock global "
		      "memory for clipboard transfer\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Copy the returned string into the global memory */
	  if (fUseUnicode)
	    {
	      memcpy (pszGlobalData,
		      pwszUnicodeStr,
		      sizeof (wchar_t) * (iUnicodeLen + 1));
	      free (pwszUnicodeStr);
	      pwszUnicodeStr = NULL;
	    }
	  else
	    {
	      strcpy (pszGlobalData, pszConvertData);
	      free (pszConvertData);
	      pszConvertData = NULL;
	    }

	  /* Release the pointer to the global memory */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;

	  /* Push the selection data to the Windows clipboard */
	  if (fUseUnicode)
	    SetClipboardData (CF_UNICODETEXT, hGlobal);
	  else
	    SetClipboardData (CF_TEXT, hGlobal);

	  /* Flag that SetClipboardData has been called */
	  fSetClipboardData = FALSE;

	  /*
	   * NOTE: Do not try to free pszGlobalData, it is owned by
	   * Windows after the call to SetClipboardData ().
	   */

	winClipboardFlushXEvents_SelectionNotify_Done:
	  /* Free allocated resources */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  free(pwszUnicodeStr);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  if (fSetClipboardData && g_fUnicodeSupport)
	    SetClipboardData (CF_UNICODETEXT, NULL);
	  if (fSetClipboardData)
	    SetClipboardData (CF_TEXT, NULL);
	  return WIN_XEVENTS_NOTIFY;

        case SelectionClear:
          winDebug("SelectionClear - doing nothing\n");
          break;

	case PropertyNotify:
	  break;

	case MappingNotify:
	  break;

	default:
          ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
	  break;
	}
    }

  return WIN_XEVENTS_SUCCESS;
}
Пример #13
0
int
winClipboardFlushXEvents(HWND hwnd,
                         Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
    Atom atomClipboard = atoms->atomClipboard;
    Atom atomLocalProperty = atoms->atomLocalProperty;
    Atom atomUTF8String = atoms->atomUTF8String;
    Atom atomCompoundText = atoms->atomCompoundText;
    Atom atomTargets = atoms->atomTargets;

    /* Process all pending events */
    while (XPending(pDisplay)) {
        XTextProperty xtpText = { 0 };
        XEvent event;
        XSelectionEvent eventSelection;
        unsigned long ulReturnBytesLeft;
        char *pszReturnData = NULL;
        char *pszGlobalData = NULL;
        int iReturn;
        HGLOBAL hGlobal = NULL;
        XICCEncodingStyle xiccesStyle;
        char *pszConvertData = NULL;
        char *pszTextList[2] = { NULL };
        int iCount;
        char **ppszTextList = NULL;
        wchar_t *pwszUnicodeStr = NULL;
        Bool fAbort = FALSE;
        Bool fCloseClipboard = FALSE;
        Bool fSetClipboardData = TRUE;

        /* Get the next event - will not block because one is ready */
        XNextEvent(pDisplay, &event);

        /* Branch on the event type */
        switch (event.type) {
            /*
             * SelectionRequest
             */

        case SelectionRequest:
        {
            char *pszAtomName = NULL;

            winDebug("SelectionRequest - target %ld\n",
                     event.xselectionrequest.target);

            pszAtomName = XGetAtomName(pDisplay,
                                       event.xselectionrequest.target);
            winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
            XFree(pszAtomName);
            pszAtomName = NULL;
        }

            /* Abort if invalid target type */
            if (event.xselectionrequest.target != XA_STRING
                && event.xselectionrequest.target != atomUTF8String
                && event.xselectionrequest.target != atomCompoundText
                && event.xselectionrequest.target != atomTargets) {
                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Handle targets type of request */
            if (event.xselectionrequest.target == atomTargets) {
                Atom atomTargetArr[] = { atomTargets,
                    atomCompoundText,
                    atomUTF8String,
                    XA_STRING
                };

                /* Try to change the property */
                iReturn = XChangeProperty(pDisplay,
                                          event.xselectionrequest.requestor,
                                          event.xselectionrequest.property,
                                          XA_ATOM,
                                          32,
                                          PropModeReplace,
                                          (unsigned char *) atomTargetArr,
                                          ARRAY_SIZE(atomTargetArr));
                if (iReturn == BadAlloc
                    || iReturn == BadAtom
                    || iReturn == BadMatch
                    || iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XChangeProperty failed: %d\n", iReturn);
                }

                /* Setup selection notify xevent */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = event.xselectionrequest.property;
                eventSelection.time = event.xselectionrequest.time;

                /*
                 * Notify the requesting window that
                 * the operation has completed
                 */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed\n");
                }
                break;
            }

            /* Close clipboard if we have it open already */
            if (GetOpenClipboardWindow() == hwnd) {
                CloseClipboard();
            }

            /* Access the clipboard */
            if (!OpenClipboard(hwnd)) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "OpenClipboard () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Indicate that clipboard was opened */
            fCloseClipboard = TRUE;

            /* Check that clipboard format is available */
            if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
                static int count;       /* Hack to stop acroread spamming the log */
                static HWND lasthwnd;   /* I've not seen any other client get here repeatedly? */

                if (hwnd != lasthwnd)
                    count = 0;
                count++;
                if (count < 6)
                    ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
                           "available from Win32 clipboard.  Aborting %d.\n",
                           count);
                lasthwnd = hwnd;

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
                ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
                       "available from Win32 clipboard.  Aborting.\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Setup the string style */
            if (event.xselectionrequest.target == XA_STRING)
                xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
            else if (event.xselectionrequest.target == atomUTF8String)
                xiccesStyle = XUTF8StringStyle;
#endif
            else if (event.xselectionrequest.target == atomCompoundText)
                xiccesStyle = XCompoundTextStyle;
            else
                xiccesStyle = XStringStyle;

            /* Get a pointer to the clipboard text, in desired format */
            if (data->fUseUnicode) {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_UNICODETEXT);
            }
            else {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_TEXT);
            }
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "GetClipboardData () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            pszGlobalData = (char *) GlobalLock(hGlobal);

            /* Convert the Unicode string to UTF8 (MBCS) */
            if (data->fUseUnicode) {
                int iConvertDataLen = WideCharToMultiByte(CP_UTF8,
                                                      0,
                                                      (LPCWSTR) pszGlobalData,
                                                      -1, NULL, 0, NULL, NULL);
                /* NOTE: iConvertDataLen includes space for null terminator */
                pszConvertData = malloc(iConvertDataLen);
                WideCharToMultiByte(CP_UTF8,
                                    0,
                                    (LPCWSTR) pszGlobalData,
                                    -1,
                                    pszConvertData,
                                    iConvertDataLen, NULL, NULL);
            }
            else {
                pszConvertData = strdup(pszGlobalData);
            }

            /* Convert DOS string to UNIX string */
            winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));

            /* Setup our text list */
            pszTextList[0] = pszConvertData;
            pszTextList[1] = NULL;

            /* Initialize the text property */
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Create the text property from the text list */
            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                iReturn = Xutf8TextListToTextProperty(pDisplay,
                                                      pszTextList,
                                                      1, xiccesStyle, &xtpText);
#endif
            }
            else {
                iReturn = XmbTextListToTextProperty(pDisplay,
                                                    pszTextList,
                                                    1, xiccesStyle, &xtpText);
            }
            if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "X*TextListToTextProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Free the converted string */
            free(pszConvertData);
            pszConvertData = NULL;

            /* Copy the clipboard text to the requesting window */
            iReturn = XChangeProperty(pDisplay,
                                      event.xselectionrequest.requestor,
                                      event.xselectionrequest.property,
                                      event.xselectionrequest.target,
                                      8,
                                      PropModeReplace,
                                      xtpText.value, xtpText.nitems);
            if (iReturn == BadAlloc || iReturn == BadAtom
                || iReturn == BadMatch || iReturn == BadValue
                || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XChangeProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Release the clipboard data */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;
            fCloseClipboard = FALSE;
            CloseClipboard();

            /* Clean up */
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Setup selection notify event */
            eventSelection.type = SelectionNotify;
            eventSelection.send_event = True;
            eventSelection.display = pDisplay;
            eventSelection.requestor = event.xselectionrequest.requestor;
            eventSelection.selection = event.xselectionrequest.selection;
            eventSelection.target = event.xselectionrequest.target;
            eventSelection.property = event.xselectionrequest.property;
            eventSelection.time = event.xselectionrequest.time;

            /* Notify the requesting window that the operation has completed */
            iReturn = XSendEvent(pDisplay,
                                 eventSelection.requestor,
                                 False, 0L, (XEvent *) &eventSelection);
            if (iReturn == BadValue || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XSendEvent () failed\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

 winClipboardFlushXEvents_SelectionRequest_Done:
            /* Free allocated resources */
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);

            /*
             * Send a SelectionNotify event to the requesting
             * client when we abort.
             */
            if (fAbort) {
                /* Setup selection notify event */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = None;
                eventSelection.time = event.xselectionrequest.time;

                /* Notify the requesting window that the operation is complete */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    /*
                     * Should not be a problem if XSendEvent fails because
                     * the client may simply have exited.
                     */
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed for abort event.\n");
                }
            }

            /* Close clipboard if it was opened */
            if (fCloseClipboard) {
                fCloseClipboard = FALSE;
                CloseClipboard();
            }
            break;

            /*
             * SelectionNotify
             */

        case SelectionNotify:
            winDebug("winClipboardFlushXEvents - SelectionNotify\n");
            {
                char *pszAtomName;

                pszAtomName = XGetAtomName(pDisplay,
                                           event.xselection.selection);

                winDebug
                    ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
                XFree(pszAtomName);
            }

            /*
              SelectionNotify with property of None indicates either:

              (i) Generated by the X server if no owner for the specified selection exists
                  (perhaps it's disappeared on us mid-transaction), or
              (ii) Sent by the selection owner when the requested selection conversion could
                   not be performed or server errors prevented the conversion data being returned
            */
            if (event.xselection.property == None) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "Conversion to format %ld refused.\n",
                           event.xselection.target);
                    return WIN_XEVENTS_FAILED;
                }

            if (event.xselection.target == atomTargets) {
              return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
            }

            /* Retrieve the selection data and delete the property */
            iReturn = XGetWindowProperty(pDisplay,
                                         iWindow,
                                         atomLocalProperty,
                                         0,
                                         INT_MAX,
                                         True,
                                         AnyPropertyType,
                                         &xtpText.encoding,
                                         &xtpText.format,
                                         &xtpText.nitems,
                                         &ulReturnBytesLeft, &xtpText.value);
            if (iReturn != Success) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            {
                char *pszAtomName = NULL;

                winDebug("SelectionNotify - returned data %lu left %lu\n",
                         xtpText.nitems, ulReturnBytesLeft);
                pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
                winDebug("Notify atom name %s\n", pszAtomName);
                XFree(pszAtomName);
                pszAtomName = NULL;
            }

            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                /* Convert the text property to a text list */
                iReturn = Xutf8TextPropertyToTextList(pDisplay,
                                                      &xtpText,
                                                      &ppszTextList, &iCount);
#endif
            }
            else {
                iReturn = XmbTextPropertyToTextList(pDisplay,
                                                    &xtpText,
                                                    &ppszTextList, &iCount);
            }
            if (iReturn == Success || iReturn > 0) {
                /* Conversion succeeded or some unconvertible characters */
                if (ppszTextList != NULL) {
                    int i;
                    int iReturnDataLen = 0;
                    for (i = 0; i < iCount; i++) {
                        iReturnDataLen += strlen(ppszTextList[i]);
                    }
                    pszReturnData = malloc(iReturnDataLen + 1);
                    pszReturnData[0] = '\0';
                    for (i = 0; i < iCount; i++) {
                        strcat(pszReturnData, ppszTextList[i]);
                    }
                }
                else {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "X*TextPropertyToTextList list_return is NULL.\n");
                    pszReturnData = malloc(1);
                    pszReturnData[0] = '\0';
                }
            }
            else {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "X*TextPropertyToTextList returned: ");
                switch (iReturn) {
                case XNoMemory:
                    ErrorF("XNoMemory\n");
                    break;
                case XLocaleNotSupported:
                    ErrorF("XLocaleNotSupported\n");
                    break;
                case XConverterNotFound:
                    ErrorF("XConverterNotFound\n");
                    break;
                default:
                    ErrorF("%d\n", iReturn);
                    break;
                }
                pszReturnData = malloc(1);
                pszReturnData[0] = '\0';
            }

            /* Free the data returned from XGetWindowProperty */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            ppszTextList = NULL;
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Convert the X clipboard string to DOS format */
            winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));

            if (data->fUseUnicode) {
                /* Find out how much space needed to convert MBCS to Unicode */
                int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
                                                  0,
                                                  pszReturnData, -1, NULL, 0);

                /* NOTE: iUnicodeLen includes space for null terminator */
                pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
                if (!pwszUnicodeStr) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify "
                           "malloc failed for pwszUnicodeStr, aborting.\n");

                    /* Abort */
                    fAbort = TRUE;
                    goto winClipboardFlushXEvents_SelectionNotify_Done;
                }

                /* Do the actual conversion */
                MultiByteToWideChar(CP_UTF8,
                                    0,
                                    pszReturnData,
                                    -1, pwszUnicodeStr, iUnicodeLen);

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE,
                                      sizeof(wchar_t) * iUnicodeLen);
            }
            else {
                int iConvertDataLen = 0;
                pszConvertData = strdup(pszReturnData);
                iConvertDataLen = strlen(pszConvertData) + 1;

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
            }

            free(pszReturnData);

            /* Check that global memory was allocated */
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify "
                       "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Obtain a pointer to the global memory */
            pszGlobalData = GlobalLock(hGlobal);
            if (pszGlobalData == NULL) {
                ErrorF("winClipboardFlushXEvents - Could not lock global "
                       "memory for clipboard transfer\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Copy the returned string into the global memory */
            if (data->fUseUnicode) {
                wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
                free(pwszUnicodeStr);
                pwszUnicodeStr = NULL;
            }
            else {
                strcpy(pszGlobalData, pszConvertData);
                free(pszConvertData);
                pszConvertData = NULL;
            }

            /* Release the pointer to the global memory */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;

            /* Push the selection data to the Windows clipboard */
            if (data->fUseUnicode)
                SetClipboardData(CF_UNICODETEXT, hGlobal);
            else
                SetClipboardData(CF_TEXT, hGlobal);

            /* Flag that SetClipboardData has been called */
            fSetClipboardData = FALSE;

            /*
             * NOTE: Do not try to free pszGlobalData, it is owned by
             * Windows after the call to SetClipboardData ().
             */

 winClipboardFlushXEvents_SelectionNotify_Done:
            /* Free allocated resources */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            free(pwszUnicodeStr);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);
            if (fSetClipboardData) {
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);
            }
            return WIN_XEVENTS_NOTIFY_DATA;

        case SelectionClear:
            winDebug("SelectionClear - doing nothing\n");
            break;

        case PropertyNotify:
            break;

        case MappingNotify:
            break;

        default:
            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
                XFixesSelectionNotifyEvent *e =
                    (XFixesSelectionNotifyEvent *) & event;

                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");

                /* Save selection owners for monitored selections, ignore other selections */
                if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
                    MonitorSelection(e, CLIP_OWN_PRIMARY);
                }
                else if (e->selection == atomClipboard) {
                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
                }
                else
                    break;

                /* Selection is being disowned */
                if (e->owner == None) {
                    winDebug
                        ("winClipboardFlushXEvents - No window, returning.\n");
                    break;
                }

                /*
                   XXX: there are all kinds of wacky edge cases we might need here:
                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
                   - root window is taking ownership?
                 */

                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
                    break;
                }

                /* Close clipboard if we have it open already (possible? correct??) */
                if (GetOpenClipboardWindow() == hwnd) {
                    CloseClipboard();
                }

                /* Access the Windows clipboard */
                if (!OpenClipboard(hwnd)) {
                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Take ownership of the Windows clipboard */
                if (!EmptyClipboard()) {
                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Advertise regular text and unicode */
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);

                /* Release the clipboard */
                if (!CloseClipboard()) {
                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }
            }
            /* XFixesSelectionWindowDestroyNotifyMask */
            /* XFixesSelectionClientCloseNotifyMask */
            else {
                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
                       event.type);
            }
            break;
        }
    }

    return WIN_XEVENTS_SUCCESS;
}