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