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