1706f2543Smrg/*
2706f2543Smrg *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
3706f2543Smrg *Copyright (C) Colin Harrison 2005-2008
4706f2543Smrg *
5706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining
6706f2543Smrg * a copy of this software and associated documentation files (the
7706f2543Smrg *"Software"), to deal in the Software without restriction, including
8706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish,
9706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to
10706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to
11706f2543Smrg *the following conditions:
12706f2543Smrg *
13706f2543Smrg *The above copyright notice and this permission notice shall be
14706f2543Smrg *included in all copies or substantial portions of the Software.
15706f2543Smrg *
16706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
20706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23706f2543Smrg *
24706f2543Smrg *Except as contained in this notice, the name of the copyright holder(s)
25706f2543Smrg *and author(s) shall not be used in advertising or otherwise to promote
26706f2543Smrg *the sale, use or other dealings in this Software without prior written
27706f2543Smrg *authorization from the copyright holder(s) and author(s).
28706f2543Smrg *
29706f2543Smrg * Authors:	Harold L Hunt II
30706f2543Smrg *              Colin Harrison
31706f2543Smrg */
32706f2543Smrg
33706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H
34706f2543Smrg#include <xwin-config.h>
35706f2543Smrg#endif
36706f2543Smrg#include "winclipboard.h"
37706f2543Smrg#include "misc.h"
38706f2543Smrg
39706f2543Smrg
40706f2543Smrg/*
41706f2543Smrg * References to external symbols
42706f2543Smrg */
43706f2543Smrg
44706f2543Smrgextern Bool		g_fUnicodeSupport;
45706f2543Smrg
46706f2543Smrg
47706f2543Smrg/*
48706f2543Smrg * Process any pending X events
49706f2543Smrg */
50706f2543Smrg
51706f2543Smrgint
52706f2543SmrgwinClipboardFlushXEvents (HWND hwnd,
53706f2543Smrg			  int iWindow,
54706f2543Smrg			  Display *pDisplay,
55706f2543Smrg			  Bool fUseUnicode)
56706f2543Smrg{
57706f2543Smrg  static Atom atomLocalProperty;
58706f2543Smrg  static Atom atomCompoundText;
59706f2543Smrg  static Atom atomUTF8String;
60706f2543Smrg  static Atom atomTargets;
61706f2543Smrg  static int generation;
62706f2543Smrg
63706f2543Smrg  if (generation != serverGeneration)
64706f2543Smrg    {
65706f2543Smrg      generation = serverGeneration;
66706f2543Smrg      atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
67706f2543Smrg      atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
68706f2543Smrg      atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
69706f2543Smrg      atomTargets = XInternAtom (pDisplay, "TARGETS", False);
70706f2543Smrg    }
71706f2543Smrg
72706f2543Smrg  /* Process all pending events */
73706f2543Smrg  while (XPending (pDisplay))
74706f2543Smrg    {
75706f2543Smrg      XTextProperty		xtpText = {0};
76706f2543Smrg      XEvent			event;
77706f2543Smrg      XSelectionEvent		eventSelection;
78706f2543Smrg      unsigned long		ulReturnBytesLeft;
79706f2543Smrg      char			*pszReturnData = NULL;
80706f2543Smrg      char			*pszGlobalData = NULL;
81706f2543Smrg      int			iReturn;
82706f2543Smrg      HGLOBAL			hGlobal = NULL;
83706f2543Smrg      XICCEncodingStyle		xiccesStyle;
84706f2543Smrg      int			iConvertDataLen = 0;
85706f2543Smrg      char			*pszConvertData = NULL;
86706f2543Smrg      char			*pszTextList[2] = {NULL};
87706f2543Smrg      int			iCount;
88706f2543Smrg      char			**ppszTextList = NULL;
89706f2543Smrg      wchar_t			*pwszUnicodeStr = NULL;
90706f2543Smrg      int			iUnicodeLen = 0;
91706f2543Smrg      int			iReturnDataLen = 0;
92706f2543Smrg      int			i;
93706f2543Smrg      Bool			fAbort = FALSE;
94706f2543Smrg      Bool			fCloseClipboard = FALSE;
95706f2543Smrg      Bool			fSetClipboardData = TRUE;
96706f2543Smrg
97706f2543Smrg      /* Get the next event - will not block because one is ready */
98706f2543Smrg      XNextEvent (pDisplay, &event);
99706f2543Smrg
100706f2543Smrg      /* Branch on the event type */
101706f2543Smrg      switch (event.type)
102706f2543Smrg	{
103706f2543Smrg	  /*
104706f2543Smrg	   * SelectionRequest
105706f2543Smrg	   */
106706f2543Smrg
107706f2543Smrg	case SelectionRequest:
108706f2543Smrg	  {
109706f2543Smrg	    char			*pszAtomName = NULL;
110706f2543Smrg	    winDebug("SelectionRequest - target %d\n",
111706f2543Smrg                     event.xselectionrequest.target);
112706f2543Smrg
113706f2543Smrg	    pszAtomName = XGetAtomName (pDisplay,
114706f2543Smrg					event.xselectionrequest.target);
115706f2543Smrg	    winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
116706f2543Smrg	    XFree (pszAtomName);
117706f2543Smrg	    pszAtomName = NULL;
118706f2543Smrg	  }
119706f2543Smrg
120706f2543Smrg	  /* Abort if invalid target type */
121706f2543Smrg	  if (event.xselectionrequest.target != XA_STRING
122706f2543Smrg	      && event.xselectionrequest.target != atomUTF8String
123706f2543Smrg	      && event.xselectionrequest.target != atomCompoundText
124706f2543Smrg	      && event.xselectionrequest.target != atomTargets)
125706f2543Smrg	    {
126706f2543Smrg	      /* Abort */
127706f2543Smrg	      fAbort = TRUE;
128706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
129706f2543Smrg	    }
130706f2543Smrg
131706f2543Smrg	  /* Handle targets type of request */
132706f2543Smrg	  if (event.xselectionrequest.target == atomTargets)
133706f2543Smrg	    {
134706f2543Smrg	      Atom atomTargetArr[] = {atomTargets,
135706f2543Smrg				      atomCompoundText,
136706f2543Smrg				      atomUTF8String,
137706f2543Smrg				      XA_STRING};
138706f2543Smrg
139706f2543Smrg	      /* Try to change the property */
140706f2543Smrg	      iReturn = XChangeProperty (pDisplay,
141706f2543Smrg					 event.xselectionrequest.requestor,
142706f2543Smrg					 event.xselectionrequest.property,
143706f2543Smrg					 XA_ATOM,
144706f2543Smrg					 32,
145706f2543Smrg					 PropModeReplace,
146706f2543Smrg					 (unsigned char *) atomTargetArr,
147706f2543Smrg					 (sizeof (atomTargetArr)
148706f2543Smrg					  / sizeof (atomTargetArr[0])));
149706f2543Smrg	      if (iReturn == BadAlloc
150706f2543Smrg		  || iReturn == BadAtom
151706f2543Smrg		  || iReturn == BadMatch
152706f2543Smrg		  || iReturn == BadValue
153706f2543Smrg		  || iReturn == BadWindow)
154706f2543Smrg		{
155706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
156706f2543Smrg			  "XChangeProperty failed: %d\n",
157706f2543Smrg			  iReturn);
158706f2543Smrg		}
159706f2543Smrg
160706f2543Smrg	      /* Setup selection notify xevent */
161706f2543Smrg	      eventSelection.type	= SelectionNotify;
162706f2543Smrg	      eventSelection.send_event	= True;
163706f2543Smrg	      eventSelection.display	= pDisplay;
164706f2543Smrg	      eventSelection.requestor	= event.xselectionrequest.requestor;
165706f2543Smrg	      eventSelection.selection	= event.xselectionrequest.selection;
166706f2543Smrg	      eventSelection.target	= event.xselectionrequest.target;
167706f2543Smrg	      eventSelection.property	= event.xselectionrequest.property;
168706f2543Smrg	      eventSelection.time	= event.xselectionrequest.time;
169706f2543Smrg
170706f2543Smrg	      /*
171706f2543Smrg	       * Notify the requesting window that
172706f2543Smrg	       * the operation has completed
173706f2543Smrg	       */
174706f2543Smrg	      iReturn = XSendEvent (pDisplay,
175706f2543Smrg				    eventSelection.requestor,
176706f2543Smrg				    False,
177706f2543Smrg				    0L,
178706f2543Smrg				    (XEvent *) &eventSelection);
179706f2543Smrg	      if (iReturn == BadValue || iReturn == BadWindow)
180706f2543Smrg		{
181706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
182706f2543Smrg			  "XSendEvent () failed\n");
183706f2543Smrg		}
184706f2543Smrg	      break;
185706f2543Smrg	    }
186706f2543Smrg
187706f2543Smrg	  /* Check that clipboard format is available */
188706f2543Smrg	  if (fUseUnicode
189706f2543Smrg	      && !IsClipboardFormatAvailable (CF_UNICODETEXT))
190706f2543Smrg	    {
191706f2543Smrg	      static int count; /* Hack to stop acroread spamming the log */
192706f2543Smrg	      static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
193706f2543Smrg	      if (hwnd != lasthwnd) count = 0;
194706f2543Smrg	      count++;
195706f2543Smrg	      if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
196706f2543Smrg		      "available from Win32 clipboard.  Aborting %d.\n", count);
197706f2543Smrg	      lasthwnd = hwnd;
198706f2543Smrg
199706f2543Smrg	      /* Abort */
200706f2543Smrg	      fAbort = TRUE;
201706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
202706f2543Smrg	    }
203706f2543Smrg	  else if (!fUseUnicode
204706f2543Smrg		   && !IsClipboardFormatAvailable (CF_TEXT))
205706f2543Smrg	    {
206706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
207706f2543Smrg		      "available from Win32 clipboard.  Aborting.\n");
208706f2543Smrg
209706f2543Smrg	      /* Abort */
210706f2543Smrg	      fAbort = TRUE;
211706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
212706f2543Smrg	    }
213706f2543Smrg
214706f2543Smrg	  /* Close clipboard if we have it open already */
215706f2543Smrg	  if (GetOpenClipboardWindow () == hwnd)
216706f2543Smrg	    {
217706f2543Smrg	      CloseClipboard ();
218706f2543Smrg	    }
219706f2543Smrg
220706f2543Smrg	  /* Access the clipboard */
221706f2543Smrg	  if (!OpenClipboard (hwnd))
222706f2543Smrg	    {
223706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
224706f2543Smrg		      "OpenClipboard () failed: %08lx\n",
225706f2543Smrg		      GetLastError ());
226706f2543Smrg
227706f2543Smrg	      /* Abort */
228706f2543Smrg	      fAbort = TRUE;
229706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
230706f2543Smrg	    }
231706f2543Smrg
232706f2543Smrg	  /* Indicate that clipboard was opened */
233706f2543Smrg	  fCloseClipboard = TRUE;
234706f2543Smrg
235706f2543Smrg	  /* Setup the string style */
236706f2543Smrg	  if (event.xselectionrequest.target == XA_STRING)
237706f2543Smrg	    xiccesStyle = XStringStyle;
238706f2543Smrg#ifdef X_HAVE_UTF8_STRING
239706f2543Smrg	  else if (event.xselectionrequest.target == atomUTF8String)
240706f2543Smrg	    xiccesStyle = XUTF8StringStyle;
241706f2543Smrg#endif
242706f2543Smrg	  else if (event.xselectionrequest.target == atomCompoundText)
243706f2543Smrg	    xiccesStyle = XCompoundTextStyle;
244706f2543Smrg	  else
245706f2543Smrg	    xiccesStyle = XStringStyle;
246706f2543Smrg
247706f2543Smrg	  /*
248706f2543Smrg	   * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
249706f2543Smrg	   */
250706f2543Smrg
251706f2543Smrg	  /* Get a pointer to the clipboard text, in desired format */
252706f2543Smrg	  if (fUseUnicode)
253706f2543Smrg	    {
254706f2543Smrg	      /* Retrieve clipboard data */
255706f2543Smrg	      hGlobal = GetClipboardData (CF_UNICODETEXT);
256706f2543Smrg	    }
257706f2543Smrg	  else
258706f2543Smrg	    {
259706f2543Smrg	      /* Retrieve clipboard data */
260706f2543Smrg	      hGlobal = GetClipboardData (CF_TEXT);
261706f2543Smrg	    }
262706f2543Smrg	  if (!hGlobal)
263706f2543Smrg	    {
264706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
265706f2543Smrg		      "GetClipboardData () failed: %08lx\n",
266706f2543Smrg		      GetLastError ());
267706f2543Smrg
268706f2543Smrg	      /* Abort */
269706f2543Smrg	      fAbort = TRUE;
270706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
271706f2543Smrg	    }
272706f2543Smrg	  pszGlobalData = (char *) GlobalLock (hGlobal);
273706f2543Smrg
274706f2543Smrg	  /* Convert the Unicode string to UTF8 (MBCS) */
275706f2543Smrg	  if (fUseUnicode)
276706f2543Smrg	    {
277706f2543Smrg	      iConvertDataLen = WideCharToMultiByte (CP_UTF8,
278706f2543Smrg						     0,
279706f2543Smrg						     (LPCWSTR)pszGlobalData,
280706f2543Smrg						     -1,
281706f2543Smrg						     NULL,
282706f2543Smrg						     0,
283706f2543Smrg						     NULL,
284706f2543Smrg						     NULL);
285706f2543Smrg	      /* NOTE: iConvertDataLen includes space for null terminator */
286706f2543Smrg	      pszConvertData = (char *) malloc (iConvertDataLen);
287706f2543Smrg	      WideCharToMultiByte (CP_UTF8,
288706f2543Smrg				   0,
289706f2543Smrg				   (LPCWSTR)pszGlobalData,
290706f2543Smrg				   -1,
291706f2543Smrg				   pszConvertData,
292706f2543Smrg				   iConvertDataLen,
293706f2543Smrg				   NULL,
294706f2543Smrg				   NULL);
295706f2543Smrg	    }
296706f2543Smrg	  else
297706f2543Smrg	    {
298706f2543Smrg	      pszConvertData = strdup (pszGlobalData);
299706f2543Smrg	      iConvertDataLen = strlen (pszConvertData) + 1;
300706f2543Smrg	    }
301706f2543Smrg
302706f2543Smrg	  /* Convert DOS string to UNIX string */
303706f2543Smrg	  winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));
304706f2543Smrg
305706f2543Smrg	  /* Setup our text list */
306706f2543Smrg	  pszTextList[0] = pszConvertData;
307706f2543Smrg	  pszTextList[1] = NULL;
308706f2543Smrg
309706f2543Smrg	  /* Initialize the text property */
310706f2543Smrg	  xtpText.value = NULL;
311706f2543Smrg	  xtpText.nitems = 0;
312706f2543Smrg
313706f2543Smrg	  /* Create the text property from the text list */
314706f2543Smrg	  if (fUseUnicode)
315706f2543Smrg	    {
316706f2543Smrg#ifdef X_HAVE_UTF8_STRING
317706f2543Smrg	      iReturn = Xutf8TextListToTextProperty (pDisplay,
318706f2543Smrg						     pszTextList,
319706f2543Smrg						     1,
320706f2543Smrg						     xiccesStyle,
321706f2543Smrg						     &xtpText);
322706f2543Smrg#endif
323706f2543Smrg	    }
324706f2543Smrg	  else
325706f2543Smrg	    {
326706f2543Smrg	      iReturn = XmbTextListToTextProperty (pDisplay,
327706f2543Smrg						   pszTextList,
328706f2543Smrg						   1,
329706f2543Smrg						   xiccesStyle,
330706f2543Smrg						   &xtpText);
331706f2543Smrg	    }
332706f2543Smrg	  if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
333706f2543Smrg	    {
334706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
335706f2543Smrg		      "X*TextListToTextProperty failed: %d\n",
336706f2543Smrg		      iReturn);
337706f2543Smrg
338706f2543Smrg	      /* Abort */
339706f2543Smrg	      fAbort = TRUE;
340706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
341706f2543Smrg	    }
342706f2543Smrg
343706f2543Smrg	  /* Free the converted string */
344706f2543Smrg	  free (pszConvertData);
345706f2543Smrg	  pszConvertData = NULL;
346706f2543Smrg
347706f2543Smrg	  /* Copy the clipboard text to the requesting window */
348706f2543Smrg	  iReturn = XChangeProperty (pDisplay,
349706f2543Smrg				     event.xselectionrequest.requestor,
350706f2543Smrg				     event.xselectionrequest.property,
351706f2543Smrg				     event.xselectionrequest.target,
352706f2543Smrg				     8,
353706f2543Smrg				     PropModeReplace,
354706f2543Smrg				     xtpText.value,
355706f2543Smrg				     xtpText.nitems);
356706f2543Smrg	  if (iReturn == BadAlloc || iReturn == BadAtom
357706f2543Smrg	      || iReturn == BadMatch || iReturn == BadValue
358706f2543Smrg	      || iReturn == BadWindow)
359706f2543Smrg	    {
360706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
361706f2543Smrg		      "XChangeProperty failed: %d\n",
362706f2543Smrg		      iReturn);
363706f2543Smrg
364706f2543Smrg	      /* Abort */
365706f2543Smrg	      fAbort = TRUE;
366706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
367706f2543Smrg	    }
368706f2543Smrg
369706f2543Smrg	  /* Release the clipboard data */
370706f2543Smrg	  GlobalUnlock (hGlobal);
371706f2543Smrg	  pszGlobalData = NULL;
372706f2543Smrg	  fCloseClipboard = FALSE;
373706f2543Smrg	  CloseClipboard ();
374706f2543Smrg
375706f2543Smrg	  /* Clean up */
376706f2543Smrg	  XFree (xtpText.value);
377706f2543Smrg	  xtpText.value = NULL;
378706f2543Smrg	  xtpText.nitems = 0;
379706f2543Smrg
380706f2543Smrg	  /* Setup selection notify event */
381706f2543Smrg	  eventSelection.type = SelectionNotify;
382706f2543Smrg	  eventSelection.send_event = True;
383706f2543Smrg	  eventSelection.display = pDisplay;
384706f2543Smrg	  eventSelection.requestor = event.xselectionrequest.requestor;
385706f2543Smrg	  eventSelection.selection = event.xselectionrequest.selection;
386706f2543Smrg	  eventSelection.target = event.xselectionrequest.target;
387706f2543Smrg	  eventSelection.property = event.xselectionrequest.property;
388706f2543Smrg	  eventSelection.time = event.xselectionrequest.time;
389706f2543Smrg
390706f2543Smrg	  /* Notify the requesting window that the operation has completed */
391706f2543Smrg	  iReturn = XSendEvent (pDisplay,
392706f2543Smrg				eventSelection.requestor,
393706f2543Smrg				False,
394706f2543Smrg				0L,
395706f2543Smrg				(XEvent *) &eventSelection);
396706f2543Smrg	  if (iReturn == BadValue || iReturn == BadWindow)
397706f2543Smrg	    {
398706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
399706f2543Smrg		      "XSendEvent () failed\n");
400706f2543Smrg
401706f2543Smrg	      /* Abort */
402706f2543Smrg	      fAbort = TRUE;
403706f2543Smrg	      goto winClipboardFlushXEvents_SelectionRequest_Done;
404706f2543Smrg	    }
405706f2543Smrg
406706f2543Smrg	winClipboardFlushXEvents_SelectionRequest_Done:
407706f2543Smrg	  /* Free allocated resources */
408706f2543Smrg	  if (xtpText.value)
409706f2543Smrg	  {
410706f2543Smrg	    XFree (xtpText.value);
411706f2543Smrg	    xtpText.value = NULL;
412706f2543Smrg	    xtpText.nitems = 0;
413706f2543Smrg	  }
414706f2543Smrg	  free(pszConvertData);
415706f2543Smrg	  if (hGlobal && pszGlobalData)
416706f2543Smrg	    GlobalUnlock (hGlobal);
417706f2543Smrg
418706f2543Smrg	  /*
419706f2543Smrg	   * Send a SelectionNotify event to the requesting
420706f2543Smrg	   * client when we abort.
421706f2543Smrg	   */
422706f2543Smrg	  if (fAbort)
423706f2543Smrg	    {
424706f2543Smrg	      /* Setup selection notify event */
425706f2543Smrg	      eventSelection.type = SelectionNotify;
426706f2543Smrg	      eventSelection.send_event = True;
427706f2543Smrg	      eventSelection.display = pDisplay;
428706f2543Smrg	      eventSelection.requestor = event.xselectionrequest.requestor;
429706f2543Smrg	      eventSelection.selection = event.xselectionrequest.selection;
430706f2543Smrg	      eventSelection.target = event.xselectionrequest.target;
431706f2543Smrg	      eventSelection.property = None;
432706f2543Smrg	      eventSelection.time = event.xselectionrequest.time;
433706f2543Smrg
434706f2543Smrg	      /* Notify the requesting window that the operation is complete */
435706f2543Smrg	      iReturn = XSendEvent (pDisplay,
436706f2543Smrg				    eventSelection.requestor,
437706f2543Smrg				    False,
438706f2543Smrg				    0L,
439706f2543Smrg				    (XEvent *) &eventSelection);
440706f2543Smrg	      if (iReturn == BadValue || iReturn == BadWindow)
441706f2543Smrg		{
442706f2543Smrg		  /*
443706f2543Smrg		   * Should not be a problem if XSendEvent fails because
444706f2543Smrg		   * the client may simply have exited.
445706f2543Smrg		   */
446706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
447706f2543Smrg			  "XSendEvent () failed for abort event.\n");
448706f2543Smrg		}
449706f2543Smrg	    }
450706f2543Smrg
451706f2543Smrg	  /* Close clipboard if it was opened */
452706f2543Smrg	  if (fCloseClipboard)
453706f2543Smrg	  {
454706f2543Smrg	    fCloseClipboard = FALSE;
455706f2543Smrg	    CloseClipboard ();
456706f2543Smrg	  }
457706f2543Smrg	  break;
458706f2543Smrg
459706f2543Smrg
460706f2543Smrg	  /*
461706f2543Smrg	   * SelectionNotify
462706f2543Smrg	   */
463706f2543Smrg
464706f2543Smrg	case SelectionNotify:
465706f2543Smrg
466706f2543Smrg	  winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
467706f2543Smrg	  {
468706f2543Smrg	    char		*pszAtomName;
469706f2543Smrg	    pszAtomName = XGetAtomName (pDisplay,
470706f2543Smrg					event.xselection.selection);
471706f2543Smrg
472706f2543Smrg	    winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
473706f2543Smrg                     pszAtomName);
474706f2543Smrg	    XFree (pszAtomName);
475706f2543Smrg	  }
476706f2543Smrg
477706f2543Smrg	  /*
478706f2543Smrg	   * Request conversion of UTF8 and CompoundText targets.
479706f2543Smrg	   */
480706f2543Smrg	  if (event.xselection.property == None)
481706f2543Smrg	    {
482706f2543Smrg	      if (event.xselection.target == XA_STRING)
483706f2543Smrg		{
484706f2543Smrg		  winDebug ("winClipboardFlushXEvents - SelectionNotify - "
485706f2543Smrg                            "XA_STRING\n");
486706f2543Smrg
487706f2543Smrg		  return WIN_XEVENTS_CONVERT;
488706f2543Smrg		}
489706f2543Smrg	      else if (event.xselection.target == atomUTF8String)
490706f2543Smrg		{
491706f2543Smrg		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
492706f2543Smrg                           "Requesting conversion of UTF8 target.\n");
493706f2543Smrg
494706f2543Smrg		  XConvertSelection (pDisplay,
495706f2543Smrg				     event.xselection.selection,
496706f2543Smrg				     XA_STRING,
497706f2543Smrg				     atomLocalProperty,
498706f2543Smrg				     iWindow,
499706f2543Smrg				     CurrentTime);
500706f2543Smrg
501706f2543Smrg		  /* Process the ConvertSelection event */
502706f2543Smrg		  XFlush (pDisplay);
503706f2543Smrg		  return WIN_XEVENTS_CONVERT;
504706f2543Smrg		}
505706f2543Smrg#ifdef X_HAVE_UTF8_STRING
506706f2543Smrg	      else if (event.xselection.target == atomCompoundText)
507706f2543Smrg		{
508706f2543Smrg		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
509706f2543Smrg                           "Requesting conversion of CompoundText target.\n");
510706f2543Smrg
511706f2543Smrg		  XConvertSelection (pDisplay,
512706f2543Smrg				     event.xselection.selection,
513706f2543Smrg				     atomUTF8String,
514706f2543Smrg				     atomLocalProperty,
515706f2543Smrg				     iWindow,
516706f2543Smrg				     CurrentTime);
517706f2543Smrg
518706f2543Smrg		  /* Process the ConvertSelection event */
519706f2543Smrg		  XFlush (pDisplay);
520706f2543Smrg		  return WIN_XEVENTS_CONVERT;
521706f2543Smrg		}
522706f2543Smrg#endif
523706f2543Smrg	      else
524706f2543Smrg		{
525706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
526706f2543Smrg			  "Unknown format.  Cannot request conversion, "
527706f2543Smrg			  "aborting.\n");
528706f2543Smrg		  break;
529706f2543Smrg		}
530706f2543Smrg	    }
531706f2543Smrg
532706f2543Smrg	  /* Retrieve the size of the stored data */
533706f2543Smrg	  iReturn = XGetWindowProperty (pDisplay,
534706f2543Smrg					iWindow,
535706f2543Smrg					atomLocalProperty,
536706f2543Smrg					0,
537706f2543Smrg					0, /* Don't get data, just size */
538706f2543Smrg					False,
539706f2543Smrg					AnyPropertyType,
540706f2543Smrg					&xtpText.encoding,
541706f2543Smrg					&xtpText.format,
542706f2543Smrg					&xtpText.nitems,
543706f2543Smrg					&ulReturnBytesLeft,
544706f2543Smrg					&xtpText.value);
545706f2543Smrg	  if (iReturn != Success)
546706f2543Smrg	    {
547706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
548706f2543Smrg		      "XGetWindowProperty () failed, aborting: %d\n",
549706f2543Smrg		      iReturn);
550706f2543Smrg	      break;
551706f2543Smrg	    }
552706f2543Smrg
553706f2543Smrg	  winDebug("SelectionNotify - returned data %d left %d\n",
554706f2543Smrg                   xtpText.nitems, ulReturnBytesLeft);
555706f2543Smrg
556706f2543Smrg	  /* Request the selection data */
557706f2543Smrg	  iReturn = XGetWindowProperty (pDisplay,
558706f2543Smrg					iWindow,
559706f2543Smrg					atomLocalProperty,
560706f2543Smrg					0,
561706f2543Smrg					ulReturnBytesLeft,
562706f2543Smrg					False,
563706f2543Smrg					AnyPropertyType,
564706f2543Smrg					&xtpText.encoding,
565706f2543Smrg					&xtpText.format,
566706f2543Smrg					&xtpText.nitems,
567706f2543Smrg					&ulReturnBytesLeft,
568706f2543Smrg					&xtpText.value);
569706f2543Smrg	  if (iReturn != Success)
570706f2543Smrg	    {
571706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
572706f2543Smrg		      "XGetWindowProperty () failed, aborting: %d\n",
573706f2543Smrg		      iReturn);
574706f2543Smrg	      break;
575706f2543Smrg	    }
576706f2543Smrg
577706f2543Smrg	    {
578706f2543Smrg	      char		*pszAtomName = NULL;
579706f2543Smrg
580706f2543Smrg	      winDebug("SelectionNotify - returned data %d left %d\n",
581706f2543Smrg                       xtpText.nitems, ulReturnBytesLeft);
582706f2543Smrg	      pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
583706f2543Smrg	      winDebug("Notify atom name %s\n", pszAtomName);
584706f2543Smrg	      XFree (pszAtomName);
585706f2543Smrg	      pszAtomName = NULL;
586706f2543Smrg	    }
587706f2543Smrg
588706f2543Smrg	  if (fUseUnicode)
589706f2543Smrg	    {
590706f2543Smrg#ifdef X_HAVE_UTF8_STRING
591706f2543Smrg	      /* Convert the text property to a text list */
592706f2543Smrg	      iReturn = Xutf8TextPropertyToTextList (pDisplay,
593706f2543Smrg						     &xtpText,
594706f2543Smrg						     &ppszTextList,
595706f2543Smrg						     &iCount);
596706f2543Smrg#endif
597706f2543Smrg	    }
598706f2543Smrg	  else
599706f2543Smrg	    {
600706f2543Smrg	      iReturn = XmbTextPropertyToTextList (pDisplay,
601706f2543Smrg						   &xtpText,
602706f2543Smrg						   &ppszTextList,
603706f2543Smrg						   &iCount);
604706f2543Smrg	    }
605706f2543Smrg	  if (iReturn == Success || iReturn > 0)
606706f2543Smrg	    {
607706f2543Smrg	      /* Conversion succeeded or some unconvertible characters */
608706f2543Smrg	      if (ppszTextList != NULL)
609706f2543Smrg		{
610706f2543Smrg		  iReturnDataLen = 0;
611706f2543Smrg		  for (i = 0; i < iCount; i++)
612706f2543Smrg		    {
613706f2543Smrg		      iReturnDataLen += strlen(ppszTextList[i]);
614706f2543Smrg		    }
615706f2543Smrg		  pszReturnData = malloc (iReturnDataLen + 1);
616706f2543Smrg		  pszReturnData[0] = '\0';
617706f2543Smrg		  for (i = 0; i < iCount; i++)
618706f2543Smrg		    {
619706f2543Smrg		      strcat (pszReturnData, ppszTextList[i]);
620706f2543Smrg		    }
621706f2543Smrg		}
622706f2543Smrg	      else
623706f2543Smrg		{
624706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
625706f2543Smrg			  "X*TextPropertyToTextList list_return is NULL.\n");
626706f2543Smrg		  pszReturnData = malloc (1);
627706f2543Smrg		  pszReturnData[0] = '\0';
628706f2543Smrg		}
629706f2543Smrg	    }
630706f2543Smrg	  else
631706f2543Smrg	    {
632706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
633706f2543Smrg		      "X*TextPropertyToTextList returned: ");
634706f2543Smrg	      switch (iReturn)
635706f2543Smrg		{
636706f2543Smrg		case XNoMemory:
637706f2543Smrg		  ErrorF ("XNoMemory\n");
638706f2543Smrg		  break;
639706f2543Smrg		case XConverterNotFound:
640706f2543Smrg		  ErrorF ("XConverterNotFound\n");
641706f2543Smrg		  break;
642706f2543Smrg		default:
643706f2543Smrg		  ErrorF ("%d", iReturn);
644706f2543Smrg		  break;
645706f2543Smrg		}
646706f2543Smrg	      pszReturnData = malloc (1);
647706f2543Smrg	      pszReturnData[0] = '\0';
648706f2543Smrg	    }
649706f2543Smrg
650706f2543Smrg	  /* Free the data returned from XGetWindowProperty */
651706f2543Smrg	  if (ppszTextList)
652706f2543Smrg	    XFreeStringList (ppszTextList);
653706f2543Smrg	  ppszTextList = NULL;
654706f2543Smrg	  XFree (xtpText.value);
655706f2543Smrg	  xtpText.value = NULL;
656706f2543Smrg	  xtpText.nitems = 0;
657706f2543Smrg
658706f2543Smrg	  /* Convert the X clipboard string to DOS format */
659706f2543Smrg	  winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));
660706f2543Smrg
661706f2543Smrg	  if (fUseUnicode)
662706f2543Smrg	    {
663706f2543Smrg	      /* Find out how much space needed to convert MBCS to Unicode */
664706f2543Smrg	      iUnicodeLen = MultiByteToWideChar (CP_UTF8,
665706f2543Smrg						 0,
666706f2543Smrg						 pszReturnData,
667706f2543Smrg						 -1,
668706f2543Smrg						 NULL,
669706f2543Smrg						 0);
670706f2543Smrg
671706f2543Smrg	      /* Allocate memory for the Unicode string */
672706f2543Smrg	      pwszUnicodeStr
673706f2543Smrg		= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
674706f2543Smrg	      if (!pwszUnicodeStr)
675706f2543Smrg		{
676706f2543Smrg		  ErrorF ("winClipboardFlushXEvents - SelectionNotify "
677706f2543Smrg			  "malloc failed for pwszUnicodeStr, aborting.\n");
678706f2543Smrg
679706f2543Smrg		  /* Abort */
680706f2543Smrg		  fAbort = TRUE;
681706f2543Smrg		  goto winClipboardFlushXEvents_SelectionNotify_Done;
682706f2543Smrg		}
683706f2543Smrg
684706f2543Smrg	      /* Do the actual conversion */
685706f2543Smrg	      MultiByteToWideChar (CP_UTF8,
686706f2543Smrg				   0,
687706f2543Smrg				   pszReturnData,
688706f2543Smrg				   -1,
689706f2543Smrg				   pwszUnicodeStr,
690706f2543Smrg				   iUnicodeLen);
691706f2543Smrg
692706f2543Smrg	      /* Allocate global memory for the X clipboard data */
693706f2543Smrg	      hGlobal = GlobalAlloc (GMEM_MOVEABLE,
694706f2543Smrg				     sizeof (wchar_t) * (iUnicodeLen + 1));
695706f2543Smrg	    }
696706f2543Smrg	  else
697706f2543Smrg	    {
698706f2543Smrg	      pszConvertData = strdup (pszReturnData);
699706f2543Smrg	      iConvertDataLen = strlen (pszConvertData) + 1;
700706f2543Smrg
701706f2543Smrg	      /* Allocate global memory for the X clipboard data */
702706f2543Smrg	      hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
703706f2543Smrg	    }
704706f2543Smrg
705706f2543Smrg	  free (pszReturnData);
706706f2543Smrg
707706f2543Smrg	  /* Check that global memory was allocated */
708706f2543Smrg	  if (!hGlobal)
709706f2543Smrg	    {
710706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - SelectionNotify "
711706f2543Smrg		      "GlobalAlloc failed, aborting: %ld\n",
712706f2543Smrg		      GetLastError ());
713706f2543Smrg
714706f2543Smrg	      /* Abort */
715706f2543Smrg	      fAbort = TRUE;
716706f2543Smrg	      goto winClipboardFlushXEvents_SelectionNotify_Done;
717706f2543Smrg	    }
718706f2543Smrg
719706f2543Smrg	  /* Obtain a pointer to the global memory */
720706f2543Smrg	  pszGlobalData = GlobalLock (hGlobal);
721706f2543Smrg	  if (pszGlobalData == NULL)
722706f2543Smrg	    {
723706f2543Smrg	      ErrorF ("winClipboardFlushXEvents - Could not lock global "
724706f2543Smrg		      "memory for clipboard transfer\n");
725706f2543Smrg
726706f2543Smrg	      /* Abort */
727706f2543Smrg	      fAbort = TRUE;
728706f2543Smrg	      goto winClipboardFlushXEvents_SelectionNotify_Done;
729706f2543Smrg	    }
730706f2543Smrg
731706f2543Smrg	  /* Copy the returned string into the global memory */
732706f2543Smrg	  if (fUseUnicode)
733706f2543Smrg	    {
734706f2543Smrg	      memcpy (pszGlobalData,
735706f2543Smrg		      pwszUnicodeStr,
736706f2543Smrg		      sizeof (wchar_t) * (iUnicodeLen + 1));
737706f2543Smrg	      free (pwszUnicodeStr);
738706f2543Smrg	      pwszUnicodeStr = NULL;
739706f2543Smrg	    }
740706f2543Smrg	  else
741706f2543Smrg	    {
742706f2543Smrg	      strcpy (pszGlobalData, pszConvertData);
743706f2543Smrg	      free (pszConvertData);
744706f2543Smrg	      pszConvertData = NULL;
745706f2543Smrg	    }
746706f2543Smrg
747706f2543Smrg	  /* Release the pointer to the global memory */
748706f2543Smrg	  GlobalUnlock (hGlobal);
749706f2543Smrg	  pszGlobalData = NULL;
750706f2543Smrg
751706f2543Smrg	  /* Push the selection data to the Windows clipboard */
752706f2543Smrg	  if (fUseUnicode)
753706f2543Smrg	    SetClipboardData (CF_UNICODETEXT, hGlobal);
754706f2543Smrg	  else
755706f2543Smrg	    SetClipboardData (CF_TEXT, hGlobal);
756706f2543Smrg
757706f2543Smrg	  /* Flag that SetClipboardData has been called */
758706f2543Smrg	  fSetClipboardData = FALSE;
759706f2543Smrg
760706f2543Smrg	  /*
761706f2543Smrg	   * NOTE: Do not try to free pszGlobalData, it is owned by
762706f2543Smrg	   * Windows after the call to SetClipboardData ().
763706f2543Smrg	   */
764706f2543Smrg
765706f2543Smrg	winClipboardFlushXEvents_SelectionNotify_Done:
766706f2543Smrg	  /* Free allocated resources */
767706f2543Smrg	  if (ppszTextList)
768706f2543Smrg	    XFreeStringList (ppszTextList);
769706f2543Smrg	  if (xtpText.value)
770706f2543Smrg	  {
771706f2543Smrg	    XFree (xtpText.value);
772706f2543Smrg	    xtpText.value = NULL;
773706f2543Smrg	    xtpText.nitems = 0;
774706f2543Smrg	  }
775706f2543Smrg	  free(pszConvertData);
776706f2543Smrg	  free(pwszUnicodeStr);
777706f2543Smrg	  if (hGlobal && pszGlobalData)
778706f2543Smrg	    GlobalUnlock (hGlobal);
779706f2543Smrg	  if (fSetClipboardData && g_fUnicodeSupport)
780706f2543Smrg	    SetClipboardData (CF_UNICODETEXT, NULL);
781706f2543Smrg	  if (fSetClipboardData)
782706f2543Smrg	    SetClipboardData (CF_TEXT, NULL);
783706f2543Smrg	  return WIN_XEVENTS_NOTIFY;
784706f2543Smrg
785706f2543Smrg        case SelectionClear:
786706f2543Smrg          winDebug("SelectionClear - doing nothing\n");
787706f2543Smrg          break;
788706f2543Smrg
789706f2543Smrg	case PropertyNotify:
790706f2543Smrg	  break;
791706f2543Smrg
792706f2543Smrg	case MappingNotify:
793706f2543Smrg	  break;
794706f2543Smrg
795706f2543Smrg	default:
796706f2543Smrg          ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
797706f2543Smrg	  break;
798706f2543Smrg	}
799706f2543Smrg    }
800706f2543Smrg
801706f2543Smrg  return WIN_XEVENTS_SUCCESS;
802706f2543Smrg}
803