#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/Xatom.h>
#define NEED_EVENTS
#include "Xlibint.h"
#include "Xlcint.h"
#include "Ximint.h"
#define XIM_EXT_SET_EVENT_MASK_IDX 0
#ifdef EXT_FORWARD
#define XIM_EXT_FORWARD_KEYEVENT_IDX 1
#endif
#ifdef EXT_MOVE
#define XIM_EXT_MOVE_IDX 2
#endif
typedef struct _XIM_QueryExtRec {
Bool is_support;
const char *name;
int name_len;
CARD16 major_opcode;
CARD16 minor_opcode;
int idx;
} XIM_QueryExtRec;
Private XIM_QueryExtRec extensions[] = {
{False, "XIM_EXT_SET_EVENT_MASK", 0, 0, 0,
XIM_EXT_SET_EVENT_MASK_IDX},
#ifdef EXT_FORWARD
{False, "XIM_EXT_FORWARD_KEYEVENT", 0, 0, 0,
XIM_EXT_FORWARD_KEYEVENT_IDX},
#endif
#ifdef EXT_MOVE
{False, "XIM_EXT_MOVE", 0, 0, 0, XIM_EXT_MOVE_IDX},
#endif
{False, NULL, 0, 0, 0, 0}
};
Private int
_XimIsSupportExt(
int idx)
{
register int i;
int n = XIMNumber(extensions) - 1;
for (i = 0; i < n; i++) {
if (extensions[i].idx == idx) {
if (extensions[i].is_support)
return i;
else
break;
}
}
return -1;
}
Private Bool
_XimProcExtSetEventMask(
Xim im,
Xic ic,
XPointer buf)
{
EVENTMASK *buf_l = (EVENTMASK *)buf;
EVENTMASK select_mask = _XimGetWindowEventmask(ic);
ic->private.proto.filter_event_mask = buf_l[0];
ic->private.proto.intercept_event_mask = buf_l[1];
ic->private.proto.select_event_mask = buf_l[2];
ic->private.proto.forward_event_mask = buf_l[3];
ic->private.proto.synchronous_event_mask = buf_l[4];
select_mask &= ~ic->private.proto.intercept_event_mask;
select_mask |= ic->private.proto.select_event_mask;
XSelectInput(im->core.display, ic->core.focus_window, select_mask);
_XimReregisterFilter(ic);
if (!(_XimProcSyncReply(im, ic)))
return False;
return True;
}
Private Bool
_XimExtSetEventMaskCallback(
Xim xim,
INT16 len,
XPointer data,
XPointer call_data)
{
CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
XIMID imid = buf_s[0];
XICID icid = buf_s[1];
Xim im = (Xim)call_data;
Xic ic;
if ((imid == im->private.proto.imid)
&& (ic = _XimICOfXICID(im, icid))) {
(void)_XimProcExtSetEventMask(im, ic, (XPointer)&buf_s[2]);
return True;
}
return False;
}
#ifdef EXT_FORWARD
Private Bool
_XimProcExtForwardKeyEvent(
Xim im,
Xic ic,
XPointer buf)
{
CARD8 *buf_b = (CARD8 *)buf;
CARD16 *buf_s = (CARD16 *)buf;
CARD32 *buf_l = (CARD32 *)buf;
XEvent ev;
XKeyEvent *kev = (XKeyEvent *)&ev;
bzero(&ev, sizeof(XEvent));
kev->send_event = False;
kev->display = im->core.display;
kev->serial = buf_s[1];
kev->type = buf_b[4] & 0x7f;
kev->keycode = buf_b[5];
kev->state = buf_s[3];
kev->time = buf_l[2];
XPutBackEvent(im->core.display, &ev);
_XimRespSyncReply(ic, buf_s[0]);
MARK_FABLICATED(ic);
return True;
}
Private Bool
_XimExtForwardKeyEventCallback(
Xim xim,
INT16 len,
XPointer data,
XPointer call_data)
{
CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
XIMID imid = buf_s[0];
XICID icid = buf_s[1];
Xim im = (Xim)call_data;
Xic ic;
if ((imid == im->private.proto.imid)
&& (ic = _XimICOfXICID(im, icid))) {
(void)_XimProcExtForwardKeyEvent(im, ic, (XPointer)&buf_s[2]);
return True;
}
return False;
}
Private Bool
_XimExtForwardKeyEventCheck(
Xim im,
INT16 len,
XPointer data,
XPointer arg)
{
Xic ic = (Xic)arg;
CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
CARD8 major_opcode = *((CARD8 *)data);
CARD8 minor_opcode = *((CARD8 *)data + 1);
XIMID imid = buf_s[0];
XICID icid = buf_s[1];
if ((major_opcode == XIM_SYNC_REPLY)
&& (minor_opcode == 0)
&& (imid == im->private.proto.imid)
&& (icid == ic->private.proto.icid))
if ((major_opcode == XIM_ERROR)
&& (minor_opcode == 0)
&& (buf_s[2] & XIM_IMID_VALID)
&& (imid == im->private.proto.imid)
&& (buf_s[2] & XIM_ICID_VALID)
&& (icid == ic->private.proto.icid))
return True;
return False;
}
Public Bool
_XimExtForwardKeyEvent(
Xic ic,
XKeyEvent *ev,
Bool sync)
{
Xim im = (Xim) ic->core.im;
CARD32 buf32[BUFSIZE/4];
CARD8 *buf = (CARD8 *)buf32;
CARD8 *buf_b = &buf[XIM_HEADER_SIZE];
CARD16 *buf_s = (CARD16 *)buf_b;
CARD32 *buf_l = (CARD32 *)buf_b;
CARD32 reply32[BUFSIZE/4];
char *reply = (char *)reply32;
XPointer preply;
int buf_size;
int ret_code;
INT16 len;
int idx;
if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) < 0)
return False;
buf_s[0] = im->private.proto.imid;
buf_s[1] = ic->private.proto.icid;
buf_s[2] = sync ? XimSYNCHRONUS : 0;
buf_s[3] = (CARD16)(((XAnyEvent *)ev)->serial & ((unsigned long) 0xffff));
buf_b[8] = ev->type;
buf_b[9] = ev->keycode;
buf_s[5] = ev->state;
buf_l[3] = ev->time;
len = sizeof(CARD16)
+ sizeof(CARD16)
+ sizeof(BITMASK16)
+ sizeof(CARD16)
+ sizeof(BYTE)
+ sizeof(BYTE)
+ sizeof(CARD16)
+ sizeof(CARD32);
_XimSetHeader((XPointer)buf,
extensions[idx].major_opcode,
extensions[idx].minor_opcode, &len);
if (!(_XimWrite(im, len, (XPointer)buf)))
return False;
_XimFlush(im);
if (sync) {
buf_size = BUFSIZE;
ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
_XimExtForwardKeyEventCheck, (XPointer)ic);
if(ret_code == XIM_TRUE) {
preply = reply;
} else if(ret_code == XIM_OVERFLOW) {
if(len <= 0) {
preply = reply;
} else {
buf_sizex = len;
preply = (XPointer)Xmalloc(buf_size);
ret_code = _XimRead(im, &len, preply, buf_size,
_XimExtForwardKeyEventCheck, (XPointer)ic);
if(ret_code != XIM_TRUE) {
Xfree(preply);
return False;
}
}
} else
return False;
buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
if (*((CARD8 *)preply) == XIM_ERROR) {
_XimProcError(im, 0, (XPointer)&buf_s[3]);
if(reply != preply)
Xfree(preply);
return False;
}
if(reply != preply)
Xfree(preply);
}
return True;
}
#endif
Private int
_XimCheckExtensionListSize(void)
{
register int i;
int len;
int total = 0;
int n = XIMNumber(extensions) - 1;
for (i = 0; i < n; i++) {
len = strlen(extensions[i].name);
extensions[i].name_len = len;
len += sizeof(BYTE);
total += len;
}
return total;
}
Private void
_XimSetExtensionList(
CARD8 *buf)
{
register int i;
int len;
int n = XIMNumber(extensions) - 1;
for (i = 0; i < n; i++) {
len = extensions[i].name_len;
buf[0] = (BYTE)len;
(void)strcpy((char *)&buf[1], extensions[i].name);
len += sizeof(BYTE);
buf += len;
}
return;
}
Private unsigned int
_XimCountNumberOfExtension(
INT16 total,
CARD8 *ext)
{
unsigned int n;
INT16 len;
INT16 min_len = sizeof(CARD8)
+ sizeof(CARD8)
+ sizeof(INT16);
n = 0;
while (total > min_len) {
len = *((INT16 *)(&ext[2]));
len += (min_len + XIM_PAD(len));
total -= len;
ext += len;
n++;
}
return n;
}
Private Bool
_XimParseExtensionList(
Xim im,
CARD16 *data)
{
int num = XIMNumber(extensions) - 1;
unsigned int n;
CARD8 *buf;
register int i;
register int j;
INT16 len;
if (!(n = _XimCountNumberOfExtension(data[0], (CARD8 *)&data[1])))
return True;
buf = (CARD8 *)&data[1];;
for (i = 0; i < n; i++) {
len = *((INT16 *)(&buf[2]));
for (j = 0; j < num; j++) {
if (!(strncmp(extensions[j].name, (char *)&buf[4], len))) {
extensions[j].major_opcode = buf[0];
extensions[j].minor_opcode = buf[1];
extensions[j].is_support = True;
break;
}
}
len += sizeof(CARD8)
+ sizeof(CARD8)
+ sizeof(INT16)
+ XIM_PAD(len);
buf += len;
}
return True;
}
Private Bool
_XimQueryExtensionCheck(
Xim im,
INT16 len,
XPointer data,
XPointer arg)
{
CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
CARD8 major_opcode = *((CARD8 *)data);
CARD8 minor_opcode = *((CARD8 *)data + 1);
XIMID imid = buf_s[0];
if ((major_opcode == XIM_QUERY_EXTENSION_REPLY)
&& (minor_opcode == 0)
&& (imid == im->private.proto.imid))
return True;
if ((major_opcode == XIM_ERROR)
&& (minor_opcode == 0)
&& (buf_s[2] & XIM_IMID_VALID)
&& (imid == im->private.proto.imid))
return True;
return False;
}
Public Bool
_XimExtension(
Xim im)
{
CARD8 *buf;
CARD16 *buf_s;
int buf_len;
INT16 len;
CARD32 reply32[BUFSIZE/4];
char *reply = (char *)reply32;
XPointer preply;
int buf_size;
int ret_code;
int idx;
if (!(len = _XimCheckExtensionListSize()))
return True;
buf_len = XIM_HEADER_SIZE
+ sizeof(CARD16)
+ sizeof(INT16)
+ len
+ XIM_PAD(len);
if (!(buf = (CARD8 *)Xmalloc(buf_len)))
return False;
buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
buf_s[0] = im->private.proto.imid;
buf_s[1] = len;
_XimSetExtensionList((CARD8 *)&buf_s[2]);
XIM_SET_PAD(&buf_s[2], len);
len += sizeof(CARD16)
+ sizeof(INT16);
_XimSetHeader((XPointer)buf, XIM_QUERY_EXTENSION, 0, &len);
if (!(_XimWrite(im, len, (XPointer)buf))) {
XFree(buf);
return False;
}
XFree(buf);
_XimFlush(im);
buf_size = BUFSIZE;
ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
_XimQueryExtensionCheck, 0);
if(ret_code == XIM_TRUE) {
preply = reply;
} else if(ret_code == XIM_OVERFLOW) {
if(len <= 0) {
preply = reply;
} else {
buf_size = len;
preply = (XPointer)Xmalloc(buf_size);
ret_code = _XimRead(im, &len, reply, buf_size,
_XimQueryExtensionCheck, 0);
if(ret_code != XIM_TRUE) {
Xfree(preply);
return False;
}
}
} else
return False;
buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
if (*((CARD8 *)preply) == XIM_ERROR) {
_XimProcError(im, 0, (XPointer)&buf_s[3]);
if(reply != preply)
Xfree(preply);
return False;
}
if (!(_XimParseExtensionList(im, &buf_s[1]))) {
if(reply != preply)
Xfree(preply);
return False;
}
if(reply != preply)
Xfree(preply);
if ((idx = _XimIsSupportExt(XIM_EXT_SET_EVENT_MASK_IDX)) >= 0)
_XimRegProtoIntrCallback(im,
extensions[idx].major_opcode,
extensions[idx].minor_opcode,
_XimExtSetEventMaskCallback, (XPointer)im);
#ifdef EXT_FORWARD
if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) >= 0)
_XimRegProtoIntrCallback(im,
extensions[idx].major_opcode,
extensions[idx].minor_opcode,
_XimExtForwardKeyEventCallback, (XPointer)im);
#endif
return True;
}
#ifdef EXT_MOVE
#define EXT_XNSPOTLOCATION (1L<<0)
#define SET_EXT_XNSPOTLOCATION(flag) (flag |= EXT_XNSPOTLOCATION)
#define IS_EXT_XNSPOTLOCATION(flag) (flag & EXT_XNSPOTLOCATION)
#define XIM_Xpoint_length 12
Private Bool
_XimExtMove(
Xim im,
Xic ic,
CARD16 x,
CARD16 y)
{
CARD32 buf32[BUFSIZE/4];
CARD8 *buf = (CARD8 *)buf32;
CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
INT16 len;
int idx;
if ((idx = _XimIsSupportExt(XIM_EXT_MOVE_IDX)) < 0)
return False;
buf_s[0] = im->private.proto.imid;
buf_s[1] = ic->private.proto.icid;
buf_s[2] = x;
buf_s[3] = y;
len = sizeof(CARD16)
+ sizeof(CARD16)
+ sizeof(INT16)
+ sizeof(INT16);
_XimSetHeader((XPointer)buf, extensions[idx].major_opcode,
extensions[idx].minor_opcode, &len);
if (!(_XimWrite(im, len, (XPointer)buf)))
return False;
_XimFlush(im);
return True;
}
Public BITMASK32
_XimExtenArgCheck(
XIMArg *arg)
{
CARD32 flag = 0L;
if (!strcmp(arg->name, XNSpotLocation))
SET_EXT_XNSPOTLOCATION(flag);
return flag;
}
Public Bool
_XimExtenMove(
Xim im,
Xic ic,
CARD32 flag,
CARD16 *buf,
INT16 length)
{
if ((IS_EXT_XNSPOTLOCATION(flag)) && (length == XIM_Xpoint_length))
return _XimExtMove(im, ic, buf[4], buf[5]);
return False;
}
#endif