Commit | Line | Data |
---|---|---|
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 | ||
43 | int | |
44 | winClipboardFlushXEvents(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 | } |