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