upload tizen2.0 source
[framework/uifw/xorg/lib/libx11.git] / modules / im / ximcp / imExten.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 "Xlcint.h"
35 #include "Ximint.h"
36
37 /*
38  * index of extensions
39  */
40
41 #define XIM_EXT_SET_EVENT_MASK_IDX      0
42 #ifdef EXT_FORWARD
43 #define XIM_EXT_FORWARD_KEYEVENT_IDX    1
44 #endif
45 #ifdef EXT_MOVE
46 #define XIM_EXT_MOVE_IDX                2
47 #endif
48
49 typedef struct  _XIM_QueryExtRec {
50     Bool         is_support;
51     const char  *name;
52     int          name_len;
53     CARD16       major_opcode;
54     CARD16       minor_opcode;
55     int          idx;
56 } XIM_QueryExtRec;
57
58 Private XIM_QueryExtRec extensions[] = {
59         {False, "XIM_EXT_SET_EVENT_MASK", 0, 0, 0,
60                                         XIM_EXT_SET_EVENT_MASK_IDX},
61 #ifdef EXT_FORWARD
62         {False, "XIM_EXT_FORWARD_KEYEVENT", 0, 0, 0,
63                                         XIM_EXT_FORWARD_KEYEVENT_IDX},
64 #endif
65 #ifdef EXT_MOVE
66         {False, "XIM_EXT_MOVE", 0, 0, 0, XIM_EXT_MOVE_IDX},
67 #endif
68         {False, NULL, 0, 0, 0, 0}               /* dummy */
69 };
70
71 Private int
72 _XimIsSupportExt(
73     int          idx)
74 {
75     register int i;
76     int          n = XIMNumber(extensions) - 1;
77
78     for (i = 0; i < n; i++) {
79         if (extensions[i].idx == idx) {
80             if (extensions[i].is_support)
81                 return i;
82             else
83                 break;
84         }
85     }
86     return -1;
87 }
88
89 Private Bool
90 _XimProcExtSetEventMask(
91     Xim          im,
92     Xic          ic,
93     XPointer     buf)
94 {
95     EVENTMASK   *buf_l = (EVENTMASK *)buf;
96     EVENTMASK    select_mask = _XimGetWindowEventmask(ic);
97
98     ic->private.proto.filter_event_mask      = buf_l[0];
99     ic->private.proto.intercept_event_mask   = buf_l[1];
100     ic->private.proto.select_event_mask      = buf_l[2];
101     ic->private.proto.forward_event_mask     = buf_l[3];
102     ic->private.proto.synchronous_event_mask = buf_l[4];
103
104     select_mask &= ~ic->private.proto.intercept_event_mask;
105                                                 /* deselected event mask */
106     select_mask |= ic->private.proto.select_event_mask;
107                                                 /* selected event mask */
108     XSelectInput(im->core.display, ic->core.focus_window, select_mask);
109     _XimReregisterFilter(ic);
110
111     if (!(_XimProcSyncReply(im, ic)))
112         return False;
113     return True;
114 }
115
116 Private Bool
117 _XimExtSetEventMaskCallback(
118     Xim          xim,
119     INT16        len,
120     XPointer     data,
121     XPointer     call_data)
122 {
123     CARD16      *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
124     XIMID        imid = buf_s[0];
125     XICID        icid = buf_s[1];
126     Xim          im = (Xim)call_data;
127     Xic          ic;
128
129     if ((imid == im->private.proto.imid)
130      && (ic = _XimICOfXICID(im, icid))) {
131         (void)_XimProcExtSetEventMask(im, ic, (XPointer)&buf_s[2]);
132         return True;
133     }
134     return False;
135 }
136
137 #ifdef EXT_FORWARD
138 Private Bool
139 _XimProcExtForwardKeyEvent(
140     Xim          im,
141     Xic          ic,
142     XPointer     buf)
143 {
144     CARD8       *buf_b = (CARD8 *)buf;
145     CARD16      *buf_s = (CARD16 *)buf;
146     CARD32      *buf_l = (CARD32 *)buf;
147     XEvent       ev;
148     XKeyEvent   *kev = (XKeyEvent *)&ev;
149
150     bzero(&ev, sizeof(XEvent));
151     kev->send_event     = False;
152     kev->display        = im->core.display;
153     kev->serial         = buf_s[1];             /* sequence number */
154     kev->type           = buf_b[4] & 0x7f;      /* xEvent.u.u.type */
155     kev->keycode        = buf_b[5];             /* Keycode */
156     kev->state          = buf_s[3];             /* state */
157     kev->time           = buf_l[2];             /* time */
158
159     XPutBackEvent(im->core.display, &ev);
160
161     _XimRespSyncReply(ic, buf_s[0]);
162     MARK_FABRICATED(im);
163
164     return True;
165 }
166
167 Private Bool
168 _XimExtForwardKeyEventCallback(
169     Xim          xim,
170     INT16        len,
171     XPointer     data,
172     XPointer     call_data)
173 {
174     CARD16      *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
175     XIMID        imid = buf_s[0];
176     XICID        icid = buf_s[1];
177     Xim          im = (Xim)call_data;
178     Xic          ic;
179
180     if ((imid == im->private.proto.imid)
181      && (ic = _XimICOfXICID(im, icid))) {
182         (void)_XimProcExtForwardKeyEvent(im, ic, (XPointer)&buf_s[2]);
183         return True;
184     }
185     return False;
186 }
187
188 Private Bool
189 _XimExtForwardKeyEventCheck(
190     Xim          im,
191     INT16        len,
192     XPointer     data,
193     XPointer     arg)
194 {
195     Xic          ic  = (Xic)arg;
196     CARD16      *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
197     CARD8        major_opcode = *((CARD8 *)data);
198     CARD8        minor_opcode = *((CARD8 *)data + 1);
199     XIMID        imid = buf_s[0];
200     XICID        icid = buf_s[1];
201
202     if ((major_opcode == XIM_SYNC_REPLY)
203      && (minor_opcode == 0)
204      && (imid == im->private.proto.imid)
205      && (icid == ic->private.proto.icid))
206     if ((major_opcode == XIM_ERROR)
207      && (minor_opcode == 0)
208      && (buf_s[2] & XIM_IMID_VALID)
209      && (imid == im->private.proto.imid)
210      && (buf_s[2] & XIM_ICID_VALID)
211      && (icid == ic->private.proto.icid))
212         return True;
213     return False;
214 }
215
216 Public Bool
217 _XimExtForwardKeyEvent(
218     Xic          ic,
219     XKeyEvent   *ev,
220     Bool         sync)
221 {
222     Xim          im = (Xim) ic->core.im;
223     CARD32       buf32[BUFSIZE/4];
224     CARD8       *buf = (CARD8 *)buf32;
225     CARD8       *buf_b = &buf[XIM_HEADER_SIZE];
226     CARD16      *buf_s = (CARD16 *)buf_b;
227     CARD32      *buf_l = (CARD32 *)buf_b;
228     CARD32       reply32[BUFSIZE/4];
229     char        *reply = (char *)reply32;
230     XPointer    preply;
231     int         buf_size;
232     int         ret_code;
233     INT16       len;
234     int         idx;
235
236     if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) < 0)
237         return False;
238
239     buf_s[0] = im->private.proto.imid;          /* imid */
240     buf_s[1] = ic->private.proto.icid;          /* icid */
241     buf_s[2] = sync ? XimSYNCHRONUS : 0;        /* flag */
242     buf_s[3] = (CARD16)(((XAnyEvent *)ev)->serial & ((unsigned long) 0xffff));
243                                                 /* sequence number */
244     buf_b[8] = ev->type;                        /* xEvent.u.u.type */
245     buf_b[9] = ev->keycode;                     /* keycode */
246     buf_s[5] = ev->state;                       /* state */
247     buf_l[3] = ev->time;                        /* time */
248     len = sizeof(CARD16)                        /* sizeof imid */
249         + sizeof(CARD16)                        /* sizeof icid */
250         + sizeof(BITMASK16)                     /* sizeof flag */
251         + sizeof(CARD16)                        /* sizeof sequence number */
252         + sizeof(BYTE)                          /* sizeof xEvent.u.u.type */
253         + sizeof(BYTE)                          /* sizeof keycode */
254         + sizeof(CARD16)                        /* sizeof state */
255         + sizeof(CARD32);                       /* sizeof time */
256
257     _XimSetHeader((XPointer)buf,
258                 extensions[idx].major_opcode,
259                 extensions[idx].minor_opcode, &len);
260     if (!(_XimWrite(im, len, (XPointer)buf)))
261         return False;
262     _XimFlush(im);
263     if (sync) {
264         buf_size = BUFSIZE;
265         ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
266                                 _XimExtForwardKeyEventCheck, (XPointer)ic);
267         if(ret_code == XIM_TRUE) {
268             preply = reply;
269         } else if(ret_code == XIM_OVERFLOW) {
270             if(len <= 0) {
271                 preply = reply;
272             } else {
273                 buf_sizex = len;
274                 preply = (XPointer)Xmalloc(buf_size);
275                 ret_code = _XimRead(im, &len, preply, buf_size,
276                                 _XimExtForwardKeyEventCheck, (XPointer)ic);
277                 if(ret_code != XIM_TRUE) {
278                     Xfree(preply);
279                     return False;
280                 }
281             }
282         } else
283             return False;
284         buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
285         if (*((CARD8 *)preply) == XIM_ERROR) {
286             _XimProcError(im, 0, (XPointer)&buf_s[3]);
287             if(reply != preply)
288                 Xfree(preply);
289             return False;
290         }
291         if(reply != preply)
292             Xfree(preply);
293     }
294     return True;
295 }
296 #endif /* EXT_FORWARD */
297
298 Private int
299 _XimCheckExtensionListSize(void)
300 {
301     register int i;
302     int          len;
303     int          total = 0;
304     int          n = XIMNumber(extensions) - 1;
305
306     for (i = 0; i < n; i++) {
307         len = strlen(extensions[i].name);
308         extensions[i].name_len = len;
309         len += sizeof(BYTE);
310         total += len;
311     }
312     return total;
313 }
314
315 Private void
316 _XimSetExtensionList(
317     CARD8       *buf)
318 {
319     register int i;
320     int          len;
321     int          n = XIMNumber(extensions) - 1;
322
323     for (i = 0; i < n; i++) {
324         len = extensions[i].name_len;
325         buf[0] = (BYTE)len;
326         (void)strcpy((char *)&buf[1], extensions[i].name);
327         len += sizeof(BYTE);
328         buf += len;
329     }
330     return;
331 }
332
333 Private unsigned int
334 _XimCountNumberOfExtension(
335     INT16        total,
336     CARD8       *ext)
337 {
338     unsigned int n;
339     INT16        len;
340     INT16        min_len = sizeof(CARD8)
341                          + sizeof(CARD8)
342                          + sizeof(INT16);
343
344     n = 0;
345     while (total > min_len) {
346         len = *((INT16 *)(&ext[2]));
347         len += (min_len + XIM_PAD(len));
348         total -= len;
349         ext += len;
350         n++;
351     }
352     return n;
353 }
354
355 Private Bool
356 _XimParseExtensionList(
357     Xim                  im,
358     CARD16              *data)
359 {
360     int                  num = XIMNumber(extensions) - 1;
361     unsigned int         n;
362     CARD8               *buf;
363     register int         i;
364     register int         j;
365     INT16                len;
366
367     if (!(n = _XimCountNumberOfExtension(data[0], (CARD8 *)&data[1])))
368         return True;
369
370     buf = (CARD8 *)&data[1];;
371     for (i = 0; i < n; i++) {
372         len = *((INT16 *)(&buf[2]));
373         for (j = 0; j < num; j++) {
374             if (!(strncmp(extensions[j].name, (char *)&buf[4], len))) {
375                 extensions[j].major_opcode = buf[0];
376                 extensions[j].minor_opcode = buf[1];
377                 extensions[j].is_support   = True;
378                 break;
379             }
380         }
381         len += sizeof(CARD8)            /* sizeof major_opcode */
382              + sizeof(CARD8)            /* sizeof minor_opcode */
383              + sizeof(INT16)            /* sizeof length */
384              + XIM_PAD(len);            /* sizeof pad */
385         buf += len;
386     }
387
388     return True;
389 }
390
391 Private Bool
392 _XimQueryExtensionCheck(
393     Xim          im,
394     INT16        len,
395     XPointer     data,
396     XPointer     arg)
397 {
398     CARD16      *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
399     CARD8        major_opcode = *((CARD8 *)data);
400     CARD8        minor_opcode = *((CARD8 *)data + 1);
401     XIMID        imid = buf_s[0];
402
403     if ((major_opcode == XIM_QUERY_EXTENSION_REPLY)
404      && (minor_opcode == 0)
405      && (imid == im->private.proto.imid))
406         return True;
407     if ((major_opcode == XIM_ERROR)
408      && (minor_opcode == 0)
409      && (buf_s[2] & XIM_IMID_VALID)
410      && (imid == im->private.proto.imid))
411         return True;
412     return False;
413 }
414
415 Public Bool
416 _XimExtension(
417     Xim          im)
418 {
419     CARD8       *buf;
420     CARD16      *buf_s;
421     int          buf_len;
422     INT16        len;
423     CARD32       reply32[BUFSIZE/4];
424     char        *reply = (char *)reply32;
425     XPointer     preply;
426     int          buf_size;
427     int          ret_code;
428     int          idx;
429
430     if (!(len = _XimCheckExtensionListSize()))
431         return True;
432
433     buf_len = XIM_HEADER_SIZE
434             + sizeof(CARD16)
435             + sizeof(INT16)
436             + len
437             + XIM_PAD(len);
438
439     if (!(buf = (CARD8 *)Xmalloc(buf_len)))
440         return False;
441     buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
442
443     buf_s[0] = im->private.proto.imid;  /* imid */
444     buf_s[1] = len;                     /* length of Extensions */
445     _XimSetExtensionList((CARD8 *)&buf_s[2]);
446                                         /* extensions supported */
447     XIM_SET_PAD(&buf_s[2], len);        /* pad */
448     len += sizeof(CARD16)               /* sizeof imid */
449          + sizeof(INT16);               /* sizeof length of extensions */
450
451     _XimSetHeader((XPointer)buf, XIM_QUERY_EXTENSION, 0, &len);
452     if (!(_XimWrite(im, len, (XPointer)buf))) {
453         XFree(buf);
454         return False;
455     }
456     XFree(buf);
457     _XimFlush(im);
458     buf_size = BUFSIZE;
459     ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
460                                         _XimQueryExtensionCheck, 0);
461     if(ret_code == XIM_TRUE) {
462         preply = reply;
463     } else if(ret_code == XIM_OVERFLOW) {
464         if(len <= 0) {
465             preply = reply;
466         } else {
467             buf_size = len;
468             preply = (XPointer)Xmalloc(buf_size);
469             ret_code = _XimRead(im, &len, reply, buf_size,
470                                         _XimQueryExtensionCheck, 0);
471             if(ret_code != XIM_TRUE) {
472                 Xfree(preply);
473                 return False;
474             }
475         }
476     } else
477         return False;
478     buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
479     if (*((CARD8 *)preply) == XIM_ERROR) {
480         _XimProcError(im, 0, (XPointer)&buf_s[3]);
481         if(reply != preply)
482             Xfree(preply);
483         return False;
484     }
485
486     if (!(_XimParseExtensionList(im, &buf_s[1]))) {
487         if(reply != preply)
488             Xfree(preply);
489         return False;
490     }
491     if(reply != preply)
492         Xfree(preply);
493
494     if ((idx = _XimIsSupportExt(XIM_EXT_SET_EVENT_MASK_IDX)) >= 0)
495         _XimRegProtoIntrCallback(im,
496                 extensions[idx].major_opcode,
497                 extensions[idx].minor_opcode,
498                 _XimExtSetEventMaskCallback, (XPointer)im);
499 #ifdef EXT_FORWARD
500     if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) >= 0)
501         _XimRegProtoIntrCallback(im,
502                 extensions[idx].major_opcode,
503                 extensions[idx].minor_opcode,
504                 _XimExtForwardKeyEventCallback, (XPointer)im);
505 #endif
506
507     return True;
508 }
509
510 #ifdef EXT_MOVE
511 /* flag of ExtenArgCheck */
512 #define EXT_XNSPOTLOCATION      (1L<<0)
513
514 /* macro for ExtenArgCheck */
515 #define SET_EXT_XNSPOTLOCATION(flag) (flag |= EXT_XNSPOTLOCATION)
516 #define IS_EXT_XNSPOTLOCATION(flag)  (flag & EXT_XNSPOTLOCATION)
517
518 /* length of XPoint attribute */
519 #define XIM_Xpoint_length       12
520
521 Private Bool
522 _XimExtMove(
523     Xim          im,
524     Xic          ic,
525     CARD16       x,
526     CARD16       y)
527 {
528     CARD32       buf32[BUFSIZE/4];
529     CARD8       *buf = (CARD8 *)buf32;
530     CARD16      *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
531     INT16        len;
532     int         idx;
533
534     if ((idx = _XimIsSupportExt(XIM_EXT_MOVE_IDX)) < 0)
535         return False;
536
537     buf_s[0] = im->private.proto.imid;  /* imid */
538     buf_s[1] = ic->private.proto.icid;  /* icid */
539     buf_s[2] = x;                       /* X */
540     buf_s[3] = y;                       /* Y */
541     len = sizeof(CARD16)                /* sizeof imid */
542         + sizeof(CARD16)                /* sizeof icid */
543         + sizeof(INT16)                 /* sizeof X */
544         + sizeof(INT16);                /* sizeof Y */
545
546     _XimSetHeader((XPointer)buf, extensions[idx].major_opcode,
547                         extensions[idx].minor_opcode, &len);
548     if (!(_XimWrite(im, len, (XPointer)buf)))
549         return False;
550     _XimFlush(im);
551     return True;
552 }
553
554 Public BITMASK32
555 _XimExtenArgCheck(
556     XIMArg      *arg)
557 {
558     CARD32      flag = 0L;
559     if (!strcmp(arg->name, XNSpotLocation))
560         SET_EXT_XNSPOTLOCATION(flag);
561     return flag;
562 }
563
564 Public Bool
565 _XimExtenMove(
566     Xim          im,
567     Xic          ic,
568     CARD32       flag,
569     CARD16      *buf,
570     INT16        length)
571 {
572     if ((IS_EXT_XNSPOTLOCATION(flag)) && (length == XIM_Xpoint_length))
573         return _XimExtMove(im, ic, buf[4], buf[5]);
574     return False;
575 }
576 #endif /* EXT_MOVE */