winclipboardxevents.c [plain text]
#ifdef HAVE_XWIN_CONFIG_H
#include <xwin-config.h>
#endif
#include "winclipboard.h"
#include "misc.h"
extern Bool g_fUnicodeSupport;
int
winClipboardFlushXEvents (HWND hwnd,
int iWindow,
Display *pDisplay,
Bool fUseUnicode)
{
static Atom atomLocalProperty;
static Atom atomCompoundText;
static Atom atomUTF8String;
static Atom atomTargets;
static int generation;
if (generation != serverGeneration)
{
generation = serverGeneration;
atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
atomTargets = XInternAtom (pDisplay, "TARGETS", False);
}
while (XPending (pDisplay))
{
XTextProperty xtpText = {0};
XEvent event;
XSelectionEvent eventSelection;
unsigned long ulReturnBytesLeft;
char *pszReturnData = NULL;
char *pszGlobalData = NULL;
int iReturn;
HGLOBAL hGlobal = NULL;
XICCEncodingStyle xiccesStyle;
int iConvertDataLen = 0;
char *pszConvertData = NULL;
char *pszTextList[2] = {NULL};
int iCount;
char **ppszTextList = NULL;
wchar_t *pwszUnicodeStr = NULL;
int iUnicodeLen = 0;
int iReturnDataLen = 0;
int i;
Bool fAbort = FALSE;
Bool fCloseClipboard = FALSE;
Bool fSetClipboardData = TRUE;
XNextEvent (pDisplay, &event);
switch (event.type)
{
case SelectionRequest:
{
char *pszAtomName = NULL;
winDebug("SelectionRequest - target %d\n",
event.xselectionrequest.target);
pszAtomName = XGetAtomName (pDisplay,
event.xselectionrequest.target);
winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
XFree (pszAtomName);
pszAtomName = NULL;
}
if (event.xselectionrequest.target != XA_STRING
&& event.xselectionrequest.target != atomUTF8String
&& event.xselectionrequest.target != atomCompoundText
&& event.xselectionrequest.target != atomTargets)
{
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
if (event.xselectionrequest.target == atomTargets)
{
Atom atomTargetArr[] = {atomTargets,
atomCompoundText,
atomUTF8String,
XA_STRING};
iReturn = XChangeProperty (pDisplay,
event.xselectionrequest.requestor,
event.xselectionrequest.property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *) atomTargetArr,
(sizeof (atomTargetArr)
/ sizeof (atomTargetArr[0])));
if (iReturn == BadAlloc
|| iReturn == BadAtom
|| iReturn == BadMatch
|| iReturn == BadValue
|| iReturn == BadWindow)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"XChangeProperty failed: %d\n",
iReturn);
}
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = event.xselectionrequest.property;
eventSelection.time = event.xselectionrequest.time;
iReturn = XSendEvent (pDisplay,
eventSelection.requestor,
False,
0L,
(XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed\n");
}
break;
}
if (fUseUnicode
&& !IsClipboardFormatAvailable (CF_UNICODETEXT))
{
static int count;
static HWND lasthwnd;
if (hwnd != lasthwnd) count = 0;
count++;
if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
"available from Win32 clipboard. Aborting %d.\n", count);
lasthwnd = hwnd;
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
else if (!fUseUnicode
&& !IsClipboardFormatAvailable (CF_TEXT))
{
ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
"available from Win32 clipboard. Aborting.\n");
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
if (GetOpenClipboardWindow () == hwnd)
{
CloseClipboard ();
}
if (!OpenClipboard (hwnd))
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"OpenClipboard () failed: %08lx\n",
GetLastError ());
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
fCloseClipboard = TRUE;
if (event.xselectionrequest.target == XA_STRING)
xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
else if (event.xselectionrequest.target == atomUTF8String)
xiccesStyle = XUTF8StringStyle;
#endif
else if (event.xselectionrequest.target == atomCompoundText)
xiccesStyle = XCompoundTextStyle;
else
xiccesStyle = XStringStyle;
if (fUseUnicode)
{
hGlobal = GetClipboardData (CF_UNICODETEXT);
}
else
{
hGlobal = GetClipboardData (CF_TEXT);
}
if (!hGlobal)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"GetClipboardData () failed: %08lx\n",
GetLastError ());
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
pszGlobalData = (char *) GlobalLock (hGlobal);
if (fUseUnicode)
{
iConvertDataLen = WideCharToMultiByte (CP_UTF8,
0,
(LPCWSTR)pszGlobalData,
-1,
NULL,
0,
NULL,
NULL);
pszConvertData = (char *) malloc (iConvertDataLen);
WideCharToMultiByte (CP_UTF8,
0,
(LPCWSTR)pszGlobalData,
-1,
pszConvertData,
iConvertDataLen,
NULL,
NULL);
}
else
{
pszConvertData = strdup (pszGlobalData);
iConvertDataLen = strlen (pszConvertData) + 1;
}
winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));
pszTextList[0] = pszConvertData;
pszTextList[1] = NULL;
xtpText.value = NULL;
xtpText.nitems = 0;
if (fUseUnicode)
{
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextListToTextProperty (pDisplay,
pszTextList,
1,
xiccesStyle,
&xtpText);
#endif
}
else
{
iReturn = XmbTextListToTextProperty (pDisplay,
pszTextList,
1,
xiccesStyle,
&xtpText);
}
if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"X*TextListToTextProperty failed: %d\n",
iReturn);
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
free (pszConvertData);
pszConvertData = NULL;
iReturn = XChangeProperty (pDisplay,
event.xselectionrequest.requestor,
event.xselectionrequest.property,
event.xselectionrequest.target,
8,
PropModeReplace,
xtpText.value,
xtpText.nitems);
if (iReturn == BadAlloc || iReturn == BadAtom
|| iReturn == BadMatch || iReturn == BadValue
|| iReturn == BadWindow)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"XChangeProperty failed: %d\n",
iReturn);
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
GlobalUnlock (hGlobal);
pszGlobalData = NULL;
fCloseClipboard = FALSE;
CloseClipboard ();
XFree (xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = event.xselectionrequest.property;
eventSelection.time = event.xselectionrequest.time;
iReturn = XSendEvent (pDisplay,
eventSelection.requestor,
False,
0L,
(XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed\n");
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
winClipboardFlushXEvents_SelectionRequest_Done:
if (xtpText.value)
{
XFree (xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
}
free(pszConvertData);
if (hGlobal && pszGlobalData)
GlobalUnlock (hGlobal);
if (fAbort)
{
eventSelection.type = SelectionNotify;
eventSelection.send_event = True;
eventSelection.display = pDisplay;
eventSelection.requestor = event.xselectionrequest.requestor;
eventSelection.selection = event.xselectionrequest.selection;
eventSelection.target = event.xselectionrequest.target;
eventSelection.property = None;
eventSelection.time = event.xselectionrequest.time;
iReturn = XSendEvent (pDisplay,
eventSelection.requestor,
False,
0L,
(XEvent *) &eventSelection);
if (iReturn == BadValue || iReturn == BadWindow)
{
ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
"XSendEvent () failed for abort event.\n");
}
}
if (fCloseClipboard)
{
fCloseClipboard = FALSE;
CloseClipboard ();
}
break;
case SelectionNotify:
winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
{
char *pszAtomName;
pszAtomName = XGetAtomName (pDisplay,
event.xselection.selection);
winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
pszAtomName);
XFree (pszAtomName);
}
if (event.xselection.property == None)
{
if (event.xselection.target == XA_STRING)
{
winDebug ("winClipboardFlushXEvents - SelectionNotify - "
"XA_STRING\n");
return WIN_XEVENTS_CONVERT;
}
else if (event.xselection.target == atomUTF8String)
{
winDebug("winClipboardFlushXEvents - SelectionNotify - "
"Requesting conversion of UTF8 target.\n");
XConvertSelection (pDisplay,
event.xselection.selection,
XA_STRING,
atomLocalProperty,
iWindow,
CurrentTime);
XFlush (pDisplay);
return WIN_XEVENTS_CONVERT;
}
#ifdef X_HAVE_UTF8_STRING
else if (event.xselection.target == atomCompoundText)
{
winDebug("winClipboardFlushXEvents - SelectionNotify - "
"Requesting conversion of CompoundText target.\n");
XConvertSelection (pDisplay,
event.xselection.selection,
atomUTF8String,
atomLocalProperty,
iWindow,
CurrentTime);
XFlush (pDisplay);
return WIN_XEVENTS_CONVERT;
}
#endif
else
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
"Unknown format. Cannot request conversion, "
"aborting.\n");
break;
}
}
iReturn = XGetWindowProperty (pDisplay,
iWindow,
atomLocalProperty,
0,
0,
False,
AnyPropertyType,
&xtpText.encoding,
&xtpText.format,
&xtpText.nitems,
&ulReturnBytesLeft,
&xtpText.value);
if (iReturn != Success)
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
"XGetWindowProperty () failed, aborting: %d\n",
iReturn);
break;
}
winDebug("SelectionNotify - returned data %d left %d\n",
xtpText.nitems, ulReturnBytesLeft);
iReturn = XGetWindowProperty (pDisplay,
iWindow,
atomLocalProperty,
0,
ulReturnBytesLeft,
False,
AnyPropertyType,
&xtpText.encoding,
&xtpText.format,
&xtpText.nitems,
&ulReturnBytesLeft,
&xtpText.value);
if (iReturn != Success)
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
"XGetWindowProperty () failed, aborting: %d\n",
iReturn);
break;
}
{
char *pszAtomName = NULL;
winDebug("SelectionNotify - returned data %d left %d\n",
xtpText.nitems, ulReturnBytesLeft);
pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
winDebug("Notify atom name %s\n", pszAtomName);
XFree (pszAtomName);
pszAtomName = NULL;
}
if (fUseUnicode)
{
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextPropertyToTextList (pDisplay,
&xtpText,
&ppszTextList,
&iCount);
#endif
}
else
{
iReturn = XmbTextPropertyToTextList (pDisplay,
&xtpText,
&ppszTextList,
&iCount);
}
if (iReturn == Success || iReturn > 0)
{
if (ppszTextList != NULL)
{
iReturnDataLen = 0;
for (i = 0; i < iCount; i++)
{
iReturnDataLen += strlen(ppszTextList[i]);
}
pszReturnData = malloc (iReturnDataLen + 1);
pszReturnData[0] = '\0';
for (i = 0; i < iCount; i++)
{
strcat (pszReturnData, ppszTextList[i]);
}
}
else
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
"X*TextPropertyToTextList list_return is NULL.\n");
pszReturnData = malloc (1);
pszReturnData[0] = '\0';
}
}
else
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
"X*TextPropertyToTextList returned: ");
switch (iReturn)
{
case XNoMemory:
ErrorF ("XNoMemory\n");
break;
case XConverterNotFound:
ErrorF ("XConverterNotFound\n");
break;
default:
ErrorF ("%d", iReturn);
break;
}
pszReturnData = malloc (1);
pszReturnData[0] = '\0';
}
if (ppszTextList)
XFreeStringList (ppszTextList);
ppszTextList = NULL;
XFree (xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));
if (fUseUnicode)
{
iUnicodeLen = MultiByteToWideChar (CP_UTF8,
0,
pszReturnData,
-1,
NULL,
0);
pwszUnicodeStr
= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
if (!pwszUnicodeStr)
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify "
"malloc failed for pwszUnicodeStr, aborting.\n");
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionNotify_Done;
}
MultiByteToWideChar (CP_UTF8,
0,
pszReturnData,
-1,
pwszUnicodeStr,
iUnicodeLen);
hGlobal = GlobalAlloc (GMEM_MOVEABLE,
sizeof (wchar_t) * (iUnicodeLen + 1));
}
else
{
pszConvertData = strdup (pszReturnData);
iConvertDataLen = strlen (pszConvertData) + 1;
hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
}
free (pszReturnData);
if (!hGlobal)
{
ErrorF ("winClipboardFlushXEvents - SelectionNotify "
"GlobalAlloc failed, aborting: %ld\n",
GetLastError ());
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionNotify_Done;
}
pszGlobalData = GlobalLock (hGlobal);
if (pszGlobalData == NULL)
{
ErrorF ("winClipboardFlushXEvents - Could not lock global "
"memory for clipboard transfer\n");
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionNotify_Done;
}
if (fUseUnicode)
{
memcpy (pszGlobalData,
pwszUnicodeStr,
sizeof (wchar_t) * (iUnicodeLen + 1));
free (pwszUnicodeStr);
pwszUnicodeStr = NULL;
}
else
{
strcpy (pszGlobalData, pszConvertData);
free (pszConvertData);
pszConvertData = NULL;
}
GlobalUnlock (hGlobal);
pszGlobalData = NULL;
if (fUseUnicode)
SetClipboardData (CF_UNICODETEXT, hGlobal);
else
SetClipboardData (CF_TEXT, hGlobal);
fSetClipboardData = FALSE;
winClipboardFlushXEvents_SelectionNotify_Done:
if (ppszTextList)
XFreeStringList (ppszTextList);
if (xtpText.value)
{
XFree (xtpText.value);
xtpText.value = NULL;
xtpText.nitems = 0;
}
free(pszConvertData);
free(pwszUnicodeStr);
if (hGlobal && pszGlobalData)
GlobalUnlock (hGlobal);
if (fSetClipboardData && g_fUnicodeSupport)
SetClipboardData (CF_UNICODETEXT, NULL);
if (fSetClipboardData)
SetClipboardData (CF_TEXT, NULL);
return WIN_XEVENTS_NOTIFY;
case SelectionClear:
winDebug("SelectionClear - doing nothing\n");
break;
case PropertyNotify:
break;
case MappingNotify:
break;
default:
ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
break;
}
}
return WIN_XEVENTS_SUCCESS;
}