imLcFlt.c revision eb411b4b
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	    } else {
75	        return(True);
76	    }
77	}
78    }
79
80    if(((Xim)ic->core.im)->private.local.top == 0 )
81	goto emit_braille;
82
83    currstate = ev->xkey.state;
84    if(ev->type == KeyPress) {
85	prevcode = ev->xkey.keycode;
86	prevstate = currstate;
87
88	if(IsModifierKey(keysym))
89	    return(False);
90	prevcode = 0;
91    } else {
92	if(prevcode != ev->xkey.keycode)
93	    return False;
94
95	/* For lookup, we use the state at the time when the key was pressed, */
96	/* because this state was not affected by the modifier that is mapped */
97	/* to the key. */
98	ev->xkey.state = prevstate;
99	XLookupString((XKeyEvent *)ev, buf, sizeof(buf), &keysym, NULL);
100    }
101
102    for(t = ic->private.local.context; t; t = b[t].next) {
103	if(IsModifierKey(b[t].keysym))
104	    anymodifier = True;
105	if(((ev->xkey.state & b[t].modifier_mask) == b[t].modifier) &&
106	   (keysym == b[t].keysym))
107	    break;
108    }
109
110    /* Restore the state */
111    ev->xkey.state = currstate;
112
113    if(t) { /* Matched */
114	if(b[t].succession) { /* Intermediate */
115	    ic->private.local.context = b[t].succession;
116	    return (ev->type == KeyPress);
117	} else { /* Terminate (reached to leaf) */
118	    ic->private.local.composed = t;
119	    ic->private.local.brl_committed = 0;
120	    /* return back to client KeyPressEvent keycode == 0 */
121	    ev->xkey.keycode = 0;
122	    ev->xkey.type = KeyPress;
123	    XPutBackEvent(d, ev);
124	    if(prevcode){
125		/* For modifier key releases, restore the event, as we do not */
126		/* filter it.  */
127		ev->xkey.type = KeyRelease;
128		ev->xkey.keycode = prevcode;
129	    }
130	    /* initialize internal state for next key sequence */
131	    ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
132	    return (ev->type == KeyPress);
133	}
134    } else { /* Unmatched */
135	/* Unmatched modifier key releases abort matching only in the case that */
136	/* there was any modifier that would have matched */
137	if((ic->private.local.context == ((Xim)ic->core.im)->private.local.top) ||
138	   (ev->type == KeyRelease && !anymodifier)) {
139	    goto emit_braille;
140	}
141	/* Error (Sequence Unmatch occured) */
142	/* initialize internal state for next key sequence */
143	ic->private.local.context = ((Xim)ic->core.im)->private.local.top;
144	return (ev->type == KeyPress);
145    }
146
147emit_braille:
148    if(braille) {
149	/* Braille pattern is not in compose tree, emit alone */
150	ic->private.local.brl_committed = ic->private.local.brl_committing;
151	ic->private.local.composed = 0;
152	ev->xkey.keycode = 0;
153	_XPutBackEvent(d, ev);
154	return(True);
155    }
156    return(False);
157}
158