Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xwin / winclipboardxevents.c
blobd4c617bec0bb3fa385ad7f2ee8d9ff04e8812b08
1 /*
2 *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of Harold L Hunt II
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from Harold L Hunt II.
28 * Authors: Harold L Hunt II
31 #ifdef HAVE_XWIN_CONFIG_H
32 #include <xwin-config.h>
33 #endif
34 #include "winclipboard.h"
38 * References to external symbols
41 extern Bool g_fUnicodeSupport;
45 * Process any pending X events
48 int
49 winClipboardFlushXEvents (HWND hwnd,
50 int iWindow,
51 Display *pDisplay,
52 Bool fUseUnicode)
54 Atom atomLocalProperty = XInternAtom (pDisplay,
55 WIN_LOCAL_PROPERTY,
56 False);
57 Atom atomUTF8String = XInternAtom (pDisplay,
58 "UTF8_STRING",
59 False);
60 Atom atomCompoundText = XInternAtom (pDisplay,
61 "COMPOUND_TEXT",
62 False);
63 Atom atomTargets = XInternAtom (pDisplay,
64 "TARGETS",
65 False);
67 /* Process all pending events */
68 while (XPending (pDisplay))
70 XTextProperty xtpText = {0};
71 XEvent event;
72 XSelectionEvent eventSelection;
73 unsigned long ulReturnBytesLeft;
74 unsigned char *pszReturnData = NULL;
75 char *pszGlobalData = NULL;
76 int iReturn;
77 HGLOBAL hGlobal = NULL;
78 XICCEncodingStyle xiccesStyle;
79 int iConvertDataLen = 0;
80 char *pszConvertData = NULL;
81 char *pszTextList[2] = {NULL};
82 int iCount;
83 char **ppszTextList = NULL;
84 wchar_t *pwszUnicodeStr = NULL;
85 int iUnicodeLen = 0;
86 int iReturnDataLen = 0;
87 int i;
88 Bool fAbort = FALSE;
89 Bool fCloseClipboard = FALSE;
90 Bool fSetClipboardData = TRUE;
92 /* Get the next event - will not block because one is ready */
93 XNextEvent (pDisplay, &event);
95 /* Branch on the event type */
96 switch (event.type)
99 * SelectionRequest
102 case SelectionRequest:
103 #if 0
105 char *pszAtomName = NULL;
107 ErrorF ("SelectionRequest - target %d\n",
108 event.xselectionrequest.target);
110 pszAtomName = XGetAtomName (pDisplay,
111 event.xselectionrequest.target);
112 ErrorF ("SelectionRequest - Target atom name %s\n", pszAtomName);
113 XFree (pszAtomName);
114 pszAtomName = NULL;
116 #endif
118 /* Abort if invalid target type */
119 if (event.xselectionrequest.target != XA_STRING
120 && event.xselectionrequest.target != atomUTF8String
121 && event.xselectionrequest.target != atomCompoundText
122 && event.xselectionrequest.target != atomTargets)
124 /* Abort */
125 fAbort = TRUE;
126 goto winClipboardFlushXEvents_SelectionRequest_Done;
129 /* Handle targets type of request */
130 if (event.xselectionrequest.target == atomTargets)
132 Atom atomTargetArr[] = {atomTargets,
133 atomCompoundText,
134 atomUTF8String,
135 XA_STRING};
137 /* Try to change the property */
138 iReturn = XChangeProperty (pDisplay,
139 event.xselectionrequest.requestor,
140 event.xselectionrequest.property,
141 XA_ATOM,
143 PropModeReplace,
144 (unsigned char *) atomTargetArr,
145 (sizeof (atomTargetArr)
146 / sizeof (atomTargetArr[0])));
147 if (iReturn == BadAlloc
148 || iReturn == BadAtom
149 || iReturn == BadMatch
150 || iReturn == BadValue
151 || iReturn == BadWindow)
153 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
154 "XChangeProperty failed: %d\n",
155 iReturn);
158 /* Setup selection notify xevent */
159 eventSelection.type = SelectionNotify;
160 eventSelection.send_event = True;
161 eventSelection.display = pDisplay;
162 eventSelection.requestor = event.xselectionrequest.requestor;
163 eventSelection.selection = event.xselectionrequest.selection;
164 eventSelection.target = event.xselectionrequest.target;
165 eventSelection.property = event.xselectionrequest.property;
166 eventSelection.time = event.xselectionrequest.time;
169 * Notify the requesting window that
170 * the operation has completed
172 iReturn = XSendEvent (pDisplay,
173 eventSelection.requestor,
174 False,
176 (XEvent *) &eventSelection);
177 if (iReturn == BadValue || iReturn == BadWindow)
179 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
180 "XSendEvent () failed\n");
182 break;
185 /* Check that clipboard format is available */
186 if (fUseUnicode
187 && !IsClipboardFormatAvailable (CF_UNICODETEXT))
189 ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
190 "available from Win32 clipboard. Aborting.\n");
192 /* Abort */
193 fAbort = TRUE;
194 goto winClipboardFlushXEvents_SelectionRequest_Done;
196 else if (!fUseUnicode
197 && !IsClipboardFormatAvailable (CF_TEXT))
199 ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
200 "available from Win32 clipboard. Aborting.\n");
202 /* Abort */
203 fAbort = TRUE;
204 goto winClipboardFlushXEvents_SelectionRequest_Done;
207 /* Close clipboard if we have it open already */
208 if (GetOpenClipboardWindow () == hwnd)
210 CloseClipboard ();
213 /* Access the clipboard */
214 if (!OpenClipboard (hwnd))
216 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
217 "OpenClipboard () failed: %08x\n",
218 GetLastError ());
220 /* Abort */
221 fAbort = TRUE;
222 goto winClipboardFlushXEvents_SelectionRequest_Done;
225 /* Indicate that clipboard was opened */
226 fCloseClipboard = TRUE;
228 /* Setup the string style */
229 if (event.xselectionrequest.target == XA_STRING)
230 xiccesStyle = XStringStyle;
231 #ifdef X_HAVE_UTF8_STRING
232 else if (event.xselectionrequest.target == atomUTF8String)
233 xiccesStyle = XUTF8StringStyle;
234 #endif
235 else if (event.xselectionrequest.target == atomCompoundText)
236 xiccesStyle = XCompoundTextStyle;
237 else
238 xiccesStyle = XStringStyle;
241 * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
244 /* Get a pointer to the clipboard text, in desired format */
245 if (fUseUnicode)
247 /* Retrieve clipboard data */
248 hGlobal = GetClipboardData (CF_UNICODETEXT);
250 else
252 /* Retrieve clipboard data */
253 hGlobal = GetClipboardData (CF_TEXT);
255 if (!hGlobal)
257 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
258 "GetClipboardData () failed: %08x\n",
259 GetLastError ());
261 /* Abort */
262 fAbort = TRUE;
263 goto winClipboardFlushXEvents_SelectionRequest_Done;
265 pszGlobalData = (char *) GlobalLock (hGlobal);
267 /* Convert the Unicode string to UTF8 (MBCS) */
268 if (fUseUnicode)
270 iConvertDataLen = WideCharToMultiByte (CP_UTF8,
272 (LPCWSTR)pszGlobalData,
274 NULL,
276 NULL,
277 NULL);
278 /* NOTE: iConvertDataLen includes space for null terminator */
279 pszConvertData = (char *) malloc (iConvertDataLen);
280 WideCharToMultiByte (CP_UTF8,
282 (LPCWSTR)pszGlobalData,
284 pszConvertData,
285 iConvertDataLen,
286 NULL,
287 NULL);
289 else
291 pszConvertData = strdup (pszGlobalData);
292 iConvertDataLen = strlen (pszConvertData) + 1;
295 /* Convert DOS string to UNIX string */
296 winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));
298 /* Setup our text list */
299 pszTextList[0] = pszConvertData;
300 pszTextList[1] = NULL;
302 /* Initialize the text property */
303 xtpText.value = NULL;
305 /* Create the text property from the text list */
306 if (fUseUnicode)
308 #ifdef X_HAVE_UTF8_STRING
309 iReturn = Xutf8TextListToTextProperty (pDisplay,
310 pszTextList,
312 xiccesStyle,
313 &xtpText);
314 #endif
316 else
318 iReturn = XmbTextListToTextProperty (pDisplay,
319 pszTextList,
321 xiccesStyle,
322 &xtpText);
324 if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
326 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
327 "X*TextListToTextProperty failed: %d\n",
328 iReturn);
330 /* Abort */
331 fAbort = TRUE;
332 goto winClipboardFlushXEvents_SelectionRequest_Done;
335 /* Free the converted string */
336 free (pszConvertData);
337 pszConvertData = NULL;
339 /* Copy the clipboard text to the requesting window */
340 iReturn = XChangeProperty (pDisplay,
341 event.xselectionrequest.requestor,
342 event.xselectionrequest.property,
343 event.xselectionrequest.target,
345 PropModeReplace,
346 xtpText.value,
347 xtpText.nitems);
348 if (iReturn == BadAlloc || iReturn == BadAtom
349 || iReturn == BadMatch || iReturn == BadValue
350 || iReturn == BadWindow)
352 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
353 "XChangeProperty failed: %d\n",
354 iReturn);
356 /* Abort */
357 fAbort = TRUE;
358 goto winClipboardFlushXEvents_SelectionRequest_Done;
361 /* Release the clipboard data */
362 GlobalUnlock (hGlobal);
363 pszGlobalData = NULL;
365 /* Clean up */
366 XFree (xtpText.value);
367 xtpText.value = NULL;
369 /* Setup selection notify event */
370 eventSelection.type = SelectionNotify;
371 eventSelection.send_event = True;
372 eventSelection.display = pDisplay;
373 eventSelection.requestor = event.xselectionrequest.requestor;
374 eventSelection.selection = event.xselectionrequest.selection;
375 eventSelection.target = event.xselectionrequest.target;
376 eventSelection.property = event.xselectionrequest.property;
377 eventSelection.time = event.xselectionrequest.time;
379 /* Notify the requesting window that the operation has completed */
380 iReturn = XSendEvent (pDisplay,
381 eventSelection.requestor,
382 False,
384 (XEvent *) &eventSelection);
385 if (iReturn == BadValue || iReturn == BadWindow)
387 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
388 "XSendEvent () failed\n");
390 /* Abort */
391 fAbort = TRUE;
392 goto winClipboardFlushXEvents_SelectionRequest_Done;
395 winClipboardFlushXEvents_SelectionRequest_Done:
396 /* Free allocated resources */
397 if (xtpText.value)
398 XFree (xtpText.value);
399 if (pszConvertData)
400 free (pszConvertData);
401 if (hGlobal && pszGlobalData)
402 GlobalUnlock (hGlobal);
405 * Send a SelectionNotify event to the requesting
406 * client when we abort.
408 if (fAbort)
410 /* Setup selection notify event */
411 eventSelection.type = SelectionNotify;
412 eventSelection.send_event = True;
413 eventSelection.display = pDisplay;
414 eventSelection.requestor = event.xselectionrequest.requestor;
415 eventSelection.selection = event.xselectionrequest.selection;
416 eventSelection.target = event.xselectionrequest.target;
417 eventSelection.property = None;
418 eventSelection.time = event.xselectionrequest.time;
420 /* Notify the requesting window that the operation is complete */
421 iReturn = XSendEvent (pDisplay,
422 eventSelection.requestor,
423 False,
425 (XEvent *) &eventSelection);
426 if (iReturn == BadValue || iReturn == BadWindow)
429 * Should not be a problem if XSendEvent fails because
430 * the client may simply have exited.
432 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
433 "XSendEvent () failed for abort event.\n");
437 /* Close clipboard if it was opened */
438 if (fCloseClipboard)
439 CloseClipboard ();
440 break;
444 * SelectionNotify
447 case SelectionNotify:
448 #if 0
449 ErrorF ("winClipboardFlushXEvents - SelectionNotify\n");
451 char *pszAtomName;
453 pszAtomName = XGetAtomName (pDisplay,
454 event.xselection.selection);
456 ErrorF ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
457 pszAtomName);
459 XFree (pszAtomName);
461 #endif
465 * Request conversion of UTF8 and CompoundText targets.
467 if (event.xselection.property == None)
469 if (event.xselection.target == XA_STRING)
471 #if 0
472 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
473 "XA_STRING\n");
474 #endif
475 return WIN_XEVENTS_CONVERT;
477 else if (event.xselection.target == atomUTF8String)
479 #if 0
480 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
481 "Requesting conversion of UTF8 target.\n");
482 #endif
483 iReturn = XConvertSelection (pDisplay,
484 event.xselection.selection,
485 XA_STRING,
486 atomLocalProperty,
487 iWindow,
488 CurrentTime);
489 if (iReturn != Success)
491 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
492 "XConvertSelection () failed for UTF8String, "
493 "aborting: %d\n",
494 iReturn);
495 break;
498 /* Process the ConvertSelection event */
499 XFlush (pDisplay);
500 return WIN_XEVENTS_CONVERT;
502 #ifdef X_HAVE_UTF8_STRING
503 else if (event.xselection.target == atomCompoundText)
505 #if 0
506 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
507 "Requesting conversion of CompoundText target.\n");
508 #endif
509 iReturn = XConvertSelection (pDisplay,
510 event.xselection.selection,
511 atomUTF8String,
512 atomLocalProperty,
513 iWindow,
514 CurrentTime);
515 if (iReturn != Success)
517 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
518 "XConvertSelection () failed for CompoundText, "
519 "aborting: %d\n",
520 iReturn);
521 break;
524 /* Process the ConvertSelection event */
525 XFlush (pDisplay);
526 return WIN_XEVENTS_CONVERT;
528 #endif
529 else
531 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
532 "Unknown format. Cannot request conversion, "
533 "aborting.\n");
534 break;
538 /* Retrieve the size of the stored data */
539 iReturn = XGetWindowProperty (pDisplay,
540 iWindow,
541 atomLocalProperty,
543 0, /* Don't get data, just size */
544 False,
545 AnyPropertyType,
546 &xtpText.encoding,
547 &xtpText.format,
548 &xtpText.nitems,
549 &ulReturnBytesLeft,
550 &xtpText.value);
551 if (iReturn != Success)
553 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
554 "XGetWindowProperty () failed, aborting: %d\n",
555 iReturn);
556 break;
559 #if 0
560 ErrorF ("SelectionNotify - returned data %d left %d\n",
561 xtpText.nitems, ulReturnBytesLeft);
562 #endif
564 /* Request the selection data */
565 iReturn = XGetWindowProperty (pDisplay,
566 iWindow,
567 atomLocalProperty,
569 ulReturnBytesLeft,
570 False,
571 AnyPropertyType,
572 &xtpText.encoding,
573 &xtpText.format,
574 &xtpText.nitems,
575 &ulReturnBytesLeft,
576 &xtpText.value);
577 if (iReturn != Success)
579 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
580 "XGetWindowProperty () failed, aborting: %d\n",
581 iReturn);
582 break;
585 #if 0
587 char *pszAtomName = NULL;
589 ErrorF ("SelectionNotify - returned data %d left %d\n",
590 xtpText.nitems, ulReturnBytesLeft);
592 pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
593 ErrorF ("Notify atom name %s\n", pszAtomName);
594 XFree (pszAtomName);
595 pszAtomName = NULL;
597 #endif
599 if (fUseUnicode)
601 #ifdef X_HAVE_UTF8_STRING
602 /* Convert the text property to a text list */
603 iReturn = Xutf8TextPropertyToTextList (pDisplay,
604 &xtpText,
605 &ppszTextList,
606 &iCount);
607 #endif
609 else
611 iReturn = XmbTextPropertyToTextList (pDisplay,
612 &xtpText,
613 &ppszTextList,
614 &iCount);
616 if (iReturn == Success || iReturn > 0)
618 /* Conversion succeeded or some unconvertible characters */
619 if (ppszTextList != NULL)
621 for (i = 0; i < iCount; i++)
623 iReturnDataLen += strlen(ppszTextList[i]);
625 pszReturnData = malloc (iReturnDataLen + 1);
626 pszReturnData[0] = '\0';
627 for (i = 0; i < iCount; i++)
629 strcat (pszReturnData, ppszTextList[i]);
632 else
634 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
635 "X*TextPropertyToTextList list_return is NULL.\n");
636 pszReturnData = malloc (1);
637 pszReturnData[0] = '\0';
640 else
642 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
643 "X*TextPropertyToTextList returned: ");
644 switch (iReturn)
646 case XNoMemory:
647 ErrorF ("XNoMemory\n");
648 break;
649 case XConverterNotFound:
650 ErrorF ("XConverterNotFound\n");
651 break;
652 default:
653 ErrorF ("%d", iReturn);
654 break;
656 pszReturnData = malloc (1);
657 pszReturnData[0] = '\0';
660 /* Free the data returned from XGetWindowProperty */
661 if (ppszTextList)
662 XFreeStringList (ppszTextList);
663 ppszTextList = NULL;
664 XFree (xtpText.value);
665 xtpText.value = NULL;
667 /* Convert the X clipboard string to DOS format */
668 winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));
670 if (fUseUnicode)
672 /* Find out how much space needed to convert MBCS to Unicode */
673 iUnicodeLen = MultiByteToWideChar (CP_UTF8,
675 pszReturnData,
677 NULL,
680 /* Allocate memory for the Unicode string */
681 pwszUnicodeStr
682 = (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
683 if (!pwszUnicodeStr)
685 ErrorF ("winClipboardFlushXEvents - SelectionNotify "
686 "malloc failed for pwszUnicodeStr, aborting.\n");
688 /* Abort */
689 fAbort = TRUE;
690 goto winClipboardFlushXEvents_SelectionNotify_Done;
693 /* Do the actual conversion */
694 MultiByteToWideChar (CP_UTF8,
696 pszReturnData,
698 pwszUnicodeStr,
699 iUnicodeLen);
701 /* Allocate global memory for the X clipboard data */
702 hGlobal = GlobalAlloc (GMEM_MOVEABLE,
703 sizeof (wchar_t) * (iUnicodeLen + 1));
705 else
707 pszConvertData = strdup (pszReturnData);
708 iConvertDataLen = strlen (pszConvertData) + 1;
710 /* Allocate global memory for the X clipboard data */
711 hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
714 /* Check that global memory was allocated */
715 if (!hGlobal)
717 ErrorF ("winClipboardFlushXEvents - SelectionNotify "
718 "GlobalAlloc failed, aborting: %ld\n",
719 GetLastError ());
721 /* Abort */
722 fAbort = TRUE;
723 goto winClipboardFlushXEvents_SelectionNotify_Done;
726 /* Obtain a pointer to the global memory */
727 pszGlobalData = GlobalLock (hGlobal);
728 if (pszGlobalData == NULL)
730 ErrorF ("winClipboardFlushXEvents - Could not lock global "
731 "memory for clipboard transfer\n");
733 /* Abort */
734 fAbort = TRUE;
735 goto winClipboardFlushXEvents_SelectionNotify_Done;
738 /* Copy the returned string into the global memory */
739 if (fUseUnicode)
741 memcpy (pszGlobalData,
742 pwszUnicodeStr,
743 sizeof (wchar_t) * (iUnicodeLen + 1));
744 free (pwszUnicodeStr);
745 pwszUnicodeStr = NULL;
747 else
749 strcpy (pszGlobalData, pszConvertData);
750 free (pszConvertData);
751 pszConvertData = NULL;
754 /* Release the pointer to the global memory */
755 GlobalUnlock (hGlobal);
756 pszGlobalData = NULL;
758 /* Push the selection data to the Windows clipboard */
759 if (fUseUnicode)
760 SetClipboardData (CF_UNICODETEXT, hGlobal);
761 else
762 SetClipboardData (CF_TEXT, hGlobal);
764 /* Flag that SetClipboardData has been called */
765 fSetClipboardData = FALSE;
768 * NOTE: Do not try to free pszGlobalData, it is owned by
769 * Windows after the call to SetClipboardData ().
772 winClipboardFlushXEvents_SelectionNotify_Done:
773 /* Free allocated resources */
774 if (ppszTextList)
775 XFreeStringList (ppszTextList);
776 if (xtpText.value)
777 XFree (xtpText.value);
778 if (pszConvertData)
779 free (pszConvertData);
780 if (pwszUnicodeStr)
781 free (pwszUnicodeStr);
782 if (hGlobal && pszGlobalData)
783 GlobalUnlock (hGlobal);
784 if (fSetClipboardData && g_fUnicodeSupport)
785 SetClipboardData (CF_UNICODETEXT, NULL);
786 if (fSetClipboardData)
787 SetClipboardData (CF_TEXT, NULL);
788 return WIN_XEVENTS_NOTIFY;
790 default:
791 break;
795 return WIN_XEVENTS_SUCCESS;