#include <X11/Xatom.h>
#define NEED_EVENTS
#include "Xlibint.h"
#include "Xutil.h"
#include "Xlcint.h"
#include "Ximint.h"
Private long
_XimTriggerCheck(
Xim im,
XKeyEvent *ev,
INT32 len,
CARD32 *keylist)
{
register long i;
KeySym keysym;
CARD32 buf32[BUFSIZE/4];
char *buf = (char *)buf32;
int modifier;
int modifier_mask;
CARD32 min_len = sizeof(CARD32)
+ sizeof(CARD32)
+ sizeof(CARD32);
XLookupString(ev, buf, BUFSIZE, &keysym, NULL);
if (!keysym)
return -1;
for (i = 0; len >= min_len; i += 3, len -= min_len) {
modifier = keylist[i + 1];
modifier_mask = keylist[i + 2];
if (((KeySym)keylist[i] == keysym)
&& ((ev->state & modifier_mask) == modifier))
return i;
}
return -1;
}
Private long
_XimTriggerOnCheck(
Xim im,
XKeyEvent *ev)
{
return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_onkeylist[0],
&im->private.proto.im_onkeylist[1]);
}
Private long
_XimTriggerOffCheck(
Xim im,
XKeyEvent *ev)
{
return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_offkeylist[0],
&im->private.proto.im_offkeylist[1]);
}
Private Bool
_XimOnKeysCheck(
Xic ic,
XKeyEvent *ev)
{
Xim im = (Xim)ic->core.im;
long idx;
if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
im->private.proto.im_onkeylist &&
im->private.proto.im_onkeylist[0]) {
if ((idx = _XimTriggerOnCheck(im, ev)) >= 0) {
(void)_XimTriggerNotify(im, ic, 0, (CARD32)idx);
return True;
}
}
return False;
}
Private Bool
_XimOffKeysCheck(
Xic ic,
XKeyEvent *ev)
{
Xim im = (Xim)ic->core.im;
long idx;
if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
im->private.proto.im_offkeylist &&
im->private.proto.im_offkeylist[0]) {
if ((idx = _XimTriggerOffCheck(im, ev)) >= 0) {
_XimTriggerNotify(im, ic, 1, (CARD32)idx);
return True;
}
}
return False;
}
Private void
_XimPendingFilter(
Xic ic)
{
Xim im = (Xim)ic->core.im;
if (IS_NEED_SYNC_REPLY(ic)) {
(void)_XimProcSyncReply(im, ic);
UNMARK_NEED_SYNC_REPLY(ic);
}
return;
}
Private Bool
_XimProtoKeypressFilter(
Xic ic,
XKeyEvent *ev)
{
#ifdef XIM_CONNECTABLE
Xim im = (Xim)ic->core.im;
#endif
if (IS_FABLICATED(ic)) {
_XimPendingFilter(ic);
UNMARK_FABLICATED(ic);
return NOTFILTERD;
}
if (IS_NEGLECT_EVENT(ic, KeyPressMask))
return FILTERD;
#ifdef XIM_CONNECTABLE
if (!IS_IC_CONNECTED(ic)) {
if (IS_CONNECTABLE(im)) {
if (_XimConnectServer(im)) {
if (!_XimReCreateIC(ic)) {
_XimDelayModeSetAttr(im);
return NOTFILTERD;
}
} else {
return NOTFILTERD;
}
} else {
return NOTFILTERD;
}
}
#else
if (!IS_IC_CONNECTED(ic))
return NOTFILTERD;
#endif
if (!IS_FORWARD_EVENT(ic, KeyPressMask)) {
if (_XimOnKeysCheck(ic, ev))
return FILTERD;
return NOTFILTERD;
}
if (_XimOffKeysCheck(ic, ev))
return FILTERD;
if (_XimForwardEvent(ic, (XEvent *)ev,
IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
return FILTERD;
return NOTFILTERD;
}
Private Bool
_XimFilterKeypress(
Display *d,
Window w,
XEvent *ev,
XPointer client_data)
{
return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev );
}
Private Bool
_XimProtoKeyreleaseFilter(
Xic ic,
XKeyEvent *ev)
{
#ifdef XIM_CONNECTABLE
Xim im = (Xim)ic->core.im;
#endif
if (IS_FABLICATED(ic)) {
_XimPendingFilter(ic);
UNMARK_FABLICATED(ic);
return NOTFILTERD;
}
if (IS_NEGLECT_EVENT(ic, KeyReleaseMask))
return FILTERD;
#ifdef XIM_CONNECTABLE
if (!IS_IC_CONNECTED(ic)) {
if (IS_CONNECTABLE(im)) {
if (_XimConnectServer(im)) {
if (!_XimReCreateIC(ic)) {
_XimDelayModeSetAttr(im);
return NOTFILTERD;
}
} else {
return NOTFILTERD;
}
} else {
return NOTFILTERD;
}
}
#else
if (!IS_IC_CONNECTED(ic))
return NOTFILTERD;
#endif
if (!IS_FORWARD_EVENT(ic, KeyReleaseMask)) {
if (_XimOnKeysCheck(ic, ev))
return FILTERD;
return NOTFILTERD;
}
if (_XimOffKeysCheck(ic, ev))
return FILTERD;
if (_XimForwardEvent(ic, (XEvent *)ev,
IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
return FILTERD;
return NOTFILTERD;
}
Private Bool
_XimFilterKeyrelease(
Display *d,
Window w,
XEvent *ev,
XPointer client_data)
{
return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev);
}
Private void
_XimRegisterKeyPressFilter(
Xic ic)
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYPRESS_MASK)) {
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyPress, KeyPress,
_XimFilterKeypress,
(XPointer)ic);
ic->private.proto.registed_filter_event |= KEYPRESS_MASK;
}
}
return;
}
Private void
_XimRegisterKeyReleaseFilter(
Xic ic)
{
if (ic->core.focus_window) {
if (!(ic->private.proto.registed_filter_event & KEYRELEASE_MASK)) {
_XRegisterFilterByType (ic->core.im->core.display,
ic->core.focus_window,
KeyRelease, KeyRelease,
_XimFilterKeyrelease,
(XPointer)ic);
ic->private.proto.registed_filter_event |= KEYRELEASE_MASK;
}
}
return;
}
Private void
_XimUnregisterKeyPressFilter(
Xic ic)
{
if (ic->core.focus_window) {
if (ic->private.proto.registed_filter_event & KEYPRESS_MASK) {
_XUnregisterFilter (ic->core.im->core.display,
ic->core.focus_window,
_XimFilterKeypress,
(XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYPRESS_MASK;
}
}
return;
}
Private void
_XimUnregisterKeyReleaseFilter(
Xic ic)
{
if (ic->core.focus_window) {
if (ic->private.proto.registed_filter_event & KEYRELEASE_MASK) {
_XUnregisterFilter (ic->core.im->core.display,
ic->core.focus_window,
_XimFilterKeyrelease,
(XPointer)ic);
ic->private.proto.registed_filter_event &= ~KEYRELEASE_MASK;
}
}
return;
}
Public void
_XimRegisterFilter(
Xic ic)
{
_XimRegisterKeyPressFilter(ic);
if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
_XimRegisterKeyReleaseFilter(ic);
return;
}
Public void
_XimUnregisterFilter(
Xic ic)
{
_XimUnregisterKeyPressFilter(ic);
_XimUnregisterKeyReleaseFilter(ic);
return;
}
Public void
_XimReregisterFilter(
Xic ic)
{
if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
_XimRegisterKeyReleaseFilter(ic);
else
_XimUnregisterKeyReleaseFilter(ic);
return;
}
Private Bool
_XimFilterServerDestroy(
Display *d,
Window w,
XEvent *ev,
XPointer client_data)
{
Xim im = (Xim)client_data;
if (ev->type == DestroyNotify) {
UNMARK_SERVER_CONNECTED(im);
#ifdef XIM_CONNECTABLE
if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
_XimServerReconectableDestroy();
return True;
}
#endif
_XimServerDestroy(im);
}
return True;
}
Public void
_XimRegisterServerFilter(
Xim im)
{
if (im->private.proto.im_window) {
if (!(im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK)) {
_XRegisterFilterByMask(im->core.display,
im->private.proto.im_window,
StructureNotifyMask,
_XimFilterServerDestroy,
(XPointer)im);
XSelectInput(im->core.display, im->private.proto.im_window,
StructureNotifyMask);
im->private.proto.registed_filter_event |= DESTROYNOTIFY_MASK;
}
}
return;
}
Public void
_XimUnregisterServerFilter(
Xim im)
{
if (im->private.proto.im_window) {
if (im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK) {
_XUnregisterFilter(im->core.display,
im->private.proto.im_window,
_XimFilterServerDestroy,
(XPointer)im);
im->private.proto.registed_filter_event &= ~DESTROYNOTIFY_MASK;
}
}
return;
}