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