upload tizen2.0 source
[framework/uifw/xorg/lib/libx11.git] / modules / im / ximcp / imDefFlt.c
1 /******************************************************************
2
3            Copyright 1992, 1993, 1994 by FUJITSU LIMITED
4
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and
8 that both that copyright notice and this permission notice appear
9 in supporting documentation, and that the name of FUJITSU LIMITED
10 not be used in advertising or publicity pertaining to distribution
11 of the software without specific, written prior permission.
12 FUJITSU LIMITED makes no representations about the suitability of
13 this software for any purpose.
14 It is provided "as is" without express or implied warranty.
15
16 FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 PERFORMANCE OF THIS SOFTWARE.
23
24   Author: Takashi Fujiwara     FUJITSU LIMITED
25                                fujiwara@a80.tech.yk.fujitsu.co.jp
26
27 ******************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 #include <X11/Xatom.h>
33 #include "Xlibint.h"
34 #include "Xutil.h"
35 #include "Xlcint.h"
36 #include "Ximint.h"
37
38 Private long
39 _XimTriggerCheck(
40     Xim                  im,
41     XKeyEvent           *ev,
42     INT32                len,
43     CARD32              *keylist)
44 {
45     register long        i;
46     KeySym               keysym;
47     CARD32               buf32[BUFSIZE/4];
48     char                *buf = (char *)buf32;
49     int                  modifier;
50     int                  modifier_mask;
51     CARD32               min_len = sizeof(CARD32)   /* sizeof keysym */
52                                  + sizeof(CARD32)   /* sizeof modifier */
53                                  + sizeof(CARD32);  /* sizeof modifier mask */
54
55     XLookupString(ev, buf, BUFSIZE, &keysym, NULL);
56     if (!keysym)
57         return -1;
58
59     for (i = 0; len >= min_len; i += 3, len -= min_len) {
60         modifier      = keylist[i + 1];
61         modifier_mask = keylist[i + 2];
62         if (((KeySym)keylist[i] == keysym)
63          && ((ev->state & modifier_mask) == modifier))
64             return i;
65     }
66     return -1;
67 }
68
69 Private long
70 _XimTriggerOnCheck(
71     Xim          im,
72     XKeyEvent   *ev)
73 {
74     return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_onkeylist[0],
75                                         &im->private.proto.im_onkeylist[1]);
76 }
77
78 Private long
79 _XimTriggerOffCheck(
80     Xim          im,
81     XKeyEvent   *ev)
82 {
83     return _XimTriggerCheck(im, ev, (INT32)im->private.proto.im_offkeylist[0],
84                                         &im->private.proto.im_offkeylist[1]);
85 }
86
87 Private Bool
88 _XimOnKeysCheck(
89     Xic          ic,
90     XKeyEvent   *ev)
91 {
92     Xim          im = (Xim)ic->core.im;
93     long         idx;
94
95     if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
96             im->private.proto.im_onkeylist &&
97             im->private.proto.im_onkeylist[0]) {
98         if ((idx = _XimTriggerOnCheck(im, ev)) >= 0) {
99             (void)_XimTriggerNotify(im, ic, 0, (CARD32)idx); /* Trigger on */
100             return True;
101         }
102     }
103     return False;
104 }
105
106 Private Bool
107 _XimOffKeysCheck(
108     Xic          ic,
109     XKeyEvent   *ev)
110 {
111     Xim          im = (Xim)ic->core.im;
112     long         idx;
113
114     if (IS_DYNAMIC_EVENT_FLOW(ic->core.im) &&
115             im->private.proto.im_offkeylist &&
116             im->private.proto.im_offkeylist[0]) {
117         if ((idx = _XimTriggerOffCheck(im, ev)) >= 0) {
118             _XimTriggerNotify(im, ic, 1, (CARD32)idx); /* Trigger off */
119             return True;
120         }
121     }
122     return False;
123 }
124
125 Private void
126 _XimPendingFilter(
127     Xic          ic)
128 {
129     Xim          im = (Xim)ic->core.im;
130
131     if (IS_NEED_SYNC_REPLY(im)) {
132         (void)_XimProcSyncReply(im, ic);
133         UNMARK_NEED_SYNC_REPLY(im);
134     }
135     return;
136 }
137
138 Private Bool
139 _XimProtoKeypressFilter(
140     Xic          ic,
141     XKeyEvent   *ev)
142 {
143     Xim         im = (Xim)ic->core.im;
144
145     if (IS_FABRICATED(im)) {
146         _XimPendingFilter(ic);
147         UNMARK_FABRICATED(im);
148         return NOTFILTERD;
149     }
150
151     if (IS_NEGLECT_EVENT(ic, KeyPressMask))
152         return FILTERD;
153
154 #ifdef XIM_CONNECTABLE
155     if (!IS_IC_CONNECTED(ic)) {
156         if (IS_CONNECTABLE(im)) {
157             if (_XimConnectServer(im)) {
158                 if (!_XimReCreateIC(ic)) {
159                     _XimDelayModeSetAttr(im);
160                     return NOTFILTERD;
161                 }
162             } else {
163                 return NOTFILTERD;
164             }
165         } else {
166             return NOTFILTERD;
167         }
168     }
169 #else
170     if (!IS_IC_CONNECTED(ic))
171         return NOTFILTERD;
172 #endif /* XIM_CONNECTABLE */
173
174     if (!IS_FORWARD_EVENT(ic, KeyPressMask)) {
175         if (_XimOnKeysCheck(ic, ev))
176             return FILTERD;
177         return NOTFILTERD;
178     }
179     if (_XimOffKeysCheck(ic, ev))
180         return FILTERD;
181
182     if (_XimForwardEvent(ic, (XEvent *)ev,
183                                 IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
184         return FILTERD;
185
186     return NOTFILTERD;
187 }
188
189 Private Bool
190 _XimFilterKeypress(
191     Display             *d,
192     Window               w,
193     XEvent              *ev,
194     XPointer             client_data)
195 {
196     return _XimProtoKeypressFilter((Xic)client_data, (XKeyEvent *)ev );
197 }
198
199 Private Bool
200 _XimProtoKeyreleaseFilter(
201     Xic          ic,
202     XKeyEvent   *ev)
203 {
204     Xim         im = (Xim)ic->core.im;
205
206     if (IS_FABRICATED(im)) {
207         _XimPendingFilter(ic);
208         UNMARK_FABRICATED(im);
209         return NOTFILTERD;
210     }
211
212     if (IS_NEGLECT_EVENT(ic, KeyReleaseMask))
213         return FILTERD;
214
215 #ifdef XIM_CONNECTABLE
216     if (!IS_IC_CONNECTED(ic)) {
217         if (IS_CONNECTABLE(im)) {
218             if (_XimConnectServer(im)) {
219                 if (!_XimReCreateIC(ic)) {
220                     _XimDelayModeSetAttr(im);
221                     return NOTFILTERD;
222                 }
223             } else {
224                 return NOTFILTERD;
225             }
226         } else {
227             return NOTFILTERD;
228         }
229     }
230 #else
231     if (!IS_IC_CONNECTED(ic))
232         return NOTFILTERD;
233 #endif /* XIM_CONNECTABLE */
234
235     if (!IS_FORWARD_EVENT(ic, KeyReleaseMask)) {
236         if (_XimOnKeysCheck(ic, ev))
237             return FILTERD;
238         return NOTFILTERD;
239     }
240     if (_XimOffKeysCheck(ic, ev))
241             return FILTERD;
242
243     if (_XimForwardEvent(ic, (XEvent *)ev,
244                                 IS_SYNCHRONOUS_EVENT(ic, KeyPressMask)))
245         return FILTERD;
246
247     return NOTFILTERD;
248 }
249
250 Private Bool
251 _XimFilterKeyrelease(
252     Display             *d,
253     Window               w,
254     XEvent              *ev,
255     XPointer             client_data)
256 {
257     return _XimProtoKeyreleaseFilter((Xic)client_data, (XKeyEvent *)ev);
258 }
259
260 Private void
261 _XimRegisterKeyPressFilter(
262     Xic          ic)
263 {
264     if (ic->core.focus_window) {
265         if (!(ic->private.proto.registed_filter_event & KEYPRESS_MASK)) {
266             _XRegisterFilterByType (ic->core.im->core.display,
267                                     ic->core.focus_window,
268                                     KeyPress, KeyPress,
269                                     _XimFilterKeypress,
270                                     (XPointer)ic);
271             ic->private.proto.registed_filter_event |= KEYPRESS_MASK;
272         }
273     }
274     return;
275 }
276
277 Private void
278 _XimRegisterKeyReleaseFilter(
279     Xic          ic)
280 {
281     if (ic->core.focus_window) {
282         if (!(ic->private.proto.registed_filter_event & KEYRELEASE_MASK)) {
283             _XRegisterFilterByType (ic->core.im->core.display,
284                                     ic->core.focus_window,
285                                     KeyRelease, KeyRelease,
286                                     _XimFilterKeyrelease,
287                                     (XPointer)ic);
288             ic->private.proto.registed_filter_event |= KEYRELEASE_MASK;
289         }
290     }
291     return;
292 }
293
294 Private void
295 _XimUnregisterKeyPressFilter(
296     Xic          ic)
297 {
298     if (ic->core.focus_window) {
299         if (ic->private.proto.registed_filter_event & KEYPRESS_MASK) {
300             _XUnregisterFilter (ic->core.im->core.display,
301                                 ic->core.focus_window,
302                                 _XimFilterKeypress,
303                                 (XPointer)ic);
304             ic->private.proto.registed_filter_event &= ~KEYPRESS_MASK;
305         }
306     }
307     return;
308 }
309
310 Private void
311 _XimUnregisterKeyReleaseFilter(
312     Xic          ic)
313 {
314     if (ic->core.focus_window) {
315         if (ic->private.proto.registed_filter_event & KEYRELEASE_MASK) {
316             _XUnregisterFilter (ic->core.im->core.display,
317                                 ic->core.focus_window,
318                                 _XimFilterKeyrelease,
319                                 (XPointer)ic);
320             ic->private.proto.registed_filter_event &= ~KEYRELEASE_MASK;
321         }
322     }
323     return;
324 }
325
326 Public void
327 _XimRegisterFilter(
328     Xic          ic)
329 {
330     _XimRegisterKeyPressFilter(ic);
331     if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
332         _XimRegisterKeyReleaseFilter(ic);
333     return;
334 }
335
336 Public void
337 _XimUnregisterFilter(
338     Xic          ic)
339 {
340     _XimUnregisterKeyPressFilter(ic);
341     _XimUnregisterKeyReleaseFilter(ic);
342     return;
343 }
344
345 Public void
346 _XimReregisterFilter(
347     Xic          ic)
348 {
349     if (IS_FORWARD_EVENT(ic, KeyReleaseMask))
350         _XimRegisterKeyReleaseFilter(ic);
351     else
352         _XimUnregisterKeyReleaseFilter(ic);
353
354     return;
355 }
356
357 Private Bool
358 _XimFilterServerDestroy(
359     Display             *d,
360     Window               w,
361     XEvent              *ev,
362     XPointer             client_data)
363 {
364     Xim                  im = (Xim)client_data;
365
366     if (ev->type == DestroyNotify) {
367         UNMARK_SERVER_CONNECTED(im);
368 #ifdef XIM_CONNECTABLE
369         if (!IS_SERVER_CONNECTED(im) && IS_RECONNECTABLE(im)) {
370             _XimServerReconectableDestroy();
371             return True;
372         }
373 #endif /* XIM_CONNECTABLE */
374         _XimServerDestroy(im);
375     }
376     return True;
377 }
378
379 Public void
380 _XimRegisterServerFilter(
381     Xim          im)
382 {
383     if (im->private.proto.im_window) {
384         if (!(im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK)) {
385             _XRegisterFilterByMask(im->core.display,
386                     im->private.proto.im_window,
387                     StructureNotifyMask,
388                     _XimFilterServerDestroy,
389                     (XPointer)im);
390             XSelectInput(im->core.display, im->private.proto.im_window,
391                          StructureNotifyMask);
392             im->private.proto.registed_filter_event |= DESTROYNOTIFY_MASK;
393         }
394     }
395     return;
396 }
397
398 Public void
399 _XimUnregisterServerFilter(
400     Xim          im)
401 {
402     if (im->private.proto.im_window) {
403         if (im->private.proto.registed_filter_event & DESTROYNOTIFY_MASK) {
404             _XUnregisterFilter(im->core.display,
405                     im->private.proto.im_window,
406                     _XimFilterServerDestroy,
407                     (XPointer)im);
408             im->private.proto.registed_filter_event &= ~DESTROYNOTIFY_MASK;
409         }
410     }
411     return;
412 }
413