Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xwin / winclipboardxevents.c
CommitLineData
a09e091a
JB
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 * Process any pending X events
41 */
42
43int
44winClipboardFlushXEvents(HWND hwnd,
45 int iWindow, Display * pDisplay, Bool fUseUnicode)
46{
47 static Atom atomLocalProperty;
48 static Atom atomCompoundText;
49 static Atom atomUTF8String;
50 static Atom atomTargets;
51 static int generation;
52
53 if (generation != serverGeneration) {
54 generation = serverGeneration;
55 atomLocalProperty = XInternAtom(pDisplay, WIN_LOCAL_PROPERTY, False);
56 atomUTF8String = XInternAtom(pDisplay, "UTF8_STRING", False);
57 atomCompoundText = XInternAtom(pDisplay, "COMPOUND_TEXT", False);
58 atomTargets = XInternAtom(pDisplay, "TARGETS", False);
59 }
60
61 /* Process all pending events */
62 while (XPending(pDisplay)) {
63 XTextProperty xtpText = { 0 };
64 XEvent event;
65 XSelectionEvent eventSelection;
66 unsigned long ulReturnBytesLeft;
67 char *pszReturnData = NULL;
68 char *pszGlobalData = NULL;
69 int iReturn;
70 HGLOBAL hGlobal = NULL;
71 XICCEncodingStyle xiccesStyle;
72 int iConvertDataLen = 0;
73 char *pszConvertData = NULL;
74 char *pszTextList[2] = { NULL };
75 int iCount;
76 char **ppszTextList = NULL;
77 wchar_t *pwszUnicodeStr = NULL;
78 int iUnicodeLen = 0;
79 int iReturnDataLen = 0;
80 int i;
81 Bool fAbort = FALSE;
82 Bool fCloseClipboard = FALSE;
83 Bool fSetClipboardData = TRUE;
84
85 /* Get the next event - will not block because one is ready */
86 XNextEvent(pDisplay, &event);
87
88 /* Branch on the event type */
89 switch (event.type) {
90 /*
91 * SelectionRequest
92 */
93
94 case SelectionRequest:
95 {
96 char *pszAtomName = NULL;
97
98 winDebug("SelectionRequest - target %d\n",
99 event.xselectionrequest.target);
100
101 pszAtomName = XGetAtomName(pDisplay,
102 event.xselectionrequest.target);
103 winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
104 XFree(pszAtomName);
105 pszAtomName = NULL;
106 }
107
108 /* Abort if invalid target type */
109 if (event.xselectionrequest.target != XA_STRING
110 && event.xselectionrequest.target != atomUTF8String
111 && event.xselectionrequest.target != atomCompoundText
112 && event.xselectionrequest.target != atomTargets) {
113 /* Abort */
114 fAbort = TRUE;
115 goto winClipboardFlushXEvents_SelectionRequest_Done;
116 }
117
118 /* Handle targets type of request */
119 if (event.xselectionrequest.target == atomTargets) {
120 Atom atomTargetArr[] = { atomTargets,
121 atomCompoundText,
122 atomUTF8String,
123 XA_STRING
124 };
125
126 /* Try to change the property */
127 iReturn = XChangeProperty(pDisplay,
128 event.xselectionrequest.requestor,
129 event.xselectionrequest.property,
130 XA_ATOM,
131 32,
132 PropModeReplace,
133 (unsigned char *) atomTargetArr,
134 (sizeof(atomTargetArr)
135 / sizeof(atomTargetArr[0])));
136 if (iReturn == BadAlloc
137 || iReturn == BadAtom
138 || iReturn == BadMatch
139 || iReturn == BadValue || iReturn == BadWindow) {
140 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
141 "XChangeProperty failed: %d\n", iReturn);
142 }
143
144 /* Setup selection notify xevent */
145 eventSelection.type = SelectionNotify;
146 eventSelection.send_event = True;
147 eventSelection.display = pDisplay;
148 eventSelection.requestor = event.xselectionrequest.requestor;
149 eventSelection.selection = event.xselectionrequest.selection;
150 eventSelection.target = event.xselectionrequest.target;
151 eventSelection.property = event.xselectionrequest.property;
152 eventSelection.time = event.xselectionrequest.time;
153
154 /*
155 * Notify the requesting window that
156 * the operation has completed
157 */
158 iReturn = XSendEvent(pDisplay,
159 eventSelection.requestor,
160 False, 0L, (XEvent *) &eventSelection);
161 if (iReturn == BadValue || iReturn == BadWindow) {
162 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
163 "XSendEvent () failed\n");
164 }
165 break;
166 }
167
168 /* Close clipboard if we have it open already */
169 if (GetOpenClipboardWindow() == hwnd) {
170 CloseClipboard();
171 }
172
173 /* Access the clipboard */
174 if (!OpenClipboard(hwnd)) {
175 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
176 "OpenClipboard () failed: %08lx\n", GetLastError());
177
178 /* Abort */
179 fAbort = TRUE;
180 goto winClipboardFlushXEvents_SelectionRequest_Done;
181 }
182
183 /* Indicate that clipboard was opened */
184 fCloseClipboard = TRUE;
185
186 /* Check that clipboard format is available */
187 if (fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
188 static int count; /* Hack to stop acroread spamming the log */
189 static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
190
191 if (hwnd != lasthwnd)
192 count = 0;
193 count++;
194 if (count < 6)
195 ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
196 "available from Win32 clipboard. Aborting %d.\n",
197 count);
198 lasthwnd = hwnd;
199
200 /* Abort */
201 fAbort = TRUE;
202 goto winClipboardFlushXEvents_SelectionRequest_Done;
203 }
204 else if (!fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
205 ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
206 "available from Win32 clipboard. Aborting.\n");
207
208 /* Abort */
209 fAbort = TRUE;
210 goto winClipboardFlushXEvents_SelectionRequest_Done;
211 }
212
213 /* Setup the string style */
214 if (event.xselectionrequest.target == XA_STRING)
215 xiccesStyle = XStringStyle;
216#ifdef X_HAVE_UTF8_STRING
217 else if (event.xselectionrequest.target == atomUTF8String)
218 xiccesStyle = XUTF8StringStyle;
219#endif
220 else if (event.xselectionrequest.target == atomCompoundText)
221 xiccesStyle = XCompoundTextStyle;
222 else
223 xiccesStyle = XStringStyle;
224
225 /* Get a pointer to the clipboard text, in desired format */
226 if (fUseUnicode) {
227 /* Retrieve clipboard data */
228 hGlobal = GetClipboardData(CF_UNICODETEXT);
229 }
230 else {
231 /* Retrieve clipboard data */
232 hGlobal = GetClipboardData(CF_TEXT);
233 }
234 if (!hGlobal) {
235 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
236 "GetClipboardData () failed: %08lx\n", GetLastError());
237
238 /* Abort */
239 fAbort = TRUE;
240 goto winClipboardFlushXEvents_SelectionRequest_Done;
241 }
242 pszGlobalData = (char *) GlobalLock(hGlobal);
243
244 /* Convert the Unicode string to UTF8 (MBCS) */
245 if (fUseUnicode) {
246 iConvertDataLen = WideCharToMultiByte(CP_UTF8,
247 0,
248 (LPCWSTR) pszGlobalData,
249 -1, NULL, 0, NULL, NULL);
250 /* NOTE: iConvertDataLen includes space for null terminator */
251 pszConvertData = (char *) malloc(iConvertDataLen);
252 WideCharToMultiByte(CP_UTF8,
253 0,
254 (LPCWSTR) pszGlobalData,
255 -1,
256 pszConvertData,
257 iConvertDataLen, NULL, NULL);
258 }
259 else {
260 pszConvertData = strdup(pszGlobalData);
261 iConvertDataLen = strlen(pszConvertData) + 1;
262 }
263
264 /* Convert DOS string to UNIX string */
265 winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));
266
267 /* Setup our text list */
268 pszTextList[0] = pszConvertData;
269 pszTextList[1] = NULL;
270
271 /* Initialize the text property */
272 xtpText.value = NULL;
273 xtpText.nitems = 0;
274
275 /* Create the text property from the text list */
276 if (fUseUnicode) {
277#ifdef X_HAVE_UTF8_STRING
278 iReturn = Xutf8TextListToTextProperty(pDisplay,
279 pszTextList,
280 1, xiccesStyle, &xtpText);
281#endif
282 }
283 else {
284 iReturn = XmbTextListToTextProperty(pDisplay,
285 pszTextList,
286 1, xiccesStyle, &xtpText);
287 }
288 if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
289 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
290 "X*TextListToTextProperty failed: %d\n", iReturn);
291
292 /* Abort */
293 fAbort = TRUE;
294 goto winClipboardFlushXEvents_SelectionRequest_Done;
295 }
296
297 /* Free the converted string */
298 free(pszConvertData);
299 pszConvertData = NULL;
300
301 /* Copy the clipboard text to the requesting window */
302 iReturn = XChangeProperty(pDisplay,
303 event.xselectionrequest.requestor,
304 event.xselectionrequest.property,
305 event.xselectionrequest.target,
306 8,
307 PropModeReplace,
308 xtpText.value, xtpText.nitems);
309 if (iReturn == BadAlloc || iReturn == BadAtom
310 || iReturn == BadMatch || iReturn == BadValue
311 || iReturn == BadWindow) {
312 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
313 "XChangeProperty failed: %d\n", iReturn);
314
315 /* Abort */
316 fAbort = TRUE;
317 goto winClipboardFlushXEvents_SelectionRequest_Done;
318 }
319
320 /* Release the clipboard data */
321 GlobalUnlock(hGlobal);
322 pszGlobalData = NULL;
323 fCloseClipboard = FALSE;
324 CloseClipboard();
325
326 /* Clean up */
327 XFree(xtpText.value);
328 xtpText.value = NULL;
329 xtpText.nitems = 0;
330
331 /* Setup selection notify event */
332 eventSelection.type = SelectionNotify;
333 eventSelection.send_event = True;
334 eventSelection.display = pDisplay;
335 eventSelection.requestor = event.xselectionrequest.requestor;
336 eventSelection.selection = event.xselectionrequest.selection;
337 eventSelection.target = event.xselectionrequest.target;
338 eventSelection.property = event.xselectionrequest.property;
339 eventSelection.time = event.xselectionrequest.time;
340
341 /* Notify the requesting window that the operation has completed */
342 iReturn = XSendEvent(pDisplay,
343 eventSelection.requestor,
344 False, 0L, (XEvent *) &eventSelection);
345 if (iReturn == BadValue || iReturn == BadWindow) {
346 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
347 "XSendEvent () failed\n");
348
349 /* Abort */
350 fAbort = TRUE;
351 goto winClipboardFlushXEvents_SelectionRequest_Done;
352 }
353
354 winClipboardFlushXEvents_SelectionRequest_Done:
355 /* Free allocated resources */
356 if (xtpText.value) {
357 XFree(xtpText.value);
358 xtpText.value = NULL;
359 xtpText.nitems = 0;
360 }
361 free(pszConvertData);
362 if (hGlobal && pszGlobalData)
363 GlobalUnlock(hGlobal);
364
365 /*
366 * Send a SelectionNotify event to the requesting
367 * client when we abort.
368 */
369 if (fAbort) {
370 /* Setup selection notify event */
371 eventSelection.type = SelectionNotify;
372 eventSelection.send_event = True;
373 eventSelection.display = pDisplay;
374 eventSelection.requestor = event.xselectionrequest.requestor;
375 eventSelection.selection = event.xselectionrequest.selection;
376 eventSelection.target = event.xselectionrequest.target;
377 eventSelection.property = None;
378 eventSelection.time = event.xselectionrequest.time;
379
380 /* Notify the requesting window that the operation is complete */
381 iReturn = XSendEvent(pDisplay,
382 eventSelection.requestor,
383 False, 0L, (XEvent *) &eventSelection);
384 if (iReturn == BadValue || iReturn == BadWindow) {
385 /*
386 * Should not be a problem if XSendEvent fails because
387 * the client may simply have exited.
388 */
389 ErrorF("winClipboardFlushXEvents - SelectionRequest - "
390 "XSendEvent () failed for abort event.\n");
391 }
392 }
393
394 /* Close clipboard if it was opened */
395 if (fCloseClipboard) {
396 fCloseClipboard = FALSE;
397 CloseClipboard();
398 }
399 break;
400
401 /*
402 * SelectionNotify
403 */
404
405 case SelectionNotify:
406
407 winDebug("winClipboardFlushXEvents - SelectionNotify\n");
408 {
409 char *pszAtomName;
410
411 pszAtomName = XGetAtomName(pDisplay,
412 event.xselection.selection);
413
414 winDebug
415 ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
416 pszAtomName);
417 XFree(pszAtomName);
418 }
419
420 /*
421 * Request conversion of UTF8 and CompoundText targets.
422 */
423 if (event.xselection.property == None) {
424 if (event.xselection.target == XA_STRING) {
425 winDebug("winClipboardFlushXEvents - SelectionNotify - "
426 "XA_STRING\n");
427
428 return WIN_XEVENTS_CONVERT;
429 }
430 else if (event.xselection.target == atomUTF8String) {
431 winDebug("winClipboardFlushXEvents - SelectionNotify - "
432 "Requesting conversion of UTF8 target.\n");
433
434 XConvertSelection(pDisplay,
435 event.xselection.selection,
436 XA_STRING,
437 atomLocalProperty, iWindow, CurrentTime);
438
439 /* Process the ConvertSelection event */
440 XFlush(pDisplay);
441 return WIN_XEVENTS_CONVERT;
442 }
443#ifdef X_HAVE_UTF8_STRING
444 else if (event.xselection.target == atomCompoundText) {
445 winDebug("winClipboardFlushXEvents - SelectionNotify - "
446 "Requesting conversion of CompoundText target.\n");
447
448 XConvertSelection(pDisplay,
449 event.xselection.selection,
450 atomUTF8String,
451 atomLocalProperty, iWindow, CurrentTime);
452
453 /* Process the ConvertSelection event */
454 XFlush(pDisplay);
455 return WIN_XEVENTS_CONVERT;
456 }
457#endif
458 else {
459 ErrorF("winClipboardFlushXEvents - SelectionNotify - "
460 "Unknown format. Cannot request conversion, "
461 "aborting.\n");
462 break;
463 }
464 }
465
466 /* Retrieve the size of the stored data */
467 iReturn = XGetWindowProperty(pDisplay, iWindow, atomLocalProperty, 0, 0, /* Don't get data, just size */
468 False,
469 AnyPropertyType,
470 &xtpText.encoding,
471 &xtpText.format,
472 &xtpText.nitems,
473 &ulReturnBytesLeft, &xtpText.value);
474 if (iReturn != Success) {
475 ErrorF("winClipboardFlushXEvents - SelectionNotify - "
476 "XGetWindowProperty () failed, aborting: %d\n", iReturn);
477 break;
478 }
479
480 winDebug("SelectionNotify - returned data %d left %d\n",
481 xtpText.nitems, ulReturnBytesLeft);
482
483 /* Request the selection data */
484 iReturn = XGetWindowProperty(pDisplay,
485 iWindow,
486 atomLocalProperty,
487 0,
488 ulReturnBytesLeft,
489 False,
490 AnyPropertyType,
491 &xtpText.encoding,
492 &xtpText.format,
493 &xtpText.nitems,
494 &ulReturnBytesLeft, &xtpText.value);
495 if (iReturn != Success) {
496 ErrorF("winClipboardFlushXEvents - SelectionNotify - "
497 "XGetWindowProperty () failed, aborting: %d\n", iReturn);
498 break;
499 }
500
501 {
502 char *pszAtomName = NULL;
503
504 winDebug("SelectionNotify - returned data %d left %d\n",
505 xtpText.nitems, ulReturnBytesLeft);
506 pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
507 winDebug("Notify atom name %s\n", pszAtomName);
508 XFree(pszAtomName);
509 pszAtomName = NULL;
510 }
511
512 if (fUseUnicode) {
513#ifdef X_HAVE_UTF8_STRING
514 /* Convert the text property to a text list */
515 iReturn = Xutf8TextPropertyToTextList(pDisplay,
516 &xtpText,
517 &ppszTextList, &iCount);
518#endif
519 }
520 else {
521 iReturn = XmbTextPropertyToTextList(pDisplay,
522 &xtpText,
523 &ppszTextList, &iCount);
524 }
525 if (iReturn == Success || iReturn > 0) {
526 /* Conversion succeeded or some unconvertible characters */
527 if (ppszTextList != NULL) {
528 iReturnDataLen = 0;
529 for (i = 0; i < iCount; i++) {
530 iReturnDataLen += strlen(ppszTextList[i]);
531 }
532 pszReturnData = malloc(iReturnDataLen + 1);
533 pszReturnData[0] = '\0';
534 for (i = 0; i < iCount; i++) {
535 strcat(pszReturnData, ppszTextList[i]);
536 }
537 }
538 else {
539 ErrorF("winClipboardFlushXEvents - SelectionNotify - "
540 "X*TextPropertyToTextList list_return is NULL.\n");
541 pszReturnData = malloc(1);
542 pszReturnData[0] = '\0';
543 }
544 }
545 else {
546 ErrorF("winClipboardFlushXEvents - SelectionNotify - "
547 "X*TextPropertyToTextList returned: ");
548 switch (iReturn) {
549 case XNoMemory:
550 ErrorF("XNoMemory\n");
551 break;
552 case XLocaleNotSupported:
553 ErrorF("XLocaleNotSupported\n");
554 break;
555 case XConverterNotFound:
556 ErrorF("XConverterNotFound\n");
557 break;
558 default:
559 ErrorF("%d\n", iReturn);
560 break;
561 }
562 pszReturnData = malloc(1);
563 pszReturnData[0] = '\0';
564 }
565
566 /* Free the data returned from XGetWindowProperty */
567 if (ppszTextList)
568 XFreeStringList(ppszTextList);
569 ppszTextList = NULL;
570 XFree(xtpText.value);
571 xtpText.value = NULL;
572 xtpText.nitems = 0;
573
574 /* Convert the X clipboard string to DOS format */
575 winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));
576
577 if (fUseUnicode) {
578 /* Find out how much space needed to convert MBCS to Unicode */
579 iUnicodeLen = MultiByteToWideChar(CP_UTF8,
580 0,
581 pszReturnData, -1, NULL, 0);
582
583 /* Allocate memory for the Unicode string */
584 pwszUnicodeStr
585 = (wchar_t *) malloc(sizeof(wchar_t) * (iUnicodeLen + 1));
586 if (!pwszUnicodeStr) {
587 ErrorF("winClipboardFlushXEvents - SelectionNotify "
588 "malloc failed for pwszUnicodeStr, aborting.\n");
589
590 /* Abort */
591 fAbort = TRUE;
592 goto winClipboardFlushXEvents_SelectionNotify_Done;
593 }
594
595 /* Do the actual conversion */
596 MultiByteToWideChar(CP_UTF8,
597 0,
598 pszReturnData,
599 -1, pwszUnicodeStr, iUnicodeLen);
600
601 /* Allocate global memory for the X clipboard data */
602 hGlobal = GlobalAlloc(GMEM_MOVEABLE,
603 sizeof(wchar_t) * (iUnicodeLen + 1));
604 }
605 else {
606 pszConvertData = strdup(pszReturnData);
607 iConvertDataLen = strlen(pszConvertData) + 1;
608
609 /* Allocate global memory for the X clipboard data */
610 hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
611 }
612
613 free(pszReturnData);
614
615 /* Check that global memory was allocated */
616 if (!hGlobal) {
617 ErrorF("winClipboardFlushXEvents - SelectionNotify "
618 "GlobalAlloc failed, aborting: %ld\n", GetLastError());
619
620 /* Abort */
621 fAbort = TRUE;
622 goto winClipboardFlushXEvents_SelectionNotify_Done;
623 }
624
625 /* Obtain a pointer to the global memory */
626 pszGlobalData = GlobalLock(hGlobal);
627 if (pszGlobalData == NULL) {
628 ErrorF("winClipboardFlushXEvents - Could not lock global "
629 "memory for clipboard transfer\n");
630
631 /* Abort */
632 fAbort = TRUE;
633 goto winClipboardFlushXEvents_SelectionNotify_Done;
634 }
635
636 /* Copy the returned string into the global memory */
637 if (fUseUnicode) {
638 memcpy(pszGlobalData,
639 pwszUnicodeStr, sizeof(wchar_t) * (iUnicodeLen + 1));
640 free(pwszUnicodeStr);
641 pwszUnicodeStr = NULL;
642 }
643 else {
644 strcpy(pszGlobalData, pszConvertData);
645 free(pszConvertData);
646 pszConvertData = NULL;
647 }
648
649 /* Release the pointer to the global memory */
650 GlobalUnlock(hGlobal);
651 pszGlobalData = NULL;
652
653 /* Push the selection data to the Windows clipboard */
654 if (fUseUnicode)
655 SetClipboardData(CF_UNICODETEXT, hGlobal);
656 else
657 SetClipboardData(CF_TEXT, hGlobal);
658
659 /* Flag that SetClipboardData has been called */
660 fSetClipboardData = FALSE;
661
662 /*
663 * NOTE: Do not try to free pszGlobalData, it is owned by
664 * Windows after the call to SetClipboardData ().
665 */
666
667 winClipboardFlushXEvents_SelectionNotify_Done:
668 /* Free allocated resources */
669 if (ppszTextList)
670 XFreeStringList(ppszTextList);
671 if (xtpText.value) {
672 XFree(xtpText.value);
673 xtpText.value = NULL;
674 xtpText.nitems = 0;
675 }
676 free(pszConvertData);
677 free(pwszUnicodeStr);
678 if (hGlobal && pszGlobalData)
679 GlobalUnlock(hGlobal);
680 if (fSetClipboardData) {
681 SetClipboardData(CF_UNICODETEXT, NULL);
682 SetClipboardData(CF_TEXT, NULL);
683 }
684 return WIN_XEVENTS_NOTIFY;
685
686 case SelectionClear:
687 winDebug("SelectionClear - doing nothing\n");
688 break;
689
690 case PropertyNotify:
691 break;
692
693 case MappingNotify:
694 break;
695
696 default:
697 ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
698 event.type);
699 break;
700 }
701 }
702
703 return WIN_XEVENTS_SUCCESS;
704}