winclipboardxevents.c revision 706f2543
1/*
2 *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
3 *Copyright (C) Colin Harrison 2005-2008
4 *
5 *Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 *"Software"), to deal in the Software without restriction, including
8 *without limitation the rights to use, copy, modify, merge, publish,
9 *distribute, sublicense, and/or sell copies of the Software, and to
10 *permit persons to whom the Software is furnished to do so, subject to
11 *the following conditions:
12 *
13 *The above copyright notice and this permission notice shall be
14 *included in all copies or substantial portions of the Software.
15 *
16 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
20 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 *Except as contained in this notice, the name of the copyright holder(s)
25 *and author(s) shall not be used in advertising or otherwise to promote
26 *the sale, use or other dealings in this Software without prior written
27 *authorization from the copyright holder(s) and author(s).
28 *
29 * Authors:	Harold L Hunt II
30 *              Colin Harrison
31 */
32
33#ifdef HAVE_XWIN_CONFIG_H
34#include <xwin-config.h>
35#endif
36#include "winclipboard.h"
37#include "misc.h"
38
39
40/*
41 * References to external symbols
42 */
43
44extern Bool		g_fUnicodeSupport;
45
46
47/*
48 * Process any pending X events
49 */
50
51int
52winClipboardFlushXEvents (HWND hwnd,
53			  int iWindow,
54			  Display *pDisplay,
55			  Bool fUseUnicode)
56{
57  static Atom atomLocalProperty;
58  static Atom atomCompoundText;
59  static Atom atomUTF8String;
60  static Atom atomTargets;
61  static int generation;
62
63  if (generation != serverGeneration)
64    {
65      generation = serverGeneration;
66      atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
67      atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
68      atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
69      atomTargets = XInternAtom (pDisplay, "TARGETS", False);
70    }
71
72  /* Process all pending events */
73  while (XPending (pDisplay))
74    {
75      XTextProperty		xtpText = {0};
76      XEvent			event;
77      XSelectionEvent		eventSelection;
78      unsigned long		ulReturnBytesLeft;
79      char			*pszReturnData = NULL;
80      char			*pszGlobalData = NULL;
81      int			iReturn;
82      HGLOBAL			hGlobal = NULL;
83      XICCEncodingStyle		xiccesStyle;
84      int			iConvertDataLen = 0;
85      char			*pszConvertData = NULL;
86      char			*pszTextList[2] = {NULL};
87      int			iCount;
88      char			**ppszTextList = NULL;
89      wchar_t			*pwszUnicodeStr = NULL;
90      int			iUnicodeLen = 0;
91      int			iReturnDataLen = 0;
92      int			i;
93      Bool			fAbort = FALSE;
94      Bool			fCloseClipboard = FALSE;
95      Bool			fSetClipboardData = TRUE;
96
97      /* Get the next event - will not block because one is ready */
98      XNextEvent (pDisplay, &event);
99
100      /* Branch on the event type */
101      switch (event.type)
102	{
103	  /*
104	   * SelectionRequest
105	   */
106
107	case SelectionRequest:
108	  {
109	    char			*pszAtomName = NULL;
110	    winDebug("SelectionRequest - target %d\n",
111                     event.xselectionrequest.target);
112
113	    pszAtomName = XGetAtomName (pDisplay,
114					event.xselectionrequest.target);
115	    winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
116	    XFree (pszAtomName);
117	    pszAtomName = NULL;
118	  }
119
120	  /* Abort if invalid target type */
121	  if (event.xselectionrequest.target != XA_STRING
122	      && event.xselectionrequest.target != atomUTF8String
123	      && event.xselectionrequest.target != atomCompoundText
124	      && event.xselectionrequest.target != atomTargets)
125	    {
126	      /* Abort */
127	      fAbort = TRUE;
128	      goto winClipboardFlushXEvents_SelectionRequest_Done;
129	    }
130
131	  /* Handle targets type of request */
132	  if (event.xselectionrequest.target == atomTargets)
133	    {
134	      Atom atomTargetArr[] = {atomTargets,
135				      atomCompoundText,
136				      atomUTF8String,
137				      XA_STRING};
138
139	      /* Try to change the property */
140	      iReturn = XChangeProperty (pDisplay,
141					 event.xselectionrequest.requestor,
142					 event.xselectionrequest.property,
143					 XA_ATOM,
144					 32,
145					 PropModeReplace,
146					 (unsigned char *) atomTargetArr,
147					 (sizeof (atomTargetArr)
148					  / sizeof (atomTargetArr[0])));
149	      if (iReturn == BadAlloc
150		  || iReturn == BadAtom
151		  || iReturn == BadMatch
152		  || iReturn == BadValue
153		  || iReturn == BadWindow)
154		{
155		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
156			  "XChangeProperty failed: %d\n",
157			  iReturn);
158		}
159
160	      /* Setup selection notify xevent */
161	      eventSelection.type	= SelectionNotify;
162	      eventSelection.send_event	= True;
163	      eventSelection.display	= pDisplay;
164	      eventSelection.requestor	= event.xselectionrequest.requestor;
165	      eventSelection.selection	= event.xselectionrequest.selection;
166	      eventSelection.target	= event.xselectionrequest.target;
167	      eventSelection.property	= event.xselectionrequest.property;
168	      eventSelection.time	= event.xselectionrequest.time;
169
170	      /*
171	       * Notify the requesting window that
172	       * the operation has completed
173	       */
174	      iReturn = XSendEvent (pDisplay,
175				    eventSelection.requestor,
176				    False,
177				    0L,
178				    (XEvent *) &eventSelection);
179	      if (iReturn == BadValue || iReturn == BadWindow)
180		{
181		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
182			  "XSendEvent () failed\n");
183		}
184	      break;
185	    }
186
187	  /* Check that clipboard format is available */
188	  if (fUseUnicode
189	      && !IsClipboardFormatAvailable (CF_UNICODETEXT))
190	    {
191	      static int count; /* Hack to stop acroread spamming the log */
192	      static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
193	      if (hwnd != lasthwnd) count = 0;
194	      count++;
195	      if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
196		      "available from Win32 clipboard.  Aborting %d.\n", count);
197	      lasthwnd = hwnd;
198
199	      /* Abort */
200	      fAbort = TRUE;
201	      goto winClipboardFlushXEvents_SelectionRequest_Done;
202	    }
203	  else if (!fUseUnicode
204		   && !IsClipboardFormatAvailable (CF_TEXT))
205	    {
206	      ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
207		      "available from Win32 clipboard.  Aborting.\n");
208
209	      /* Abort */
210	      fAbort = TRUE;
211	      goto winClipboardFlushXEvents_SelectionRequest_Done;
212	    }
213
214	  /* Close clipboard if we have it open already */
215	  if (GetOpenClipboardWindow () == hwnd)
216	    {
217	      CloseClipboard ();
218	    }
219
220	  /* Access the clipboard */
221	  if (!OpenClipboard (hwnd))
222	    {
223	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
224		      "OpenClipboard () failed: %08lx\n",
225		      GetLastError ());
226
227	      /* Abort */
228	      fAbort = TRUE;
229	      goto winClipboardFlushXEvents_SelectionRequest_Done;
230	    }
231
232	  /* Indicate that clipboard was opened */
233	  fCloseClipboard = TRUE;
234
235	  /* Setup the string style */
236	  if (event.xselectionrequest.target == XA_STRING)
237	    xiccesStyle = XStringStyle;
238#ifdef X_HAVE_UTF8_STRING
239	  else if (event.xselectionrequest.target == atomUTF8String)
240	    xiccesStyle = XUTF8StringStyle;
241#endif
242	  else if (event.xselectionrequest.target == atomCompoundText)
243	    xiccesStyle = XCompoundTextStyle;
244	  else
245	    xiccesStyle = XStringStyle;
246
247	  /*
248	   * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
249	   */
250
251	  /* Get a pointer to the clipboard text, in desired format */
252	  if (fUseUnicode)
253	    {
254	      /* Retrieve clipboard data */
255	      hGlobal = GetClipboardData (CF_UNICODETEXT);
256	    }
257	  else
258	    {
259	      /* Retrieve clipboard data */
260	      hGlobal = GetClipboardData (CF_TEXT);
261	    }
262	  if (!hGlobal)
263	    {
264	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
265		      "GetClipboardData () failed: %08lx\n",
266		      GetLastError ());
267
268	      /* Abort */
269	      fAbort = TRUE;
270	      goto winClipboardFlushXEvents_SelectionRequest_Done;
271	    }
272	  pszGlobalData = (char *) GlobalLock (hGlobal);
273
274	  /* Convert the Unicode string to UTF8 (MBCS) */
275	  if (fUseUnicode)
276	    {
277	      iConvertDataLen = WideCharToMultiByte (CP_UTF8,
278						     0,
279						     (LPCWSTR)pszGlobalData,
280						     -1,
281						     NULL,
282						     0,
283						     NULL,
284						     NULL);
285	      /* NOTE: iConvertDataLen includes space for null terminator */
286	      pszConvertData = (char *) malloc (iConvertDataLen);
287	      WideCharToMultiByte (CP_UTF8,
288				   0,
289				   (LPCWSTR)pszGlobalData,
290				   -1,
291				   pszConvertData,
292				   iConvertDataLen,
293				   NULL,
294				   NULL);
295	    }
296	  else
297	    {
298	      pszConvertData = strdup (pszGlobalData);
299	      iConvertDataLen = strlen (pszConvertData) + 1;
300	    }
301
302	  /* Convert DOS string to UNIX string */
303	  winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));
304
305	  /* Setup our text list */
306	  pszTextList[0] = pszConvertData;
307	  pszTextList[1] = NULL;
308
309	  /* Initialize the text property */
310	  xtpText.value = NULL;
311	  xtpText.nitems = 0;
312
313	  /* Create the text property from the text list */
314	  if (fUseUnicode)
315	    {
316#ifdef X_HAVE_UTF8_STRING
317	      iReturn = Xutf8TextListToTextProperty (pDisplay,
318						     pszTextList,
319						     1,
320						     xiccesStyle,
321						     &xtpText);
322#endif
323	    }
324	  else
325	    {
326	      iReturn = XmbTextListToTextProperty (pDisplay,
327						   pszTextList,
328						   1,
329						   xiccesStyle,
330						   &xtpText);
331	    }
332	  if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
333	    {
334	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
335		      "X*TextListToTextProperty failed: %d\n",
336		      iReturn);
337
338	      /* Abort */
339	      fAbort = TRUE;
340	      goto winClipboardFlushXEvents_SelectionRequest_Done;
341	    }
342
343	  /* Free the converted string */
344	  free (pszConvertData);
345	  pszConvertData = NULL;
346
347	  /* Copy the clipboard text to the requesting window */
348	  iReturn = XChangeProperty (pDisplay,
349				     event.xselectionrequest.requestor,
350				     event.xselectionrequest.property,
351				     event.xselectionrequest.target,
352				     8,
353				     PropModeReplace,
354				     xtpText.value,
355				     xtpText.nitems);
356	  if (iReturn == BadAlloc || iReturn == BadAtom
357	      || iReturn == BadMatch || iReturn == BadValue
358	      || iReturn == BadWindow)
359	    {
360	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
361		      "XChangeProperty failed: %d\n",
362		      iReturn);
363
364	      /* Abort */
365	      fAbort = TRUE;
366	      goto winClipboardFlushXEvents_SelectionRequest_Done;
367	    }
368
369	  /* Release the clipboard data */
370	  GlobalUnlock (hGlobal);
371	  pszGlobalData = NULL;
372	  fCloseClipboard = FALSE;
373	  CloseClipboard ();
374
375	  /* Clean up */
376	  XFree (xtpText.value);
377	  xtpText.value = NULL;
378	  xtpText.nitems = 0;
379
380	  /* Setup selection notify event */
381	  eventSelection.type = SelectionNotify;
382	  eventSelection.send_event = True;
383	  eventSelection.display = pDisplay;
384	  eventSelection.requestor = event.xselectionrequest.requestor;
385	  eventSelection.selection = event.xselectionrequest.selection;
386	  eventSelection.target = event.xselectionrequest.target;
387	  eventSelection.property = event.xselectionrequest.property;
388	  eventSelection.time = event.xselectionrequest.time;
389
390	  /* Notify the requesting window that the operation has completed */
391	  iReturn = XSendEvent (pDisplay,
392				eventSelection.requestor,
393				False,
394				0L,
395				(XEvent *) &eventSelection);
396	  if (iReturn == BadValue || iReturn == BadWindow)
397	    {
398	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
399		      "XSendEvent () failed\n");
400
401	      /* Abort */
402	      fAbort = TRUE;
403	      goto winClipboardFlushXEvents_SelectionRequest_Done;
404	    }
405
406	winClipboardFlushXEvents_SelectionRequest_Done:
407	  /* Free allocated resources */
408	  if (xtpText.value)
409	  {
410	    XFree (xtpText.value);
411	    xtpText.value = NULL;
412	    xtpText.nitems = 0;
413	  }
414	  free(pszConvertData);
415	  if (hGlobal && pszGlobalData)
416	    GlobalUnlock (hGlobal);
417
418	  /*
419	   * Send a SelectionNotify event to the requesting
420	   * client when we abort.
421	   */
422	  if (fAbort)
423	    {
424	      /* Setup selection notify event */
425	      eventSelection.type = SelectionNotify;
426	      eventSelection.send_event = True;
427	      eventSelection.display = pDisplay;
428	      eventSelection.requestor = event.xselectionrequest.requestor;
429	      eventSelection.selection = event.xselectionrequest.selection;
430	      eventSelection.target = event.xselectionrequest.target;
431	      eventSelection.property = None;
432	      eventSelection.time = event.xselectionrequest.time;
433
434	      /* Notify the requesting window that the operation is complete */
435	      iReturn = XSendEvent (pDisplay,
436				    eventSelection.requestor,
437				    False,
438				    0L,
439				    (XEvent *) &eventSelection);
440	      if (iReturn == BadValue || iReturn == BadWindow)
441		{
442		  /*
443		   * Should not be a problem if XSendEvent fails because
444		   * the client may simply have exited.
445		   */
446		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
447			  "XSendEvent () failed for abort event.\n");
448		}
449	    }
450
451	  /* Close clipboard if it was opened */
452	  if (fCloseClipboard)
453	  {
454	    fCloseClipboard = FALSE;
455	    CloseClipboard ();
456	  }
457	  break;
458
459
460	  /*
461	   * SelectionNotify
462	   */
463
464	case SelectionNotify:
465
466	  winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
467	  {
468	    char		*pszAtomName;
469	    pszAtomName = XGetAtomName (pDisplay,
470					event.xselection.selection);
471
472	    winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
473                     pszAtomName);
474	    XFree (pszAtomName);
475	  }
476
477	  /*
478	   * Request conversion of UTF8 and CompoundText targets.
479	   */
480	  if (event.xselection.property == None)
481	    {
482	      if (event.xselection.target == XA_STRING)
483		{
484		  winDebug ("winClipboardFlushXEvents - SelectionNotify - "
485                            "XA_STRING\n");
486
487		  return WIN_XEVENTS_CONVERT;
488		}
489	      else if (event.xselection.target == atomUTF8String)
490		{
491		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
492                           "Requesting conversion of UTF8 target.\n");
493
494		  XConvertSelection (pDisplay,
495				     event.xselection.selection,
496				     XA_STRING,
497				     atomLocalProperty,
498				     iWindow,
499				     CurrentTime);
500
501		  /* Process the ConvertSelection event */
502		  XFlush (pDisplay);
503		  return WIN_XEVENTS_CONVERT;
504		}
505#ifdef X_HAVE_UTF8_STRING
506	      else if (event.xselection.target == atomCompoundText)
507		{
508		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
509                           "Requesting conversion of CompoundText target.\n");
510
511		  XConvertSelection (pDisplay,
512				     event.xselection.selection,
513				     atomUTF8String,
514				     atomLocalProperty,
515				     iWindow,
516				     CurrentTime);
517
518		  /* Process the ConvertSelection event */
519		  XFlush (pDisplay);
520		  return WIN_XEVENTS_CONVERT;
521		}
522#endif
523	      else
524		{
525		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
526			  "Unknown format.  Cannot request conversion, "
527			  "aborting.\n");
528		  break;
529		}
530	    }
531
532	  /* Retrieve the size of the stored data */
533	  iReturn = XGetWindowProperty (pDisplay,
534					iWindow,
535					atomLocalProperty,
536					0,
537					0, /* Don't get data, just size */
538					False,
539					AnyPropertyType,
540					&xtpText.encoding,
541					&xtpText.format,
542					&xtpText.nitems,
543					&ulReturnBytesLeft,
544					&xtpText.value);
545	  if (iReturn != Success)
546	    {
547	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
548		      "XGetWindowProperty () failed, aborting: %d\n",
549		      iReturn);
550	      break;
551	    }
552
553	  winDebug("SelectionNotify - returned data %d left %d\n",
554                   xtpText.nitems, ulReturnBytesLeft);
555
556	  /* Request the selection data */
557	  iReturn = XGetWindowProperty (pDisplay,
558					iWindow,
559					atomLocalProperty,
560					0,
561					ulReturnBytesLeft,
562					False,
563					AnyPropertyType,
564					&xtpText.encoding,
565					&xtpText.format,
566					&xtpText.nitems,
567					&ulReturnBytesLeft,
568					&xtpText.value);
569	  if (iReturn != Success)
570	    {
571	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
572		      "XGetWindowProperty () failed, aborting: %d\n",
573		      iReturn);
574	      break;
575	    }
576
577	    {
578	      char		*pszAtomName = NULL;
579
580	      winDebug("SelectionNotify - returned data %d left %d\n",
581                       xtpText.nitems, ulReturnBytesLeft);
582	      pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
583	      winDebug("Notify atom name %s\n", pszAtomName);
584	      XFree (pszAtomName);
585	      pszAtomName = NULL;
586	    }
587
588	  if (fUseUnicode)
589	    {
590#ifdef X_HAVE_UTF8_STRING
591	      /* Convert the text property to a text list */
592	      iReturn = Xutf8TextPropertyToTextList (pDisplay,
593						     &xtpText,
594						     &ppszTextList,
595						     &iCount);
596#endif
597	    }
598	  else
599	    {
600	      iReturn = XmbTextPropertyToTextList (pDisplay,
601						   &xtpText,
602						   &ppszTextList,
603						   &iCount);
604	    }
605	  if (iReturn == Success || iReturn > 0)
606	    {
607	      /* Conversion succeeded or some unconvertible characters */
608	      if (ppszTextList != NULL)
609		{
610		  iReturnDataLen = 0;
611		  for (i = 0; i < iCount; i++)
612		    {
613		      iReturnDataLen += strlen(ppszTextList[i]);
614		    }
615		  pszReturnData = malloc (iReturnDataLen + 1);
616		  pszReturnData[0] = '\0';
617		  for (i = 0; i < iCount; i++)
618		    {
619		      strcat (pszReturnData, ppszTextList[i]);
620		    }
621		}
622	      else
623		{
624		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
625			  "X*TextPropertyToTextList list_return is NULL.\n");
626		  pszReturnData = malloc (1);
627		  pszReturnData[0] = '\0';
628		}
629	    }
630	  else
631	    {
632	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
633		      "X*TextPropertyToTextList returned: ");
634	      switch (iReturn)
635		{
636		case XNoMemory:
637		  ErrorF ("XNoMemory\n");
638		  break;
639		case XConverterNotFound:
640		  ErrorF ("XConverterNotFound\n");
641		  break;
642		default:
643		  ErrorF ("%d", iReturn);
644		  break;
645		}
646	      pszReturnData = malloc (1);
647	      pszReturnData[0] = '\0';
648	    }
649
650	  /* Free the data returned from XGetWindowProperty */
651	  if (ppszTextList)
652	    XFreeStringList (ppszTextList);
653	  ppszTextList = NULL;
654	  XFree (xtpText.value);
655	  xtpText.value = NULL;
656	  xtpText.nitems = 0;
657
658	  /* Convert the X clipboard string to DOS format */
659	  winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));
660
661	  if (fUseUnicode)
662	    {
663	      /* Find out how much space needed to convert MBCS to Unicode */
664	      iUnicodeLen = MultiByteToWideChar (CP_UTF8,
665						 0,
666						 pszReturnData,
667						 -1,
668						 NULL,
669						 0);
670
671	      /* Allocate memory for the Unicode string */
672	      pwszUnicodeStr
673		= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
674	      if (!pwszUnicodeStr)
675		{
676		  ErrorF ("winClipboardFlushXEvents - SelectionNotify "
677			  "malloc failed for pwszUnicodeStr, aborting.\n");
678
679		  /* Abort */
680		  fAbort = TRUE;
681		  goto winClipboardFlushXEvents_SelectionNotify_Done;
682		}
683
684	      /* Do the actual conversion */
685	      MultiByteToWideChar (CP_UTF8,
686				   0,
687				   pszReturnData,
688				   -1,
689				   pwszUnicodeStr,
690				   iUnicodeLen);
691
692	      /* Allocate global memory for the X clipboard data */
693	      hGlobal = GlobalAlloc (GMEM_MOVEABLE,
694				     sizeof (wchar_t) * (iUnicodeLen + 1));
695	    }
696	  else
697	    {
698	      pszConvertData = strdup (pszReturnData);
699	      iConvertDataLen = strlen (pszConvertData) + 1;
700
701	      /* Allocate global memory for the X clipboard data */
702	      hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
703	    }
704
705	  free (pszReturnData);
706
707	  /* Check that global memory was allocated */
708	  if (!hGlobal)
709	    {
710	      ErrorF ("winClipboardFlushXEvents - SelectionNotify "
711		      "GlobalAlloc failed, aborting: %ld\n",
712		      GetLastError ());
713
714	      /* Abort */
715	      fAbort = TRUE;
716	      goto winClipboardFlushXEvents_SelectionNotify_Done;
717	    }
718
719	  /* Obtain a pointer to the global memory */
720	  pszGlobalData = GlobalLock (hGlobal);
721	  if (pszGlobalData == NULL)
722	    {
723	      ErrorF ("winClipboardFlushXEvents - Could not lock global "
724		      "memory for clipboard transfer\n");
725
726	      /* Abort */
727	      fAbort = TRUE;
728	      goto winClipboardFlushXEvents_SelectionNotify_Done;
729	    }
730
731	  /* Copy the returned string into the global memory */
732	  if (fUseUnicode)
733	    {
734	      memcpy (pszGlobalData,
735		      pwszUnicodeStr,
736		      sizeof (wchar_t) * (iUnicodeLen + 1));
737	      free (pwszUnicodeStr);
738	      pwszUnicodeStr = NULL;
739	    }
740	  else
741	    {
742	      strcpy (pszGlobalData, pszConvertData);
743	      free (pszConvertData);
744	      pszConvertData = NULL;
745	    }
746
747	  /* Release the pointer to the global memory */
748	  GlobalUnlock (hGlobal);
749	  pszGlobalData = NULL;
750
751	  /* Push the selection data to the Windows clipboard */
752	  if (fUseUnicode)
753	    SetClipboardData (CF_UNICODETEXT, hGlobal);
754	  else
755	    SetClipboardData (CF_TEXT, hGlobal);
756
757	  /* Flag that SetClipboardData has been called */
758	  fSetClipboardData = FALSE;
759
760	  /*
761	   * NOTE: Do not try to free pszGlobalData, it is owned by
762	   * Windows after the call to SetClipboardData ().
763	   */
764
765	winClipboardFlushXEvents_SelectionNotify_Done:
766	  /* Free allocated resources */
767	  if (ppszTextList)
768	    XFreeStringList (ppszTextList);
769	  if (xtpText.value)
770	  {
771	    XFree (xtpText.value);
772	    xtpText.value = NULL;
773	    xtpText.nitems = 0;
774	  }
775	  free(pszConvertData);
776	  free(pwszUnicodeStr);
777	  if (hGlobal && pszGlobalData)
778	    GlobalUnlock (hGlobal);
779	  if (fSetClipboardData && g_fUnicodeSupport)
780	    SetClipboardData (CF_UNICODETEXT, NULL);
781	  if (fSetClipboardData)
782	    SetClipboardData (CF_TEXT, NULL);
783	  return WIN_XEVENTS_NOTIFY;
784
785        case SelectionClear:
786          winDebug("SelectionClear - doing nothing\n");
787          break;
788
789	case PropertyNotify:
790	  break;
791
792	case MappingNotify:
793	  break;
794
795	default:
796          ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
797	  break;
798	}
799    }
800
801  return WIN_XEVENTS_SUCCESS;
802}
803