imLcFlt.c revision 258a0ebe
1/******************************************************************
2
3              Copyright 1992 by Fuji Xerox Co., Ltd.
4              Copyright 1992, 1994 by FUJITSU LIMITED
5
6Permission to use, copy, modify, distribute, and sell this software
7and its documentation for any purpose is hereby granted without fee,
8provided that the above copyright notice appear in all copies and
9that both that copyright notice and this permission notice appear
10in supporting documentation, and that the name of Fuji Xerox,
11FUJITSU LIMITED not be used in advertising or publicity pertaining
12to distribution of the software without specific, written prior
13permission. Fuji Xerox, FUJITSU LIMITED make no representations
14about the suitability of this software for any purpose.
15It is provided "as is" without express or implied warranty.
16
17FUJI XEROX, FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH
18REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
19MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL FUJI XEROX,
20FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
22OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24PERFORMANCE OF THIS SOFTWARE.
25
26  Author   : Kazunori Nishihara	Fuji Xerox
27  Modifier : Takashi Fujiwara   FUJITSU LIMITED
28                                fujiwara@a80.tech.yk.fujitsu.co.jp
29
30******************************************************************/
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include "Xlibint.h"
36#include <X11/keysym.h>
37#include "Xlcint.h"
38#include "Ximint.h"
39
40Bool
41_XimLocalFilter(Display *d, Window w, XEvent *ev, XPointer client_data)
42{
43    Xic		 ic = (Xic)client_data;
44    KeySym	 keysym;
45    static char	 buf[256];
46    static unsigned prevcode = 0, prevstate = 0;
47    unsigned    currstate;
48    DefTree	*b = ic->private.local.base.tree;
49    DTIndex	 t;
50    Bool	 braille = False, anymodifier = False;
51
52    if(ev->xkey.keycode == 0)
53	return (False);
54
55    XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &keysym, NULL);
56
57    if(keysym >= XK_braille_dot_1 && keysym <= XK_braille_dot_8) {
58	if(ev->type == KeyPress) {
59	    ic->private.local.brl_pressed |=
60		1<<(keysym-XK_braille_dot_1);
61	    return(True);
62	} else {
63	    if(!ic->private.local.brl_committing
64		    || ev->xkey.time - ic->private.local.brl_release_start > 300) {
65	    	ic->private.local.brl_committing = ic->private.local.brl_pressed;
66		ic->private.local.brl_release_start = ev->xkey.time;
67	    }
68	    ic->private.local.brl_pressed &= ~(1<<(keysym-XK_braille_dot_1));
69	    if(!ic->private.local.brl_pressed && ic->private.local.brl_committing) {
70		/* Commited a braille pattern, let it go through compose tree */
71		keysym = XK_braille_blank | ic->private.local.brl_committing;
72		ev->type = KeyPress;
73		braille = True;
74		ic->private.local.brl_committing = 0;
75	    } else {
76	        return(True);
77	    }
78	}
79    }
80
81    if(((Xim)ic->core.im)->private.local.top == 0 )
82	goto emit_braille;
83
84    currstate = ev->xkey.state;
85    if(ev->type == KeyPress) {
86	prevcode = ev->xkey.keycode;
87	prevstate = currstate;
88
89	if(IsModifierKey(keysym))
90	    return(False);
91	prevcode = 0;
92    } else {
93	if(prevcode != ev->xkey.keycode)
94	    return False;
95
96	/* For lookup, we use the state at the time when the key was pressed, */
97	/* because this state was not affected by the modifier that is mapped */
98	/* to the key. */
99	ev->xkey.state = prevstate;
100	XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &keysym, NULL);
101    }
102
103    for(t = ic->private.local.context; t; t = b[t].next) {
104	if(IsModifierKey(b[t].keysym))
105	    anymodifier = True;
106	if(((ev->xkey.state & b[t].modifier_mask) == b[t].modifier) &&
107	   (keysym == b[t].keysym))
108	    break;
109    }
110
111    /* Restore the state */
112    ev->xkey.state = currstate;
113
114    if(t) { /* Matched */
115	if(b[t].succession) { /* Intermediate */
116	    ic->private.local.context = b[t].succession;
117	    return (ev->type == KeyPress);
118	} else { /* Terminate (reached to leaf) */
119	    ic->private.local.composed = t;
120	    ic->private.local.brl_committed = 0;
121	    /* return back to client KeyPressEvent keycode == 0 */
122	    ev->xkey.keycode = 0;
123	    ev->xkey.type = KeyPress;
124	    XPutBackEvent(d, ev);
125	    if(prevcode){
126		/* For modifier key releases, restore the event, as we do not */
127		/* filter it.  */
128		ev->xkey.type = KeyRelease;
129		ev->xkey.keycode = prevcode;
130	    }
131	    /* initialize internal state for next key sequence */
132	    ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
133	    return (ev->type == KeyPress);
134	}
135    } else { /* Unmatched */
136	/* Unmatched modifier key releases abort matching only in the case that */
137	/* there was any modifier that would have matched */
138	if((ic->private.local.context == ((Xim)ic->core.im)->private.local.top) ||
139	   (ev->type == KeyRelease && !anymodifier)) {
140	    goto emit_braille;
141	}
142	/* Error (Sequence Unmatch occured) */
143	/* initialize internal state for next key sequence */
144	ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
145	return (ev->type == KeyPress);
146    }
147
148emit_braille:
149    if(braille) {
150	/* Braille pattern is not in compose tree, emit alone */
151	ic->private.local.brl_committed = ic->private.local.brl_committing;
152	ic->private.local.composed = 0;
153	ev->xkey.keycode = 0;
154	_XPutBackEvent(d, ev);
155	return(True);
156    }
157    return(False);
158}
159