imDefLkup.c revision b4ee4795
1/******************************************************************
2
3           Copyright 1992, 1993, 1994 by FUJITSU LIMITED
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and
8that both that copyright notice and this permission notice appear
9in supporting documentation, and that the name of FUJITSU LIMITED
10not be used in advertising or publicity pertaining to distribution
11of the software without specific, written prior permission.
12FUJITSU LIMITED makes no representations about the suitability of
13this software for any purpose.
14It is provided "as is" without express or implied warranty.
15
16FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22PERFORMANCE 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#define  NEED_EVENTS
34#include "Xlibint.h"
35#include "Xlcint.h"
36#include "Ximint.h"
37
38Public Xic
39_XimICOfXICID(
40    Xim		  im,
41    XICID	  icid)
42{
43    Xic		  pic;
44
45    for (pic = (Xic)im->core.ic_chain; pic; pic = (Xic)pic->core.next) {
46	if (pic->private.proto.icid == icid)
47	    return pic;
48    }
49    return (Xic)0;
50}
51
52Private void
53_XimProcIMSetEventMask(
54    Xim		 im,
55    XPointer	 buf)
56{
57    EVENTMASK	*buf_l = (EVENTMASK *)buf;
58
59    im->private.proto.forward_event_mask     = buf_l[0];
60    im->private.proto.synchronous_event_mask = buf_l[1];
61    return;
62}
63
64Private void
65_XimProcICSetEventMask(
66    Xic		 ic,
67    XPointer	 buf)
68{
69    EVENTMASK	*buf_l = (EVENTMASK *)buf;
70
71    ic->private.proto.forward_event_mask     = buf_l[0];
72    ic->private.proto.synchronous_event_mask = buf_l[1];
73    _XimReregisterFilter(ic);
74    return;
75}
76
77Public Bool
78_XimSetEventMaskCallback(
79    Xim		 xim,
80    INT16	 len,
81    XPointer	 data,
82    XPointer	 call_data)
83{
84    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
85    XIMID        imid = buf_s[0];
86    XICID        icid = buf_s[1];
87    Xim		 im = (Xim)call_data;
88    Xic		 ic;
89
90    if (imid == im->private.proto.imid) {
91	if (icid) {
92	    ic = _XimICOfXICID(im, icid);
93	    _XimProcICSetEventMask(ic, (XPointer)&buf_s[2]);
94	} else {
95	    _XimProcIMSetEventMask(im, (XPointer)&buf_s[2]);
96	}
97	return True;
98    }
99    return False;
100}
101
102Private Bool
103_XimSyncCheck(
104    Xim          im,
105    INT16        len,
106    XPointer	 data,
107    XPointer     arg)
108{
109    Xic		 ic  = (Xic)arg;
110    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
111    CARD8	 major_opcode = *((CARD8 *)data);
112    CARD8	 minor_opcode = *((CARD8 *)data + 1);
113    XIMID	 imid = buf_s[0];
114    XICID	 icid = buf_s[1];
115
116    if ((major_opcode == XIM_SYNC_REPLY)
117     && (minor_opcode == 0)
118     && (imid == im->private.proto.imid)
119     && (icid == ic->private.proto.icid))
120	return True;
121    if ((major_opcode == XIM_ERROR)
122     && (minor_opcode == 0)
123     && (buf_s[2] & XIM_IMID_VALID)
124     && (imid == im->private.proto.imid)
125     && (buf_s[2] & XIM_ICID_VALID)
126     && (icid == ic->private.proto.icid))
127	return True;
128    return False;
129}
130
131Public Bool
132_XimSync(
133    Xim		 im,
134    Xic		 ic)
135{
136    CARD32	 buf32[BUFSIZE/4];
137    CARD8	*buf = (CARD8 *)buf32;
138    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
139    INT16	 len;
140    CARD32	 reply32[BUFSIZE/4];
141    char	*reply = (char *)reply32;
142    XPointer	 preply;
143    int		 buf_size;
144    int		 ret_code;
145
146    buf_s[0] = im->private.proto.imid;		/* imid */
147    buf_s[1] = ic->private.proto.icid;		/* icid */
148
149    len = sizeof(CARD16)			/* sizeof imid */
150	+ sizeof(CARD16);			/* sizeof icid */
151
152    _XimSetHeader((XPointer)buf, XIM_SYNC, 0, &len);
153    if (!(_XimWrite(im, len, (XPointer)buf)))
154	return False;
155    _XimFlush(im);
156    buf_size = BUFSIZE;
157    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
158					_XimSyncCheck, (XPointer)ic);
159    if(ret_code == XIM_TRUE) {
160	preply = reply;
161    } else if(ret_code == XIM_OVERFLOW) {
162	if(len <= 0) {
163	    preply = reply;
164	} else {
165	    buf_size = len;
166	    preply = (XPointer)Xmalloc(len);
167	    ret_code = _XimRead(im, &len, preply, buf_size,
168					_XimSyncCheck, (XPointer)ic);
169	    if(ret_code != XIM_TRUE) {
170		Xfree(preply);
171		return False;
172	    }
173	}
174    } else {
175	return False;
176    }
177    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
178    if (*((CARD8 *)preply) == XIM_ERROR) {
179	_XimProcError(im, 0, (XPointer)&buf_s[3]);
180	if(reply != preply)
181	    Xfree(preply);
182	return False;
183    }
184    if(reply != preply)
185	Xfree(preply);
186    return True;
187}
188
189Public Bool
190_XimProcSyncReply(
191    Xim		 im,
192    Xic		 ic)
193{
194    CARD32	 buf32[BUFSIZE/4];
195    CARD8	*buf = (CARD8 *)buf32;
196    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
197    INT16	 len;
198
199    buf_s[0] = im->private.proto.imid;		/* imid */
200    buf_s[1] = ic->private.proto.icid;		/* icid */
201
202    len = sizeof(CARD16)			/* sizeof imid */
203	+ sizeof(CARD16);			/* sizeof icid */
204
205    _XimSetHeader((XPointer)buf, XIM_SYNC_REPLY, 0, &len);
206    if (!(_XimWrite(im, len, (XPointer)buf)))
207	return False;
208    _XimFlush(im);
209    return True;
210}
211
212Public Bool
213_XimRespSyncReply(
214    Xic		 ic,
215    BITMASK16	 mode)
216{
217    if (mode & XimSYNCHRONUS) /* SYNC Request */ {
218	if (IS_FOCUSED(ic))
219	    MARK_NEED_SYNC_REPLY(ic);
220	else
221	    _XimProcSyncReply((Xim)ic->core.im, ic);
222    }
223
224    return True;
225}
226
227Public Bool
228_XimSyncCallback(
229    Xim		 xim,
230    INT16	 len,
231    XPointer	 data,
232    XPointer	 call_data)
233{
234    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
235    XIMID        imid = buf_s[0];
236    XICID        icid = buf_s[1];
237    Xim		 im = (Xim)call_data;
238    Xic		 ic;
239
240    if ((imid == im->private.proto.imid)
241     && (ic = _XimICOfXICID(im, icid))) {
242	(void)_XimProcSyncReply(im, ic);
243	return True;
244    }
245    return False;
246}
247
248Private INT16
249_XimSetEventToWire(
250    XEvent	*ev,
251    xEvent	*event)
252{
253    if (!(_XimProtoEventToWire(ev, event, False)))
254	return 0;
255    event->u.u.sequenceNumber =
256		((XAnyEvent *)ev)->serial & (unsigned long)0xffff;
257    return sz_xEvent;
258}
259
260Private Bool
261_XimForwardEventCore(
262    Xic		 ic,
263    XEvent	*ev,
264    Bool	 sync)
265{
266    Xim		 im = (Xim)ic->core.im;
267    CARD32	 buf32[BUFSIZE/4];
268    CARD8	*buf = (CARD8 *)buf32;
269    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
270    CARD32	 reply32[BUFSIZE/4];
271    char	*reply = (char *)reply32;
272    XPointer	 preply;
273    int		 buf_size;
274    int		 ret_code;
275    INT16	 len;
276
277    if (!(len = _XimSetEventToWire(ev, (xEvent *)&buf_s[4])))
278	return False;				/* X event */
279
280    buf_s[0] = im->private.proto.imid;		/* imid */
281    buf_s[1] = ic->private.proto.icid;		/* icid */
282    buf_s[2] = sync ? XimSYNCHRONUS : 0;	/* flag */
283    buf_s[3] =
284        (CARD16)((((XAnyEvent *)ev)->serial & ~((unsigned long)0xffff)) >> 16);
285						/* serial number */
286
287    len += sizeof(CARD16)			/* sizeof imid */
288	 + sizeof(CARD16)			/* sizeof icid */
289	 + sizeof(BITMASK16)			/* sizeof flag */
290	 + sizeof(CARD16);			/* sizeof serila number */
291
292    _XimSetHeader((XPointer)buf, XIM_FORWARD_EVENT, 0, &len);
293    if (!(_XimWrite(im, len, (XPointer)buf)))
294	return False;
295    _XimFlush(im);
296
297    if (sync) {
298	buf_size = BUFSIZE;
299	ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
300					_XimSyncCheck, (XPointer)ic);
301	if(ret_code == XIM_TRUE) {
302	    preply = reply;
303	} else if(ret_code == XIM_OVERFLOW) {
304	    if(len <= 0) {
305		preply = reply;
306	    } else {
307		buf_size = len;
308		preply = (XPointer)Xmalloc(len);
309		ret_code = _XimRead(im, &len, preply, buf_size,
310					_XimSyncCheck, (XPointer)ic);
311		if(ret_code != XIM_TRUE) {
312		    Xfree(preply);
313		    return False;
314		}
315	    }
316	} else {
317	    return False;
318	}
319	buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
320	if (*((CARD8 *)preply) == XIM_ERROR) {
321	    _XimProcError(im, 0, (XPointer)&buf_s[3]);
322	    if(reply != preply)
323		Xfree(preply);
324	    return False;
325	}
326	if(reply != preply)
327	    Xfree(preply);
328    }
329    return True;
330}
331
332Public Bool
333_XimForwardEvent(
334    Xic		 ic,
335    XEvent	*ev,
336    Bool	 sync)
337{
338#ifdef EXT_FORWARD
339    if (((ev->type == KeyPress) || (ev->type == KeyRelease)))
340	if (_XimExtForwardKeyEvent(ic, (XKeyEvent *)ev, sync))
341	    return True;
342#endif
343    return _XimForwardEventCore(ic, ev, sync);
344}
345
346Private void
347_XimProcEvent(
348    Display		*d,
349    Xic			 ic,
350    XEvent		*ev,
351    CARD16		*buf)
352{
353    INT16	 serial = buf[0];
354    xEvent	*xev = (xEvent *)&buf[1];
355
356    _XimProtoWireToEvent(ev, xev, False);
357    ev->xany.serial |= serial << 16;
358    ev->xany.send_event = False;
359    ev->xany.display = d;
360    MARK_FABLICATED(ic);
361    return;
362}
363
364Private Bool
365_XimForwardEventRecv(
366    Xim		 im,
367    Xic		 ic,
368    XPointer	 buf)
369{
370    CARD16	*buf_s = (CARD16 *)buf;
371    Display	*d = im->core.display;
372    XEvent	 ev;
373
374    _XimProcEvent(d, ic, &ev, &buf_s[1]);
375
376    (void)_XimRespSyncReply(ic, buf_s[0]);
377
378    XPutBackEvent(d, &ev);
379
380    return True;
381}
382
383Public Bool
384_XimForwardEventCallback(
385    Xim		 xim,
386    INT16	 len,
387    XPointer	 data,
388    XPointer	 call_data)
389{
390    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
391    XIMID        imid = buf_s[0];
392    XICID        icid = buf_s[1];
393    Xim		 im = (Xim)call_data;
394    Xic		 ic;
395
396    if ((imid == im->private.proto.imid)
397     && (ic = _XimICOfXICID(im, icid))) {
398	(void)_XimForwardEventRecv(im, ic, (XPointer)&buf_s[2]);
399	return True;
400    }
401    return False;
402}
403
404Private Bool
405_XimRegisterTriggerkey(
406    Xim			 im,
407    XPointer		 buf)
408{
409    CARD32		*buf_l = (CARD32 *)buf;
410    CARD32		 len;
411    CARD32 		*key;
412
413    if (IS_DYNAMIC_EVENT_FLOW(im))	/* already Dynamic event flow mode */
414	return True;
415
416    /*
417     *  register onkeylist
418     */
419
420    len = buf_l[0];				/* length of on-keys */
421    len += sizeof(INT32);			/* sizeof length of on-keys */
422
423    if (!(key = (CARD32 *)Xmalloc(len))) {
424	_XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
425	return False;
426    }
427    memcpy((char *)key, (char *)buf_l, len);
428    im->private.proto.im_onkeylist = key;
429
430    MARK_DYNAMIC_EVENT_FLOW(im);
431
432    /*
433     *  register offkeylist
434     */
435
436    buf_l = (CARD32 *)((char *)buf + len);
437    len = buf_l[0];				/* length of off-keys */
438    len += sizeof(INT32);			/* sizeof length of off-keys */
439
440    if (!(key = (CARD32 *)Xmalloc(len))) {
441	_XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
442	return False;
443    }
444
445    memcpy((char *)key, (char *)buf_l, len);
446    im->private.proto.im_offkeylist = key;
447
448    return True;
449}
450
451Public Bool
452_XimRegisterTriggerKeysCallback(
453    Xim		 xim,
454    INT16	 len,
455    XPointer	 data,
456    XPointer	 call_data)
457{
458    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
459    Xim		 im = (Xim)call_data;
460
461    (void )_XimRegisterTriggerkey(im, (XPointer)&buf_s[2]);
462    return True;
463}
464
465Public EVENTMASK
466_XimGetWindowEventmask(
467    Xic		 ic)
468{
469    Xim			im = (Xim )ic->core.im;
470    XWindowAttributes	atr;
471
472    if (!XGetWindowAttributes(im->core.display, ic->core.focus_window, &atr))
473	return 0;
474    return (EVENTMASK)atr.your_event_mask;
475}
476
477
478Private Bool
479_XimTriggerNotifyCheck(
480    Xim          im,
481    INT16        len,
482    XPointer	 data,
483    XPointer     arg)
484{
485    Xic		 ic  = (Xic)arg;
486    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
487    CARD8	 major_opcode = *((CARD8 *)data);
488    CARD8	 minor_opcode = *((CARD8 *)data + 1);
489    XIMID	 imid = buf_s[0];
490    XICID	 icid = buf_s[1];
491
492    if ((major_opcode == XIM_TRIGGER_NOTIFY_REPLY)
493     && (minor_opcode == 0)
494     && (imid == im->private.proto.imid)
495     && (icid == ic->private.proto.icid))
496	return True;
497    if ((major_opcode == XIM_ERROR)
498     && (minor_opcode == 0)
499     && (buf_s[2] & XIM_IMID_VALID)
500     && (imid == im->private.proto.imid)
501     && (buf_s[2] & XIM_ICID_VALID)
502     && (icid == ic->private.proto.icid))
503	return True;
504    return False;
505}
506
507Public Bool
508_XimTriggerNotify(
509    Xim		 im,
510    Xic		 ic,
511    int		 mode,
512    CARD32	 idx)
513{
514    CARD32	 buf32[BUFSIZE/4];
515    CARD8	*buf = (CARD8 *)buf32;
516    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
517    CARD32	*buf_l = (CARD32 *)&buf[XIM_HEADER_SIZE];
518    CARD32	 reply32[BUFSIZE/4];
519    char	*reply = (char *)reply32;
520    XPointer	 preply;
521    int		 buf_size;
522    int		 ret_code;
523    INT16	 len;
524    EVENTMASK	 mask = _XimGetWindowEventmask(ic);
525
526    buf_s[0] = im->private.proto.imid;	/* imid */
527    buf_s[1] = ic->private.proto.icid;	/* icid */
528    buf_l[1] = mode;			/* flag */
529    buf_l[2] = idx;			/* index of keys list */
530    buf_l[3] = mask;			/* select-event-mask */
531
532    len = sizeof(CARD16)		/* sizeof imid */
533	+ sizeof(CARD16)		/* sizeof icid */
534	+ sizeof(CARD32)		/* sizeof flag */
535	+ sizeof(CARD32)		/* sizeof index of key list */
536	+ sizeof(EVENTMASK);		/* sizeof select-event-mask */
537
538    _XimSetHeader((XPointer)buf, XIM_TRIGGER_NOTIFY, 0, &len);
539    if (!(_XimWrite(im, len, (XPointer)buf)))
540	return False;
541    _XimFlush(im);
542    buf_size = BUFSIZE;
543    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
544				_XimTriggerNotifyCheck, (XPointer)ic);
545    if(ret_code == XIM_TRUE) {
546	preply = reply;
547    } else if(ret_code == XIM_OVERFLOW) {
548	if(len <= 0) {
549	    preply = reply;
550	} else {
551	    buf_size = len;
552	    preply = (XPointer)Xmalloc(len);
553	    ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
554				_XimTriggerNotifyCheck, (XPointer)ic);
555	    if(ret_code != XIM_TRUE) {
556		Xfree(preply);
557		return False;
558	    }
559	}
560    } else {
561	return False;
562    }
563    buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
564    if (*((CARD8 *)preply) == XIM_ERROR) {
565	_XimProcError(im, 0, (XPointer)&buf_s[3]);
566	if(reply != preply)
567	    Xfree(preply);
568	return False;
569    }
570    if(reply != preply)
571	Xfree(preply);
572    return True;
573}
574
575Private Bool
576_XimRegCommitInfo(
577    Xic			 ic,
578    char		*string,
579    int			 string_len,
580    KeySym		*keysym,
581    int			 keysym_len)
582{
583    XimCommitInfo	info;
584
585    if (!(info = (XimCommitInfo)Xmalloc(sizeof(XimCommitInfoRec))))
586	return False;
587    info->string	= string;
588    info->string_len	= string_len;
589    info->keysym	= keysym;
590    info->keysym_len	= keysym_len;
591    info->next = ic->private.proto.commit_info;
592    ic->private.proto.commit_info = info;
593    return True;
594}
595
596Private void
597_XimUnregCommitInfo(
598    Xic			ic)
599{
600    XimCommitInfo	info;
601
602    if (!(info = ic->private.proto.commit_info))
603	return;
604
605    if (info->string)
606	Xfree(info->string);
607    if (info->keysym)
608	Xfree(info->keysym);
609    ic->private.proto.commit_info = info->next;
610    Xfree(info);
611    return;
612}
613
614Public void
615_XimFreeCommitInfo(
616    Xic			ic)
617{
618    while (ic->private.proto.commit_info)
619	_XimUnregCommitInfo(ic);
620    return;
621}
622
623Private Bool
624_XimProcKeySym(
625    Xic			  ic,
626    CARD32		  sym,
627    KeySym		**xim_keysym,
628    int			 *xim_keysym_len)
629{
630    Xim			 im = (Xim)ic->core.im;
631
632    if (!(*xim_keysym = (KeySym *)Xmalloc(sizeof(KeySym)))) {
633	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
634	return False;
635    }
636
637    **xim_keysym = (KeySym)sym;
638    *xim_keysym_len = 1;
639
640    return True;
641}
642
643Private Bool
644_XimProcCommit(
645    Xic		  ic,
646    BYTE	 *buf,
647    int		  len,
648    char	**xim_string,
649    int		 *xim_string_len)
650{
651    Xim		 im = (Xim)ic->core.im;
652    char	*string;
653
654    if (!(string = (char *)Xmalloc(len + 1))) {
655	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
656	return False;
657    }
658
659    (void)memcpy(string, (char *)buf, len);
660    string[len] = '\0';
661
662    *xim_string = string;
663    *xim_string_len = len;
664    return True;
665}
666
667Private Bool
668_XimCommitRecv(
669    Xim		 im,
670    Xic		 ic,
671    XPointer	 buf)
672{
673    CARD16	*buf_s = (CARD16 *)buf;
674    BITMASK16	 flag = buf_s[0];
675    XKeyEvent	 ev;
676    char	*string = NULL;
677    int		 string_len = 0;
678    KeySym	*keysym = NULL;
679    int		 keysym_len = 0;
680
681    if ((flag & XimLookupBoth) == XimLookupChars) {
682	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2],
683			 		(int)buf_s[1], &string, &string_len)))
684	    return False;
685
686    } else if ((flag & XimLookupBoth) == XimLookupKeySym) {
687	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
688	    return False;
689
690    } else if ((flag & XimLookupBoth) == XimLookupBoth) {
691	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
692	    return False;
693
694	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5],
695			 		(int)buf_s[4], &string, &string_len)))
696	    return False;
697    }
698
699    if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) {
700	if (string)
701	    Xfree(string);
702	if (keysym)
703	    Xfree(keysym);
704	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
705	return False;
706    }
707
708    (void)_XimRespSyncReply(ic, flag);
709
710    MARK_FABLICATED(ic);
711
712    ev.type = KeyPress;
713    ev.send_event = False;
714    ev.display = im->core.display;
715    ev.window = ic->core.focus_window;
716    ev.keycode = 0;
717    ev.state = 0;
718
719    XPutBackEvent(im->core.display, (XEvent *)&ev);
720
721    return True;
722}
723
724Public Bool
725_XimCommitCallback(
726    Xim		 xim,
727    INT16	 len,
728    XPointer	 data,
729    XPointer	 call_data)
730{
731    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
732    XIMID        imid = buf_s[0];
733    XICID        icid = buf_s[1];
734    Xim		 im = (Xim)call_data;
735    Xic		 ic;
736
737    if ((imid == im->private.proto.imid)
738     && (ic = _XimICOfXICID(im, icid))) {
739	(void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]);
740	return True;
741    }
742    return False;
743}
744
745Public void
746_XimProcError(
747    Xim		 im,
748    Xic		 ic,
749    XPointer	 data)
750{
751    return;
752}
753
754Public Bool
755_XimErrorCallback(
756    Xim		 xim,
757    INT16	 len,
758    XPointer	 data,
759    XPointer	 call_data)
760{
761    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
762    BITMASK16	 flag = buf_s[2];
763    XIMID        imid;
764    XICID        icid;
765    Xim		 im = (Xim)call_data;
766    Xic		 ic = NULL;
767
768    if (flag & XIM_IMID_VALID) {
769	imid = buf_s[0];
770	if (imid != im->private.proto.imid)
771	    return False;
772    }
773    if (flag & XIM_ICID_VALID) {
774	icid = buf_s[1];
775	if (!(ic = _XimICOfXICID(im, icid)))
776	    return False;
777    }
778    _XimProcError(im, ic, (XPointer)&buf_s[3]);
779
780    return True;
781}
782
783Public Bool
784_XimError(
785    Xim		 im,
786    Xic		 ic,
787    CARD16	 error_code,
788    INT16	 detail_length,
789    CARD16	 type,
790    char	*detail)
791{
792    CARD32	 buf32[BUFSIZE/4];
793    CARD8	*buf = (CARD8 *)buf32;
794    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
795    INT16	 len = 0;
796
797    buf_s[0] = im->private.proto.imid;	/* imid */
798    buf_s[2] = XIM_IMID_VALID;		/* flag */
799    if (ic) {
800    	buf_s[1] = ic->private.proto.icid;	/* icid */
801	buf_s[2] |= XIM_ICID_VALID;		/* flag */
802    }
803    buf_s[3] = error_code;			/* Error Code */
804    buf_s[4] = detail_length;			/* length of error detail */
805    buf_s[5] = type;				/* type of error detail */
806
807    if (detail_length && detail) {
808	len = detail_length;
809	memcpy((char *)&buf_s[6], detail, len);
810	XIM_SET_PAD(&buf_s[6], len);
811    }
812
813    len += sizeof(CARD16)		/* sizeof imid */
814	 + sizeof(CARD16)		/* sizeof icid */
815	 + sizeof(BITMASK16)		/* sizeof flag */
816	 + sizeof(CARD16)		/* sizeof error_code */
817	 + sizeof(INT16)		/* sizeof length of detail */
818	 + sizeof(CARD16);		/* sizeof type */
819
820    _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len);
821    if (!(_XimWrite(im, len, (XPointer)buf)))
822	return False;
823    _XimFlush(im);
824    return True;
825}
826
827Private int
828_Ximctsconvert(
829    XlcConv	 conv,
830    char	*from,
831    int		 from_len,
832    char	*to,
833    int		 to_len,
834    Status	*state)
835{
836    int		 from_left;
837    int		 to_left;
838    int		 from_savelen;
839    int		 to_savelen;
840    int		 from_cnvlen;
841    int		 to_cnvlen;
842    char	*from_buf;
843    char	*to_buf;
844    char	 scratchbuf[BUFSIZ];
845    Status	 tmp_state;
846
847    if (!state)
848	state = &tmp_state;
849
850    if (!conv || !from || !from_len) {
851	*state = XLookupNone;
852	return 0;
853    }
854
855    /* Reset the converter.  The CompoundText at 'from' starts in
856       initial state.  */
857    _XlcResetConverter(conv);
858
859    from_left = from_len;
860    to_left = BUFSIZ;
861    from_cnvlen = 0;
862    to_cnvlen = 0;
863    for (;;) {
864	from_buf = &from[from_cnvlen];
865	from_savelen = from_left;
866	to_buf = &scratchbuf[to_cnvlen];
867	to_savelen = to_left;
868	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
869				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
870	    *state = XLookupNone;
871	    return 0;
872	}
873	from_cnvlen += (from_savelen - from_left);
874	to_cnvlen += (to_savelen - to_left);
875	if (from_left == 0) {
876	    if (!to_cnvlen) {
877		*state = XLookupNone;
878		return 0;
879           }
880	   break;
881	}
882    }
883
884    if (!to || !to_len || (to_len < to_cnvlen)) {
885       *state = XBufferOverflow;
886    } else {
887       memcpy(to, scratchbuf, to_cnvlen);
888       *state = XLookupChars;
889    }
890    return to_cnvlen;
891}
892
893Public int
894_Ximctstombs(XIM xim, char *from, int from_len,
895	     char *to, int to_len, Status *state)
896{
897    return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv,
898			  from, from_len, to, to_len, state);
899}
900
901Public int
902_Ximctstowcs(
903    XIM		 xim,
904    char	*from,
905    int		 from_len,
906    wchar_t	*to,
907    int		 to_len,
908    Status	*state)
909{
910    Xim		 im = (Xim)xim;
911    XlcConv	 conv = im->private.proto.ctow_conv;
912    int		 from_left;
913    int		 to_left;
914    int		 from_savelen;
915    int		 to_savelen;
916    int		 from_cnvlen;
917    int		 to_cnvlen;
918    char	*from_buf;
919    wchar_t	*to_buf;
920    wchar_t	 scratchbuf[BUFSIZ];
921    Status	 tmp_state;
922
923    if (!state)
924	state = &tmp_state;
925
926    if (!conv || !from || !from_len) {
927	*state = XLookupNone;
928	return 0;
929    }
930
931    /* Reset the converter.  The CompoundText at 'from' starts in
932       initial state.  */
933    _XlcResetConverter(conv);
934
935    from_left = from_len;
936    to_left = BUFSIZ;
937    from_cnvlen = 0;
938    to_cnvlen = 0;
939    for (;;) {
940	from_buf = &from[from_cnvlen];
941       from_savelen = from_left;
942       to_buf = &scratchbuf[to_cnvlen];
943       to_savelen = to_left;
944	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
945				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
946	    *state = XLookupNone;
947	    return 0;
948	}
949	from_cnvlen += (from_savelen - from_left);
950       to_cnvlen += (to_savelen - to_left);
951	if (from_left == 0) {
952           if (!to_cnvlen){
953		*state = XLookupNone;
954               return 0;
955           }
956	    break;
957	}
958    }
959
960    if (!to || !to_len || (to_len < to_cnvlen)) {
961       *state = XBufferOverflow;
962    } else {
963       memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t));
964       *state = XLookupChars;
965    }
966    return to_cnvlen;
967}
968
969Public int
970_Ximctstoutf8(
971    XIM		 xim,
972    char	*from,
973    int		 from_len,
974    char	*to,
975    int		 to_len,
976    Status	*state)
977{
978    return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv,
979			  from, from_len, to, to_len, state);
980}
981
982Public int
983_XimProtoMbLookupString(
984    XIC			 xic,
985    XKeyEvent		*ev,
986    char		*buffer,
987    int			 bytes,
988    KeySym		*keysym,
989    Status		*state)
990{
991    Xic			 ic = (Xic)xic;
992    Xim			 im = (Xim)ic->core.im;
993    int			 ret;
994    Status		 tmp_state;
995    XimCommitInfo	 info;
996
997    if (!IS_SERVER_CONNECTED(im))
998	return 0;
999
1000    if (!state)
1001	state = &tmp_state;
1002
1003    if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */
1004	if (!(info = ic->private.proto.commit_info)) {
1005	    *state = XLookupNone;
1006	    return 0;
1007	}
1008
1009	ret = im->methods->ctstombs((XIM)im, info->string,
1010			 	info->string_len, buffer, bytes, state);
1011	if (*state == XBufferOverflow)
1012            return ret;
1013	if (keysym && (info->keysym && *(info->keysym))) {
1014	    *keysym = *(info->keysym);
1015	    if (*state == XLookupChars)
1016		*state = XLookupBoth;
1017	    else
1018		*state = XLookupKeySym;
1019	}
1020	_XimUnregCommitInfo(ic);
1021
1022    } else  if (ev->type == KeyPress) {
1023	ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
1024	if (ret > 0) {
1025           if (ret > bytes)
1026               *state = XBufferOverflow;
1027           else if (keysym && *keysym != NoSymbol)
1028		*state = XLookupBoth;
1029	    else
1030		*state = XLookupChars;
1031	} else {
1032	    if (keysym && *keysym != NoSymbol)
1033		*state = XLookupKeySym;
1034	    else
1035		*state = XLookupNone;
1036	}
1037    } else {
1038	*state = XLookupNone;
1039	ret = 0;
1040    }
1041
1042    return ret;
1043}
1044
1045Public int
1046_XimProtoWcLookupString(
1047    XIC			 xic,
1048    XKeyEvent		*ev,
1049    wchar_t		*buffer,
1050    int			 bytes,
1051    KeySym		*keysym,
1052    Status		*state)
1053{
1054    Xic			 ic = (Xic)xic;
1055    Xim			 im = (Xim)ic->core.im;
1056    int			 ret;
1057    Status		 tmp_state;
1058    XimCommitInfo	 info;
1059
1060    if (!IS_SERVER_CONNECTED(im))
1061	return 0;
1062
1063    if (!state)
1064	state = &tmp_state;
1065
1066    if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
1067	if (!(info = ic->private.proto.commit_info)) {
1068           *state = XLookupNone;
1069	    return 0;
1070	}
1071
1072	ret = im->methods->ctstowcs((XIM)im, info->string,
1073			 	info->string_len, buffer, bytes, state);
1074	if (*state == XBufferOverflow)
1075           return ret;
1076	if (keysym && (info->keysym && *(info->keysym))) {
1077	    *keysym = *(info->keysym);
1078	    if (*state == XLookupChars)
1079		*state = XLookupBoth;
1080	    else
1081		*state = XLookupKeySym;
1082	}
1083	_XimUnregCommitInfo(ic);
1084
1085    } else if (ev->type == KeyPress) {
1086	ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
1087	if (ret > 0) {
1088           if (ret > bytes)
1089               *state = XBufferOverflow;
1090           else if (keysym && *keysym != NoSymbol)
1091		*state = XLookupBoth;
1092	    else
1093		*state = XLookupChars;
1094	} else {
1095	    if (keysym && *keysym != NoSymbol)
1096		*state = XLookupKeySym;
1097	    else
1098		*state = XLookupNone;
1099	}
1100    } else {
1101	*state = XLookupNone;
1102	ret = 0;
1103    }
1104
1105    return ret;
1106}
1107
1108Public int
1109_XimProtoUtf8LookupString(
1110    XIC			 xic,
1111    XKeyEvent		*ev,
1112    char		*buffer,
1113    int			 bytes,
1114    KeySym		*keysym,
1115    Status		*state)
1116{
1117    Xic			 ic = (Xic)xic;
1118    Xim			 im = (Xim)ic->core.im;
1119    int			 ret;
1120    Status		 tmp_state;
1121    XimCommitInfo	 info;
1122
1123    if (!IS_SERVER_CONNECTED(im))
1124	return 0;
1125
1126    if (!state)
1127	state = &tmp_state;
1128
1129    if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
1130	if (!(info = ic->private.proto.commit_info)) {
1131           *state = XLookupNone;
1132	    return 0;
1133	}
1134
1135	ret = im->methods->ctstoutf8((XIM)im, info->string,
1136			 	info->string_len, buffer, bytes, state);
1137	if (*state == XBufferOverflow)
1138           return ret;
1139	if (keysym && (info->keysym && *(info->keysym))) {
1140	    *keysym = *(info->keysym);
1141	    if (*state == XLookupChars)
1142		*state = XLookupBoth;
1143	    else
1144		*state = XLookupKeySym;
1145	}
1146	_XimUnregCommitInfo(ic);
1147
1148    } else if (ev->type == KeyPress) {
1149	ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
1150	if (ret > 0) {
1151           if (ret > bytes)
1152               *state = XBufferOverflow;
1153           else if (keysym && *keysym != NoSymbol)
1154		*state = XLookupBoth;
1155	    else
1156		*state = XLookupChars;
1157	} else {
1158	    if (keysym && *keysym != NoSymbol)
1159		*state = XLookupKeySym;
1160	    else
1161		*state = XLookupNone;
1162	}
1163    } else {
1164	*state = XLookupNone;
1165	ret = 0;
1166    }
1167
1168    return ret;
1169}
1170