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