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>
34 #include "winclipboard.h"
38 * References to external symbols
41 extern Bool g_fUnicodeSupport
;
45 * Process any pending X events
49 winClipboardFlushXEvents (HWND hwnd
,
54 Atom atomLocalProperty
= XInternAtom (pDisplay
,
57 Atom atomUTF8String
= XInternAtom (pDisplay
,
60 Atom atomCompoundText
= XInternAtom (pDisplay
,
63 Atom atomTargets
= XInternAtom (pDisplay
,
67 /* Process all pending events */
68 while (XPending (pDisplay
))
70 XTextProperty xtpText
= {0};
72 XSelectionEvent eventSelection
;
73 unsigned long ulReturnBytesLeft
;
74 unsigned char *pszReturnData
= NULL
;
75 char *pszGlobalData
= NULL
;
77 HGLOBAL hGlobal
= NULL
;
78 XICCEncodingStyle xiccesStyle
;
79 int iConvertDataLen
= 0;
80 char *pszConvertData
= NULL
;
81 char *pszTextList
[2] = {NULL
};
83 char **ppszTextList
= NULL
;
84 wchar_t *pwszUnicodeStr
= NULL
;
86 int iReturnDataLen
= 0;
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 */
102 case SelectionRequest
:
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
);
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
)
126 goto winClipboardFlushXEvents_SelectionRequest_Done
;
129 /* Handle targets type of request */
130 if (event
.xselectionrequest
.target
== atomTargets
)
132 Atom atomTargetArr
[] = {atomTargets
,
137 /* Try to change the property */
138 iReturn
= XChangeProperty (pDisplay
,
139 event
.xselectionrequest
.requestor
,
140 event
.xselectionrequest
.property
,
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",
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
,
176 (XEvent
*) &eventSelection
);
177 if (iReturn
== BadValue
|| iReturn
== BadWindow
)
179 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
180 "XSendEvent () failed\n");
185 /* Check that clipboard format is available */
187 && !IsClipboardFormatAvailable (CF_UNICODETEXT
))
189 ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
190 "available from Win32 clipboard. Aborting.\n");
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");
204 goto winClipboardFlushXEvents_SelectionRequest_Done
;
207 /* Close clipboard if we have it open already */
208 if (GetOpenClipboardWindow () == hwnd
)
213 /* Access the clipboard */
214 if (!OpenClipboard (hwnd
))
216 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
217 "OpenClipboard () failed: %08x\n",
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
;
235 else if (event
.xselectionrequest
.target
== atomCompoundText
)
236 xiccesStyle
= XCompoundTextStyle
;
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 */
247 /* Retrieve clipboard data */
248 hGlobal
= GetClipboardData (CF_UNICODETEXT
);
252 /* Retrieve clipboard data */
253 hGlobal
= GetClipboardData (CF_TEXT
);
257 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
258 "GetClipboardData () failed: %08x\n",
263 goto winClipboardFlushXEvents_SelectionRequest_Done
;
265 pszGlobalData
= (char *) GlobalLock (hGlobal
);
267 /* Convert the Unicode string to UTF8 (MBCS) */
270 iConvertDataLen
= WideCharToMultiByte (CP_UTF8
,
272 (LPCWSTR
)pszGlobalData
,
278 /* NOTE: iConvertDataLen includes space for null terminator */
279 pszConvertData
= (char *) malloc (iConvertDataLen
);
280 WideCharToMultiByte (CP_UTF8
,
282 (LPCWSTR
)pszGlobalData
,
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 */
308 #ifdef X_HAVE_UTF8_STRING
309 iReturn
= Xutf8TextListToTextProperty (pDisplay
,
318 iReturn
= XmbTextListToTextProperty (pDisplay
,
324 if (iReturn
== XNoMemory
|| iReturn
== XLocaleNotSupported
)
326 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
327 "X*TextListToTextProperty failed: %d\n",
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
,
348 if (iReturn
== BadAlloc
|| iReturn
== BadAtom
349 || iReturn
== BadMatch
|| iReturn
== BadValue
350 || iReturn
== BadWindow
)
352 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
353 "XChangeProperty failed: %d\n",
358 goto winClipboardFlushXEvents_SelectionRequest_Done
;
361 /* Release the clipboard data */
362 GlobalUnlock (hGlobal
);
363 pszGlobalData
= NULL
;
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
,
384 (XEvent
*) &eventSelection
);
385 if (iReturn
== BadValue
|| iReturn
== BadWindow
)
387 ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
388 "XSendEvent () failed\n");
392 goto winClipboardFlushXEvents_SelectionRequest_Done
;
395 winClipboardFlushXEvents_SelectionRequest_Done
:
396 /* Free allocated resources */
398 XFree (xtpText
.value
);
400 free (pszConvertData
);
401 if (hGlobal
&& pszGlobalData
)
402 GlobalUnlock (hGlobal
);
405 * Send a SelectionNotify event to the requesting
406 * client when we abort.
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
,
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 */
447 case SelectionNotify
:
449 ErrorF ("winClipboardFlushXEvents - SelectionNotify\n");
453 pszAtomName
= XGetAtomName (pDisplay
,
454 event
.xselection
.selection
);
456 ErrorF ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
465 * Request conversion of UTF8 and CompoundText targets.
467 if (event
.xselection
.property
== None
)
469 if (event
.xselection
.target
== XA_STRING
)
472 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
475 return WIN_XEVENTS_CONVERT
;
477 else if (event
.xselection
.target
== atomUTF8String
)
480 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
481 "Requesting conversion of UTF8 target.\n");
483 iReturn
= XConvertSelection (pDisplay
,
484 event
.xselection
.selection
,
489 if (iReturn
!= Success
)
491 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
492 "XConvertSelection () failed for UTF8String, "
498 /* Process the ConvertSelection event */
500 return WIN_XEVENTS_CONVERT
;
502 #ifdef X_HAVE_UTF8_STRING
503 else if (event
.xselection
.target
== atomCompoundText
)
506 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
507 "Requesting conversion of CompoundText target.\n");
509 iReturn
= XConvertSelection (pDisplay
,
510 event
.xselection
.selection
,
515 if (iReturn
!= Success
)
517 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
518 "XConvertSelection () failed for CompoundText, "
524 /* Process the ConvertSelection event */
526 return WIN_XEVENTS_CONVERT
;
531 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
532 "Unknown format. Cannot request conversion, "
538 /* Retrieve the size of the stored data */
539 iReturn
= XGetWindowProperty (pDisplay
,
543 0, /* Don't get data, just size */
551 if (iReturn
!= Success
)
553 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
554 "XGetWindowProperty () failed, aborting: %d\n",
560 ErrorF ("SelectionNotify - returned data %d left %d\n",
561 xtpText
.nitems
, ulReturnBytesLeft
);
564 /* Request the selection data */
565 iReturn
= XGetWindowProperty (pDisplay
,
577 if (iReturn
!= Success
)
579 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
580 "XGetWindowProperty () failed, aborting: %d\n",
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
);
601 #ifdef X_HAVE_UTF8_STRING
602 /* Convert the text property to a text list */
603 iReturn
= Xutf8TextPropertyToTextList (pDisplay
,
611 iReturn
= XmbTextPropertyToTextList (pDisplay
,
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
]);
634 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
635 "X*TextPropertyToTextList list_return is NULL.\n");
636 pszReturnData
= malloc (1);
637 pszReturnData
[0] = '\0';
642 ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
643 "X*TextPropertyToTextList returned: ");
647 ErrorF ("XNoMemory\n");
649 case XConverterNotFound
:
650 ErrorF ("XConverterNotFound\n");
653 ErrorF ("%d", iReturn
);
656 pszReturnData
= malloc (1);
657 pszReturnData
[0] = '\0';
660 /* Free the data returned from XGetWindowProperty */
662 XFreeStringList (ppszTextList
);
664 XFree (xtpText
.value
);
665 xtpText
.value
= NULL
;
667 /* Convert the X clipboard string to DOS format */
668 winClipboardUNIXtoDOS (&pszReturnData
, strlen (pszReturnData
));
672 /* Find out how much space needed to convert MBCS to Unicode */
673 iUnicodeLen
= MultiByteToWideChar (CP_UTF8
,
680 /* Allocate memory for the Unicode string */
682 = (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen
+ 1));
685 ErrorF ("winClipboardFlushXEvents - SelectionNotify "
686 "malloc failed for pwszUnicodeStr, aborting.\n");
690 goto winClipboardFlushXEvents_SelectionNotify_Done
;
693 /* Do the actual conversion */
694 MultiByteToWideChar (CP_UTF8
,
701 /* Allocate global memory for the X clipboard data */
702 hGlobal
= GlobalAlloc (GMEM_MOVEABLE
,
703 sizeof (wchar_t) * (iUnicodeLen
+ 1));
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 */
717 ErrorF ("winClipboardFlushXEvents - SelectionNotify "
718 "GlobalAlloc failed, aborting: %ld\n",
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");
735 goto winClipboardFlushXEvents_SelectionNotify_Done
;
738 /* Copy the returned string into the global memory */
741 memcpy (pszGlobalData
,
743 sizeof (wchar_t) * (iUnicodeLen
+ 1));
744 free (pwszUnicodeStr
);
745 pwszUnicodeStr
= NULL
;
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 */
760 SetClipboardData (CF_UNICODETEXT
, hGlobal
);
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 */
775 XFreeStringList (ppszTextList
);
777 XFree (xtpText
.value
);
779 free (pszConvertData
);
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
;
795 return WIN_XEVENTS_SUCCESS
;