1706f2543Smrg/* 2706f2543Smrg *Copyright (C) 2003-2004 Harold L Hunt II All Rights Reserved. 3706f2543Smrg *Copyright (C) Colin Harrison 2005-2008 4706f2543Smrg * 5706f2543Smrg *Permission is hereby granted, free of charge, to any person obtaining 6706f2543Smrg * a copy of this software and associated documentation files (the 7706f2543Smrg *"Software"), to deal in the Software without restriction, including 8706f2543Smrg *without limitation the rights to use, copy, modify, merge, publish, 9706f2543Smrg *distribute, sublicense, and/or sell copies of the Software, and to 10706f2543Smrg *permit persons to whom the Software is furnished to do so, subject to 11706f2543Smrg *the following conditions: 12706f2543Smrg * 13706f2543Smrg *The above copyright notice and this permission notice shall be 14706f2543Smrg *included in all copies or substantial portions of the Software. 15706f2543Smrg * 16706f2543Smrg *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17706f2543Smrg *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18706f2543Smrg *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19706f2543Smrg *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR 20706f2543Smrg *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 21706f2543Smrg *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22706f2543Smrg *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23706f2543Smrg * 24706f2543Smrg *Except as contained in this notice, the name of the copyright holder(s) 25706f2543Smrg *and author(s) shall not be used in advertising or otherwise to promote 26706f2543Smrg *the sale, use or other dealings in this Software without prior written 27706f2543Smrg *authorization from the copyright holder(s) and author(s). 28706f2543Smrg * 29706f2543Smrg * Authors: Harold L Hunt II 30706f2543Smrg * Colin Harrison 31706f2543Smrg */ 32706f2543Smrg 33706f2543Smrg#ifdef HAVE_XWIN_CONFIG_H 34706f2543Smrg#include <xwin-config.h> 35706f2543Smrg#endif 36706f2543Smrg#include "winclipboard.h" 37706f2543Smrg#include "misc.h" 38706f2543Smrg 39706f2543Smrg 40706f2543Smrg/* 41706f2543Smrg * References to external symbols 42706f2543Smrg */ 43706f2543Smrg 44706f2543Smrgextern Bool g_fUnicodeSupport; 45706f2543Smrg 46706f2543Smrg 47706f2543Smrg/* 48706f2543Smrg * Process any pending X events 49706f2543Smrg */ 50706f2543Smrg 51706f2543Smrgint 52706f2543SmrgwinClipboardFlushXEvents (HWND hwnd, 53706f2543Smrg int iWindow, 54706f2543Smrg Display *pDisplay, 55706f2543Smrg Bool fUseUnicode) 56706f2543Smrg{ 57706f2543Smrg static Atom atomLocalProperty; 58706f2543Smrg static Atom atomCompoundText; 59706f2543Smrg static Atom atomUTF8String; 60706f2543Smrg static Atom atomTargets; 61706f2543Smrg static int generation; 62706f2543Smrg 63706f2543Smrg if (generation != serverGeneration) 64706f2543Smrg { 65706f2543Smrg generation = serverGeneration; 66706f2543Smrg atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False); 67706f2543Smrg atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False); 68706f2543Smrg atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False); 69706f2543Smrg atomTargets = XInternAtom (pDisplay, "TARGETS", False); 70706f2543Smrg } 71706f2543Smrg 72706f2543Smrg /* Process all pending events */ 73706f2543Smrg while (XPending (pDisplay)) 74706f2543Smrg { 75706f2543Smrg XTextProperty xtpText = {0}; 76706f2543Smrg XEvent event; 77706f2543Smrg XSelectionEvent eventSelection; 78706f2543Smrg unsigned long ulReturnBytesLeft; 79706f2543Smrg char *pszReturnData = NULL; 80706f2543Smrg char *pszGlobalData = NULL; 81706f2543Smrg int iReturn; 82706f2543Smrg HGLOBAL hGlobal = NULL; 83706f2543Smrg XICCEncodingStyle xiccesStyle; 84706f2543Smrg int iConvertDataLen = 0; 85706f2543Smrg char *pszConvertData = NULL; 86706f2543Smrg char *pszTextList[2] = {NULL}; 87706f2543Smrg int iCount; 88706f2543Smrg char **ppszTextList = NULL; 89706f2543Smrg wchar_t *pwszUnicodeStr = NULL; 90706f2543Smrg int iUnicodeLen = 0; 91706f2543Smrg int iReturnDataLen = 0; 92706f2543Smrg int i; 93706f2543Smrg Bool fAbort = FALSE; 94706f2543Smrg Bool fCloseClipboard = FALSE; 95706f2543Smrg Bool fSetClipboardData = TRUE; 96706f2543Smrg 97706f2543Smrg /* Get the next event - will not block because one is ready */ 98706f2543Smrg XNextEvent (pDisplay, &event); 99706f2543Smrg 100706f2543Smrg /* Branch on the event type */ 101706f2543Smrg switch (event.type) 102706f2543Smrg { 103706f2543Smrg /* 104706f2543Smrg * SelectionRequest 105706f2543Smrg */ 106706f2543Smrg 107706f2543Smrg case SelectionRequest: 108706f2543Smrg { 109706f2543Smrg char *pszAtomName = NULL; 110706f2543Smrg winDebug("SelectionRequest - target %d\n", 111706f2543Smrg event.xselectionrequest.target); 112706f2543Smrg 113706f2543Smrg pszAtomName = XGetAtomName (pDisplay, 114706f2543Smrg event.xselectionrequest.target); 115706f2543Smrg winDebug("SelectionRequest - Target atom name %s\n", pszAtomName); 116706f2543Smrg XFree (pszAtomName); 117706f2543Smrg pszAtomName = NULL; 118706f2543Smrg } 119706f2543Smrg 120706f2543Smrg /* Abort if invalid target type */ 121706f2543Smrg if (event.xselectionrequest.target != XA_STRING 122706f2543Smrg && event.xselectionrequest.target != atomUTF8String 123706f2543Smrg && event.xselectionrequest.target != atomCompoundText 124706f2543Smrg && event.xselectionrequest.target != atomTargets) 125706f2543Smrg { 126706f2543Smrg /* Abort */ 127706f2543Smrg fAbort = TRUE; 128706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 129706f2543Smrg } 130706f2543Smrg 131706f2543Smrg /* Handle targets type of request */ 132706f2543Smrg if (event.xselectionrequest.target == atomTargets) 133706f2543Smrg { 134706f2543Smrg Atom atomTargetArr[] = {atomTargets, 135706f2543Smrg atomCompoundText, 136706f2543Smrg atomUTF8String, 137706f2543Smrg XA_STRING}; 138706f2543Smrg 139706f2543Smrg /* Try to change the property */ 140706f2543Smrg iReturn = XChangeProperty (pDisplay, 141706f2543Smrg event.xselectionrequest.requestor, 142706f2543Smrg event.xselectionrequest.property, 143706f2543Smrg XA_ATOM, 144706f2543Smrg 32, 145706f2543Smrg PropModeReplace, 146706f2543Smrg (unsigned char *) atomTargetArr, 147706f2543Smrg (sizeof (atomTargetArr) 148706f2543Smrg / sizeof (atomTargetArr[0]))); 149706f2543Smrg if (iReturn == BadAlloc 150706f2543Smrg || iReturn == BadAtom 151706f2543Smrg || iReturn == BadMatch 152706f2543Smrg || iReturn == BadValue 153706f2543Smrg || iReturn == BadWindow) 154706f2543Smrg { 155706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 156706f2543Smrg "XChangeProperty failed: %d\n", 157706f2543Smrg iReturn); 158706f2543Smrg } 159706f2543Smrg 160706f2543Smrg /* Setup selection notify xevent */ 161706f2543Smrg eventSelection.type = SelectionNotify; 162706f2543Smrg eventSelection.send_event = True; 163706f2543Smrg eventSelection.display = pDisplay; 164706f2543Smrg eventSelection.requestor = event.xselectionrequest.requestor; 165706f2543Smrg eventSelection.selection = event.xselectionrequest.selection; 166706f2543Smrg eventSelection.target = event.xselectionrequest.target; 167706f2543Smrg eventSelection.property = event.xselectionrequest.property; 168706f2543Smrg eventSelection.time = event.xselectionrequest.time; 169706f2543Smrg 170706f2543Smrg /* 171706f2543Smrg * Notify the requesting window that 172706f2543Smrg * the operation has completed 173706f2543Smrg */ 174706f2543Smrg iReturn = XSendEvent (pDisplay, 175706f2543Smrg eventSelection.requestor, 176706f2543Smrg False, 177706f2543Smrg 0L, 178706f2543Smrg (XEvent *) &eventSelection); 179706f2543Smrg if (iReturn == BadValue || iReturn == BadWindow) 180706f2543Smrg { 181706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 182706f2543Smrg "XSendEvent () failed\n"); 183706f2543Smrg } 184706f2543Smrg break; 185706f2543Smrg } 186706f2543Smrg 187706f2543Smrg /* Check that clipboard format is available */ 188706f2543Smrg if (fUseUnicode 189706f2543Smrg && !IsClipboardFormatAvailable (CF_UNICODETEXT)) 190706f2543Smrg { 191706f2543Smrg static int count; /* Hack to stop acroread spamming the log */ 192706f2543Smrg static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */ 193706f2543Smrg if (hwnd != lasthwnd) count = 0; 194706f2543Smrg count++; 195706f2543Smrg if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not " 196706f2543Smrg "available from Win32 clipboard. Aborting %d.\n", count); 197706f2543Smrg lasthwnd = hwnd; 198706f2543Smrg 199706f2543Smrg /* Abort */ 200706f2543Smrg fAbort = TRUE; 201706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 202706f2543Smrg } 203706f2543Smrg else if (!fUseUnicode 204706f2543Smrg && !IsClipboardFormatAvailable (CF_TEXT)) 205706f2543Smrg { 206706f2543Smrg ErrorF ("winClipboardFlushXEvents - CF_TEXT is not " 207706f2543Smrg "available from Win32 clipboard. Aborting.\n"); 208706f2543Smrg 209706f2543Smrg /* Abort */ 210706f2543Smrg fAbort = TRUE; 211706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 212706f2543Smrg } 213706f2543Smrg 214706f2543Smrg /* Close clipboard if we have it open already */ 215706f2543Smrg if (GetOpenClipboardWindow () == hwnd) 216706f2543Smrg { 217706f2543Smrg CloseClipboard (); 218706f2543Smrg } 219706f2543Smrg 220706f2543Smrg /* Access the clipboard */ 221706f2543Smrg if (!OpenClipboard (hwnd)) 222706f2543Smrg { 223706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 224706f2543Smrg "OpenClipboard () failed: %08lx\n", 225706f2543Smrg GetLastError ()); 226706f2543Smrg 227706f2543Smrg /* Abort */ 228706f2543Smrg fAbort = TRUE; 229706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 230706f2543Smrg } 231706f2543Smrg 232706f2543Smrg /* Indicate that clipboard was opened */ 233706f2543Smrg fCloseClipboard = TRUE; 234706f2543Smrg 235706f2543Smrg /* Setup the string style */ 236706f2543Smrg if (event.xselectionrequest.target == XA_STRING) 237706f2543Smrg xiccesStyle = XStringStyle; 238706f2543Smrg#ifdef X_HAVE_UTF8_STRING 239706f2543Smrg else if (event.xselectionrequest.target == atomUTF8String) 240706f2543Smrg xiccesStyle = XUTF8StringStyle; 241706f2543Smrg#endif 242706f2543Smrg else if (event.xselectionrequest.target == atomCompoundText) 243706f2543Smrg xiccesStyle = XCompoundTextStyle; 244706f2543Smrg else 245706f2543Smrg xiccesStyle = XStringStyle; 246706f2543Smrg 247706f2543Smrg /* 248706f2543Smrg * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me 249706f2543Smrg */ 250706f2543Smrg 251706f2543Smrg /* Get a pointer to the clipboard text, in desired format */ 252706f2543Smrg if (fUseUnicode) 253706f2543Smrg { 254706f2543Smrg /* Retrieve clipboard data */ 255706f2543Smrg hGlobal = GetClipboardData (CF_UNICODETEXT); 256706f2543Smrg } 257706f2543Smrg else 258706f2543Smrg { 259706f2543Smrg /* Retrieve clipboard data */ 260706f2543Smrg hGlobal = GetClipboardData (CF_TEXT); 261706f2543Smrg } 262706f2543Smrg if (!hGlobal) 263706f2543Smrg { 264706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 265706f2543Smrg "GetClipboardData () failed: %08lx\n", 266706f2543Smrg GetLastError ()); 267706f2543Smrg 268706f2543Smrg /* Abort */ 269706f2543Smrg fAbort = TRUE; 270706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 271706f2543Smrg } 272706f2543Smrg pszGlobalData = (char *) GlobalLock (hGlobal); 273706f2543Smrg 274706f2543Smrg /* Convert the Unicode string to UTF8 (MBCS) */ 275706f2543Smrg if (fUseUnicode) 276706f2543Smrg { 277706f2543Smrg iConvertDataLen = WideCharToMultiByte (CP_UTF8, 278706f2543Smrg 0, 279706f2543Smrg (LPCWSTR)pszGlobalData, 280706f2543Smrg -1, 281706f2543Smrg NULL, 282706f2543Smrg 0, 283706f2543Smrg NULL, 284706f2543Smrg NULL); 285706f2543Smrg /* NOTE: iConvertDataLen includes space for null terminator */ 286706f2543Smrg pszConvertData = (char *) malloc (iConvertDataLen); 287706f2543Smrg WideCharToMultiByte (CP_UTF8, 288706f2543Smrg 0, 289706f2543Smrg (LPCWSTR)pszGlobalData, 290706f2543Smrg -1, 291706f2543Smrg pszConvertData, 292706f2543Smrg iConvertDataLen, 293706f2543Smrg NULL, 294706f2543Smrg NULL); 295706f2543Smrg } 296706f2543Smrg else 297706f2543Smrg { 298706f2543Smrg pszConvertData = strdup (pszGlobalData); 299706f2543Smrg iConvertDataLen = strlen (pszConvertData) + 1; 300706f2543Smrg } 301706f2543Smrg 302706f2543Smrg /* Convert DOS string to UNIX string */ 303706f2543Smrg winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData)); 304706f2543Smrg 305706f2543Smrg /* Setup our text list */ 306706f2543Smrg pszTextList[0] = pszConvertData; 307706f2543Smrg pszTextList[1] = NULL; 308706f2543Smrg 309706f2543Smrg /* Initialize the text property */ 310706f2543Smrg xtpText.value = NULL; 311706f2543Smrg xtpText.nitems = 0; 312706f2543Smrg 313706f2543Smrg /* Create the text property from the text list */ 314706f2543Smrg if (fUseUnicode) 315706f2543Smrg { 316706f2543Smrg#ifdef X_HAVE_UTF8_STRING 317706f2543Smrg iReturn = Xutf8TextListToTextProperty (pDisplay, 318706f2543Smrg pszTextList, 319706f2543Smrg 1, 320706f2543Smrg xiccesStyle, 321706f2543Smrg &xtpText); 322706f2543Smrg#endif 323706f2543Smrg } 324706f2543Smrg else 325706f2543Smrg { 326706f2543Smrg iReturn = XmbTextListToTextProperty (pDisplay, 327706f2543Smrg pszTextList, 328706f2543Smrg 1, 329706f2543Smrg xiccesStyle, 330706f2543Smrg &xtpText); 331706f2543Smrg } 332706f2543Smrg if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) 333706f2543Smrg { 334706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 335706f2543Smrg "X*TextListToTextProperty failed: %d\n", 336706f2543Smrg iReturn); 337706f2543Smrg 338706f2543Smrg /* Abort */ 339706f2543Smrg fAbort = TRUE; 340706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 341706f2543Smrg } 342706f2543Smrg 343706f2543Smrg /* Free the converted string */ 344706f2543Smrg free (pszConvertData); 345706f2543Smrg pszConvertData = NULL; 346706f2543Smrg 347706f2543Smrg /* Copy the clipboard text to the requesting window */ 348706f2543Smrg iReturn = XChangeProperty (pDisplay, 349706f2543Smrg event.xselectionrequest.requestor, 350706f2543Smrg event.xselectionrequest.property, 351706f2543Smrg event.xselectionrequest.target, 352706f2543Smrg 8, 353706f2543Smrg PropModeReplace, 354706f2543Smrg xtpText.value, 355706f2543Smrg xtpText.nitems); 356706f2543Smrg if (iReturn == BadAlloc || iReturn == BadAtom 357706f2543Smrg || iReturn == BadMatch || iReturn == BadValue 358706f2543Smrg || iReturn == BadWindow) 359706f2543Smrg { 360706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 361706f2543Smrg "XChangeProperty failed: %d\n", 362706f2543Smrg iReturn); 363706f2543Smrg 364706f2543Smrg /* Abort */ 365706f2543Smrg fAbort = TRUE; 366706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 367706f2543Smrg } 368706f2543Smrg 369706f2543Smrg /* Release the clipboard data */ 370706f2543Smrg GlobalUnlock (hGlobal); 371706f2543Smrg pszGlobalData = NULL; 372706f2543Smrg fCloseClipboard = FALSE; 373706f2543Smrg CloseClipboard (); 374706f2543Smrg 375706f2543Smrg /* Clean up */ 376706f2543Smrg XFree (xtpText.value); 377706f2543Smrg xtpText.value = NULL; 378706f2543Smrg xtpText.nitems = 0; 379706f2543Smrg 380706f2543Smrg /* Setup selection notify event */ 381706f2543Smrg eventSelection.type = SelectionNotify; 382706f2543Smrg eventSelection.send_event = True; 383706f2543Smrg eventSelection.display = pDisplay; 384706f2543Smrg eventSelection.requestor = event.xselectionrequest.requestor; 385706f2543Smrg eventSelection.selection = event.xselectionrequest.selection; 386706f2543Smrg eventSelection.target = event.xselectionrequest.target; 387706f2543Smrg eventSelection.property = event.xselectionrequest.property; 388706f2543Smrg eventSelection.time = event.xselectionrequest.time; 389706f2543Smrg 390706f2543Smrg /* Notify the requesting window that the operation has completed */ 391706f2543Smrg iReturn = XSendEvent (pDisplay, 392706f2543Smrg eventSelection.requestor, 393706f2543Smrg False, 394706f2543Smrg 0L, 395706f2543Smrg (XEvent *) &eventSelection); 396706f2543Smrg if (iReturn == BadValue || iReturn == BadWindow) 397706f2543Smrg { 398706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 399706f2543Smrg "XSendEvent () failed\n"); 400706f2543Smrg 401706f2543Smrg /* Abort */ 402706f2543Smrg fAbort = TRUE; 403706f2543Smrg goto winClipboardFlushXEvents_SelectionRequest_Done; 404706f2543Smrg } 405706f2543Smrg 406706f2543Smrg winClipboardFlushXEvents_SelectionRequest_Done: 407706f2543Smrg /* Free allocated resources */ 408706f2543Smrg if (xtpText.value) 409706f2543Smrg { 410706f2543Smrg XFree (xtpText.value); 411706f2543Smrg xtpText.value = NULL; 412706f2543Smrg xtpText.nitems = 0; 413706f2543Smrg } 414706f2543Smrg free(pszConvertData); 415706f2543Smrg if (hGlobal && pszGlobalData) 416706f2543Smrg GlobalUnlock (hGlobal); 417706f2543Smrg 418706f2543Smrg /* 419706f2543Smrg * Send a SelectionNotify event to the requesting 420706f2543Smrg * client when we abort. 421706f2543Smrg */ 422706f2543Smrg if (fAbort) 423706f2543Smrg { 424706f2543Smrg /* Setup selection notify event */ 425706f2543Smrg eventSelection.type = SelectionNotify; 426706f2543Smrg eventSelection.send_event = True; 427706f2543Smrg eventSelection.display = pDisplay; 428706f2543Smrg eventSelection.requestor = event.xselectionrequest.requestor; 429706f2543Smrg eventSelection.selection = event.xselectionrequest.selection; 430706f2543Smrg eventSelection.target = event.xselectionrequest.target; 431706f2543Smrg eventSelection.property = None; 432706f2543Smrg eventSelection.time = event.xselectionrequest.time; 433706f2543Smrg 434706f2543Smrg /* Notify the requesting window that the operation is complete */ 435706f2543Smrg iReturn = XSendEvent (pDisplay, 436706f2543Smrg eventSelection.requestor, 437706f2543Smrg False, 438706f2543Smrg 0L, 439706f2543Smrg (XEvent *) &eventSelection); 440706f2543Smrg if (iReturn == BadValue || iReturn == BadWindow) 441706f2543Smrg { 442706f2543Smrg /* 443706f2543Smrg * Should not be a problem if XSendEvent fails because 444706f2543Smrg * the client may simply have exited. 445706f2543Smrg */ 446706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionRequest - " 447706f2543Smrg "XSendEvent () failed for abort event.\n"); 448706f2543Smrg } 449706f2543Smrg } 450706f2543Smrg 451706f2543Smrg /* Close clipboard if it was opened */ 452706f2543Smrg if (fCloseClipboard) 453706f2543Smrg { 454706f2543Smrg fCloseClipboard = FALSE; 455706f2543Smrg CloseClipboard (); 456706f2543Smrg } 457706f2543Smrg break; 458706f2543Smrg 459706f2543Smrg 460706f2543Smrg /* 461706f2543Smrg * SelectionNotify 462706f2543Smrg */ 463706f2543Smrg 464706f2543Smrg case SelectionNotify: 465706f2543Smrg 466706f2543Smrg winDebug ("winClipboardFlushXEvents - SelectionNotify\n"); 467706f2543Smrg { 468706f2543Smrg char *pszAtomName; 469706f2543Smrg pszAtomName = XGetAtomName (pDisplay, 470706f2543Smrg event.xselection.selection); 471706f2543Smrg 472706f2543Smrg winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n", 473706f2543Smrg pszAtomName); 474706f2543Smrg XFree (pszAtomName); 475706f2543Smrg } 476706f2543Smrg 477706f2543Smrg /* 478706f2543Smrg * Request conversion of UTF8 and CompoundText targets. 479706f2543Smrg */ 480706f2543Smrg if (event.xselection.property == None) 481706f2543Smrg { 482706f2543Smrg if (event.xselection.target == XA_STRING) 483706f2543Smrg { 484706f2543Smrg winDebug ("winClipboardFlushXEvents - SelectionNotify - " 485706f2543Smrg "XA_STRING\n"); 486706f2543Smrg 487706f2543Smrg return WIN_XEVENTS_CONVERT; 488706f2543Smrg } 489706f2543Smrg else if (event.xselection.target == atomUTF8String) 490706f2543Smrg { 491706f2543Smrg winDebug("winClipboardFlushXEvents - SelectionNotify - " 492706f2543Smrg "Requesting conversion of UTF8 target.\n"); 493706f2543Smrg 494706f2543Smrg XConvertSelection (pDisplay, 495706f2543Smrg event.xselection.selection, 496706f2543Smrg XA_STRING, 497706f2543Smrg atomLocalProperty, 498706f2543Smrg iWindow, 499706f2543Smrg CurrentTime); 500706f2543Smrg 501706f2543Smrg /* Process the ConvertSelection event */ 502706f2543Smrg XFlush (pDisplay); 503706f2543Smrg return WIN_XEVENTS_CONVERT; 504706f2543Smrg } 505706f2543Smrg#ifdef X_HAVE_UTF8_STRING 506706f2543Smrg else if (event.xselection.target == atomCompoundText) 507706f2543Smrg { 508706f2543Smrg winDebug("winClipboardFlushXEvents - SelectionNotify - " 509706f2543Smrg "Requesting conversion of CompoundText target.\n"); 510706f2543Smrg 511706f2543Smrg XConvertSelection (pDisplay, 512706f2543Smrg event.xselection.selection, 513706f2543Smrg atomUTF8String, 514706f2543Smrg atomLocalProperty, 515706f2543Smrg iWindow, 516706f2543Smrg CurrentTime); 517706f2543Smrg 518706f2543Smrg /* Process the ConvertSelection event */ 519706f2543Smrg XFlush (pDisplay); 520706f2543Smrg return WIN_XEVENTS_CONVERT; 521706f2543Smrg } 522706f2543Smrg#endif 523706f2543Smrg else 524706f2543Smrg { 525706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify - " 526706f2543Smrg "Unknown format. Cannot request conversion, " 527706f2543Smrg "aborting.\n"); 528706f2543Smrg break; 529706f2543Smrg } 530706f2543Smrg } 531706f2543Smrg 532706f2543Smrg /* Retrieve the size of the stored data */ 533706f2543Smrg iReturn = XGetWindowProperty (pDisplay, 534706f2543Smrg iWindow, 535706f2543Smrg atomLocalProperty, 536706f2543Smrg 0, 537706f2543Smrg 0, /* Don't get data, just size */ 538706f2543Smrg False, 539706f2543Smrg AnyPropertyType, 540706f2543Smrg &xtpText.encoding, 541706f2543Smrg &xtpText.format, 542706f2543Smrg &xtpText.nitems, 543706f2543Smrg &ulReturnBytesLeft, 544706f2543Smrg &xtpText.value); 545706f2543Smrg if (iReturn != Success) 546706f2543Smrg { 547706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify - " 548706f2543Smrg "XGetWindowProperty () failed, aborting: %d\n", 549706f2543Smrg iReturn); 550706f2543Smrg break; 551706f2543Smrg } 552706f2543Smrg 553706f2543Smrg winDebug("SelectionNotify - returned data %d left %d\n", 554706f2543Smrg xtpText.nitems, ulReturnBytesLeft); 555706f2543Smrg 556706f2543Smrg /* Request the selection data */ 557706f2543Smrg iReturn = XGetWindowProperty (pDisplay, 558706f2543Smrg iWindow, 559706f2543Smrg atomLocalProperty, 560706f2543Smrg 0, 561706f2543Smrg ulReturnBytesLeft, 562706f2543Smrg False, 563706f2543Smrg AnyPropertyType, 564706f2543Smrg &xtpText.encoding, 565706f2543Smrg &xtpText.format, 566706f2543Smrg &xtpText.nitems, 567706f2543Smrg &ulReturnBytesLeft, 568706f2543Smrg &xtpText.value); 569706f2543Smrg if (iReturn != Success) 570706f2543Smrg { 571706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify - " 572706f2543Smrg "XGetWindowProperty () failed, aborting: %d\n", 573706f2543Smrg iReturn); 574706f2543Smrg break; 575706f2543Smrg } 576706f2543Smrg 577706f2543Smrg { 578706f2543Smrg char *pszAtomName = NULL; 579706f2543Smrg 580706f2543Smrg winDebug("SelectionNotify - returned data %d left %d\n", 581706f2543Smrg xtpText.nitems, ulReturnBytesLeft); 582706f2543Smrg pszAtomName = XGetAtomName(pDisplay, xtpText.encoding); 583706f2543Smrg winDebug("Notify atom name %s\n", pszAtomName); 584706f2543Smrg XFree (pszAtomName); 585706f2543Smrg pszAtomName = NULL; 586706f2543Smrg } 587706f2543Smrg 588706f2543Smrg if (fUseUnicode) 589706f2543Smrg { 590706f2543Smrg#ifdef X_HAVE_UTF8_STRING 591706f2543Smrg /* Convert the text property to a text list */ 592706f2543Smrg iReturn = Xutf8TextPropertyToTextList (pDisplay, 593706f2543Smrg &xtpText, 594706f2543Smrg &ppszTextList, 595706f2543Smrg &iCount); 596706f2543Smrg#endif 597706f2543Smrg } 598706f2543Smrg else 599706f2543Smrg { 600706f2543Smrg iReturn = XmbTextPropertyToTextList (pDisplay, 601706f2543Smrg &xtpText, 602706f2543Smrg &ppszTextList, 603706f2543Smrg &iCount); 604706f2543Smrg } 605706f2543Smrg if (iReturn == Success || iReturn > 0) 606706f2543Smrg { 607706f2543Smrg /* Conversion succeeded or some unconvertible characters */ 608706f2543Smrg if (ppszTextList != NULL) 609706f2543Smrg { 610706f2543Smrg iReturnDataLen = 0; 611706f2543Smrg for (i = 0; i < iCount; i++) 612706f2543Smrg { 613706f2543Smrg iReturnDataLen += strlen(ppszTextList[i]); 614706f2543Smrg } 615706f2543Smrg pszReturnData = malloc (iReturnDataLen + 1); 616706f2543Smrg pszReturnData[0] = '\0'; 617706f2543Smrg for (i = 0; i < iCount; i++) 618706f2543Smrg { 619706f2543Smrg strcat (pszReturnData, ppszTextList[i]); 620706f2543Smrg } 621706f2543Smrg } 622706f2543Smrg else 623706f2543Smrg { 624706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify - " 625706f2543Smrg "X*TextPropertyToTextList list_return is NULL.\n"); 626706f2543Smrg pszReturnData = malloc (1); 627706f2543Smrg pszReturnData[0] = '\0'; 628706f2543Smrg } 629706f2543Smrg } 630706f2543Smrg else 631706f2543Smrg { 632706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify - " 633706f2543Smrg "X*TextPropertyToTextList returned: "); 634706f2543Smrg switch (iReturn) 635706f2543Smrg { 636706f2543Smrg case XNoMemory: 637706f2543Smrg ErrorF ("XNoMemory\n"); 638706f2543Smrg break; 639706f2543Smrg case XConverterNotFound: 640706f2543Smrg ErrorF ("XConverterNotFound\n"); 641706f2543Smrg break; 642706f2543Smrg default: 643706f2543Smrg ErrorF ("%d", iReturn); 644706f2543Smrg break; 645706f2543Smrg } 646706f2543Smrg pszReturnData = malloc (1); 647706f2543Smrg pszReturnData[0] = '\0'; 648706f2543Smrg } 649706f2543Smrg 650706f2543Smrg /* Free the data returned from XGetWindowProperty */ 651706f2543Smrg if (ppszTextList) 652706f2543Smrg XFreeStringList (ppszTextList); 653706f2543Smrg ppszTextList = NULL; 654706f2543Smrg XFree (xtpText.value); 655706f2543Smrg xtpText.value = NULL; 656706f2543Smrg xtpText.nitems = 0; 657706f2543Smrg 658706f2543Smrg /* Convert the X clipboard string to DOS format */ 659706f2543Smrg winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData)); 660706f2543Smrg 661706f2543Smrg if (fUseUnicode) 662706f2543Smrg { 663706f2543Smrg /* Find out how much space needed to convert MBCS to Unicode */ 664706f2543Smrg iUnicodeLen = MultiByteToWideChar (CP_UTF8, 665706f2543Smrg 0, 666706f2543Smrg pszReturnData, 667706f2543Smrg -1, 668706f2543Smrg NULL, 669706f2543Smrg 0); 670706f2543Smrg 671706f2543Smrg /* Allocate memory for the Unicode string */ 672706f2543Smrg pwszUnicodeStr 673706f2543Smrg = (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1)); 674706f2543Smrg if (!pwszUnicodeStr) 675706f2543Smrg { 676706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify " 677706f2543Smrg "malloc failed for pwszUnicodeStr, aborting.\n"); 678706f2543Smrg 679706f2543Smrg /* Abort */ 680706f2543Smrg fAbort = TRUE; 681706f2543Smrg goto winClipboardFlushXEvents_SelectionNotify_Done; 682706f2543Smrg } 683706f2543Smrg 684706f2543Smrg /* Do the actual conversion */ 685706f2543Smrg MultiByteToWideChar (CP_UTF8, 686706f2543Smrg 0, 687706f2543Smrg pszReturnData, 688706f2543Smrg -1, 689706f2543Smrg pwszUnicodeStr, 690706f2543Smrg iUnicodeLen); 691706f2543Smrg 692706f2543Smrg /* Allocate global memory for the X clipboard data */ 693706f2543Smrg hGlobal = GlobalAlloc (GMEM_MOVEABLE, 694706f2543Smrg sizeof (wchar_t) * (iUnicodeLen + 1)); 695706f2543Smrg } 696706f2543Smrg else 697706f2543Smrg { 698706f2543Smrg pszConvertData = strdup (pszReturnData); 699706f2543Smrg iConvertDataLen = strlen (pszConvertData) + 1; 700706f2543Smrg 701706f2543Smrg /* Allocate global memory for the X clipboard data */ 702706f2543Smrg hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen); 703706f2543Smrg } 704706f2543Smrg 705706f2543Smrg free (pszReturnData); 706706f2543Smrg 707706f2543Smrg /* Check that global memory was allocated */ 708706f2543Smrg if (!hGlobal) 709706f2543Smrg { 710706f2543Smrg ErrorF ("winClipboardFlushXEvents - SelectionNotify " 711706f2543Smrg "GlobalAlloc failed, aborting: %ld\n", 712706f2543Smrg GetLastError ()); 713706f2543Smrg 714706f2543Smrg /* Abort */ 715706f2543Smrg fAbort = TRUE; 716706f2543Smrg goto winClipboardFlushXEvents_SelectionNotify_Done; 717706f2543Smrg } 718706f2543Smrg 719706f2543Smrg /* Obtain a pointer to the global memory */ 720706f2543Smrg pszGlobalData = GlobalLock (hGlobal); 721706f2543Smrg if (pszGlobalData == NULL) 722706f2543Smrg { 723706f2543Smrg ErrorF ("winClipboardFlushXEvents - Could not lock global " 724706f2543Smrg "memory for clipboard transfer\n"); 725706f2543Smrg 726706f2543Smrg /* Abort */ 727706f2543Smrg fAbort = TRUE; 728706f2543Smrg goto winClipboardFlushXEvents_SelectionNotify_Done; 729706f2543Smrg } 730706f2543Smrg 731706f2543Smrg /* Copy the returned string into the global memory */ 732706f2543Smrg if (fUseUnicode) 733706f2543Smrg { 734706f2543Smrg memcpy (pszGlobalData, 735706f2543Smrg pwszUnicodeStr, 736706f2543Smrg sizeof (wchar_t) * (iUnicodeLen + 1)); 737706f2543Smrg free (pwszUnicodeStr); 738706f2543Smrg pwszUnicodeStr = NULL; 739706f2543Smrg } 740706f2543Smrg else 741706f2543Smrg { 742706f2543Smrg strcpy (pszGlobalData, pszConvertData); 743706f2543Smrg free (pszConvertData); 744706f2543Smrg pszConvertData = NULL; 745706f2543Smrg } 746706f2543Smrg 747706f2543Smrg /* Release the pointer to the global memory */ 748706f2543Smrg GlobalUnlock (hGlobal); 749706f2543Smrg pszGlobalData = NULL; 750706f2543Smrg 751706f2543Smrg /* Push the selection data to the Windows clipboard */ 752706f2543Smrg if (fUseUnicode) 753706f2543Smrg SetClipboardData (CF_UNICODETEXT, hGlobal); 754706f2543Smrg else 755706f2543Smrg SetClipboardData (CF_TEXT, hGlobal); 756706f2543Smrg 757706f2543Smrg /* Flag that SetClipboardData has been called */ 758706f2543Smrg fSetClipboardData = FALSE; 759706f2543Smrg 760706f2543Smrg /* 761706f2543Smrg * NOTE: Do not try to free pszGlobalData, it is owned by 762706f2543Smrg * Windows after the call to SetClipboardData (). 763706f2543Smrg */ 764706f2543Smrg 765706f2543Smrg winClipboardFlushXEvents_SelectionNotify_Done: 766706f2543Smrg /* Free allocated resources */ 767706f2543Smrg if (ppszTextList) 768706f2543Smrg XFreeStringList (ppszTextList); 769706f2543Smrg if (xtpText.value) 770706f2543Smrg { 771706f2543Smrg XFree (xtpText.value); 772706f2543Smrg xtpText.value = NULL; 773706f2543Smrg xtpText.nitems = 0; 774706f2543Smrg } 775706f2543Smrg free(pszConvertData); 776706f2543Smrg free(pwszUnicodeStr); 777706f2543Smrg if (hGlobal && pszGlobalData) 778706f2543Smrg GlobalUnlock (hGlobal); 779706f2543Smrg if (fSetClipboardData && g_fUnicodeSupport) 780706f2543Smrg SetClipboardData (CF_UNICODETEXT, NULL); 781706f2543Smrg if (fSetClipboardData) 782706f2543Smrg SetClipboardData (CF_TEXT, NULL); 783706f2543Smrg return WIN_XEVENTS_NOTIFY; 784706f2543Smrg 785706f2543Smrg case SelectionClear: 786706f2543Smrg winDebug("SelectionClear - doing nothing\n"); 787706f2543Smrg break; 788706f2543Smrg 789706f2543Smrg case PropertyNotify: 790706f2543Smrg break; 791706f2543Smrg 792706f2543Smrg case MappingNotify: 793706f2543Smrg break; 794706f2543Smrg 795706f2543Smrg default: 796706f2543Smrg ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type); 797706f2543Smrg break; 798706f2543Smrg } 799706f2543Smrg } 800706f2543Smrg 801706f2543Smrg return WIN_XEVENTS_SUCCESS; 802706f2543Smrg} 803