imDefLkup.c revision 818534a1
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    if (info->string)
603	Xfree(info->string);
604    if (info->keysym)
605	Xfree(info->keysym);
606    ic->private.proto.commit_info = info->next;
607    Xfree(info);
608    return;
609}
610
611void
612_XimFreeCommitInfo(
613    Xic			ic)
614{
615    while (ic->private.proto.commit_info)
616	_XimUnregCommitInfo(ic);
617    return;
618}
619
620static Bool
621_XimProcKeySym(
622    Xic			  ic,
623    CARD32		  sym,
624    KeySym		**xim_keysym,
625    int			 *xim_keysym_len)
626{
627    Xim			 im = (Xim)ic->core.im;
628
629    if (!(*xim_keysym = Xmalloc(sizeof(KeySym)))) {
630	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
631	return False;
632    }
633
634    **xim_keysym = (KeySym)sym;
635    *xim_keysym_len = 1;
636
637    return True;
638}
639
640static Bool
641_XimProcCommit(
642    Xic		  ic,
643    BYTE	 *buf,
644    int		  len,
645    char	**xim_string,
646    int		 *xim_string_len)
647{
648    Xim		 im = (Xim)ic->core.im;
649    char	*string;
650
651    if (!(string = Xmalloc(len + 1))) {
652	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
653	return False;
654    }
655
656    (void)memcpy(string, (char *)buf, len);
657    string[len] = '\0';
658
659    *xim_string = string;
660    *xim_string_len = len;
661    return True;
662}
663
664static Bool
665_XimCommitRecv(
666    Xim		 im,
667    Xic		 ic,
668    XPointer	 buf)
669{
670    CARD16	*buf_s = (CARD16 *)buf;
671    BITMASK16	 flag = buf_s[0];
672    XKeyEvent	 ev;
673    char	*string = NULL;
674    int		 string_len = 0;
675    KeySym	*keysym = NULL;
676    int		 keysym_len = 0;
677
678    if ((flag & XimLookupBoth) == XimLookupChars) {
679	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2],
680			 		(int)buf_s[1], &string, &string_len)))
681	    return False;
682
683    } else if ((flag & XimLookupBoth) == XimLookupKeySym) {
684	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
685	    return False;
686
687    } else if ((flag & XimLookupBoth) == XimLookupBoth) {
688	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
689	    return False;
690
691	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5],
692					(int)buf_s[4], &string, &string_len))) {
693	    Xfree(keysym);
694	    return False;
695	}
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    if (ic->private.proto.registed_filter_event
710	& (KEYPRESS_MASK | KEYRELEASE_MASK))
711	    MARK_FABRICATED(im);
712
713    bzero(&ev, sizeof(ev));	/* uninitialized : found when running kterm under valgrind */
714
715    ev.type = KeyPress;
716    ev.send_event = False;
717    ev.display = im->core.display;
718    ev.window = ic->core.focus_window;
719    ev.keycode = 0;
720    ev.state = 0;
721
722    ev.time = 0L;
723    ev.serial = LastKnownRequestProcessed(im->core.display);
724    /* FIXME :
725       I wish there were COMMENTs (!) about the data passed around.
726    */
727#if 0
728    fprintf(stderr,"%s,%d: putback k press   FIXED ev.time=0 ev.serial=%lu\n", __FILE__, __LINE__, ev.serial);
729#endif
730
731    XPutBackEvent(im->core.display, (XEvent *)&ev);
732
733    return True;
734}
735
736Bool
737_XimCommitCallback(
738    Xim		 xim,
739    INT16	 len,
740    XPointer	 data,
741    XPointer	 call_data)
742{
743    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
744    XIMID        imid = buf_s[0];
745    XICID        icid = buf_s[1];
746    Xim		 im = (Xim)call_data;
747    Xic		 ic;
748
749    if ((imid == im->private.proto.imid)
750     && (ic = _XimICOfXICID(im, icid))) {
751	(void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]);
752	return True;
753    }
754    return False;
755}
756
757void
758_XimProcError(
759    Xim		 im,
760    Xic		 ic,
761    XPointer	 data)
762{
763    return;
764}
765
766Bool
767_XimErrorCallback(
768    Xim		 xim,
769    INT16	 len,
770    XPointer	 data,
771    XPointer	 call_data)
772{
773    CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
774    BITMASK16	 flag = buf_s[2];
775    XIMID        imid;
776    XICID        icid;
777    Xim		 im = (Xim)call_data;
778    Xic		 ic = NULL;
779
780    if (flag & XIM_IMID_VALID) {
781	imid = buf_s[0];
782	if (imid != im->private.proto.imid)
783	    return False;
784    }
785    if (flag & XIM_ICID_VALID) {
786	icid = buf_s[1];
787	if (!(ic = _XimICOfXICID(im, icid)))
788	    return False;
789    }
790    _XimProcError(im, ic, (XPointer)&buf_s[3]);
791
792    return True;
793}
794
795Bool
796_XimError(
797    Xim		 im,
798    Xic		 ic,
799    CARD16	 error_code,
800    INT16	 detail_length,
801    CARD16	 type,
802    char	*detail)
803{
804    CARD32	 buf32[BUFSIZE/4];
805    CARD8	*buf = (CARD8 *)buf32;
806    CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
807    INT16	 len = 0;
808
809    buf_s[0] = im->private.proto.imid;	/* imid */
810    buf_s[2] = XIM_IMID_VALID;		/* flag */
811    if (ic) {
812    	buf_s[1] = ic->private.proto.icid;	/* icid */
813	buf_s[2] |= XIM_ICID_VALID;		/* flag */
814    }
815    buf_s[3] = error_code;			/* Error Code */
816    buf_s[4] = detail_length;			/* length of error detail */
817    buf_s[5] = type;				/* type of error detail */
818
819    if (detail_length && detail) {
820	len = detail_length;
821	memcpy((char *)&buf_s[6], detail, len);
822	XIM_SET_PAD(&buf_s[6], len);
823    }
824
825    len += sizeof(CARD16)		/* sizeof imid */
826	 + sizeof(CARD16)		/* sizeof icid */
827	 + sizeof(BITMASK16)		/* sizeof flag */
828	 + sizeof(CARD16)		/* sizeof error_code */
829	 + sizeof(INT16)		/* sizeof length of detail */
830	 + sizeof(CARD16);		/* sizeof type */
831
832    _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len);
833    if (!(_XimWrite(im, len, (XPointer)buf)))
834	return False;
835    _XimFlush(im);
836    return True;
837}
838
839static int
840_Ximctsconvert(
841    XlcConv	 conv,
842    char	*from,
843    int		 from_len,
844    char	*to,
845    int		 to_len,
846    Status	*state)
847{
848    int		 from_left;
849    int		 to_left;
850    int		 from_savelen;
851    int		 to_savelen;
852    int		 from_cnvlen;
853    int		 to_cnvlen;
854    char	*from_buf;
855    char	*to_buf;
856    char	 scratchbuf[BUFSIZ];
857    Status	 tmp_state;
858
859    if (!state)
860	state = &tmp_state;
861
862    if (!conv || !from || !from_len) {
863	*state = XLookupNone;
864	return 0;
865    }
866
867    /* Reset the converter.  The CompoundText at 'from' starts in
868       initial state.  */
869    _XlcResetConverter(conv);
870
871    from_left = from_len;
872    to_left = BUFSIZ;
873    from_cnvlen = 0;
874    to_cnvlen = 0;
875    for (;;) {
876	from_buf = &from[from_cnvlen];
877	from_savelen = from_left;
878	to_buf = &scratchbuf[to_cnvlen];
879	to_savelen = to_left;
880	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
881				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
882	    *state = XLookupNone;
883	    return 0;
884	}
885	from_cnvlen += (from_savelen - from_left);
886	to_cnvlen += (to_savelen - to_left);
887	if (from_left == 0) {
888	    if (!to_cnvlen) {
889		*state = XLookupNone;
890		return 0;
891           }
892	   break;
893	}
894    }
895
896    if (!to || !to_len || (to_len < to_cnvlen)) {
897       *state = XBufferOverflow;
898    } else {
899       memcpy(to, scratchbuf, to_cnvlen);
900       *state = XLookupChars;
901    }
902    return to_cnvlen;
903}
904
905int
906_Ximctstombs(XIM xim, char *from, int from_len,
907	     char *to, int to_len, Status *state)
908{
909    return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv,
910			  from, from_len, to, to_len, state);
911}
912
913int
914_Ximctstowcs(
915    XIM		 xim,
916    char	*from,
917    int		 from_len,
918    wchar_t	*to,
919    int		 to_len,
920    Status	*state)
921{
922    Xim		 im = (Xim)xim;
923    XlcConv	 conv = im->private.proto.ctow_conv;
924    int		 from_left;
925    int		 to_left;
926    int		 from_savelen;
927    int		 to_savelen;
928    int		 from_cnvlen;
929    int		 to_cnvlen;
930    char	*from_buf;
931    wchar_t	*to_buf;
932    wchar_t	 scratchbuf[BUFSIZ];
933    Status	 tmp_state;
934
935    if (!state)
936	state = &tmp_state;
937
938    if (!conv || !from || !from_len) {
939	*state = XLookupNone;
940	return 0;
941    }
942
943    /* Reset the converter.  The CompoundText at 'from' starts in
944       initial state.  */
945    _XlcResetConverter(conv);
946
947    from_left = from_len;
948    to_left = BUFSIZ;
949    from_cnvlen = 0;
950    to_cnvlen = 0;
951    for (;;) {
952	from_buf = &from[from_cnvlen];
953       from_savelen = from_left;
954       to_buf = &scratchbuf[to_cnvlen];
955       to_savelen = to_left;
956	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
957				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
958	    *state = XLookupNone;
959	    return 0;
960	}
961	from_cnvlen += (from_savelen - from_left);
962       to_cnvlen += (to_savelen - to_left);
963	if (from_left == 0) {
964           if (!to_cnvlen){
965		*state = XLookupNone;
966               return 0;
967           }
968	    break;
969	}
970    }
971
972    if (!to || !to_len || (to_len < to_cnvlen)) {
973       *state = XBufferOverflow;
974    } else {
975       memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t));
976       *state = XLookupChars;
977    }
978    return to_cnvlen;
979}
980
981int
982_Ximctstoutf8(
983    XIM		 xim,
984    char	*from,
985    int		 from_len,
986    char	*to,
987    int		 to_len,
988    Status	*state)
989{
990    return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv,
991			  from, from_len, to, to_len, state);
992}
993
994int
995_XimProtoMbLookupString(
996    XIC			 xic,
997    XKeyEvent		*ev,
998    char		*buffer,
999    int			 bytes,
1000    KeySym		*keysym,
1001    Status		*state)
1002{
1003    Xic			 ic = (Xic)xic;
1004    Xim			 im = (Xim)ic->core.im;
1005    int			 ret;
1006    Status		 tmp_state;
1007    XimCommitInfo	 info;
1008
1009    if (!IS_SERVER_CONNECTED(im))
1010	return 0;
1011
1012    if (!state)
1013	state = &tmp_state;
1014
1015    if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */
1016	if (!(info = ic->private.proto.commit_info)) {
1017	    *state = XLookupNone;
1018	    return 0;
1019	}
1020
1021	ret = im->methods->ctstombs((XIM)im, info->string,
1022			 	info->string_len, buffer, bytes, state);
1023	if (*state == XBufferOverflow)
1024            return ret;
1025	if (keysym && (info->keysym && *(info->keysym))) {
1026	    *keysym = *(info->keysym);
1027	    if (*state == XLookupChars)
1028		*state = XLookupBoth;
1029	    else
1030		*state = XLookupKeySym;
1031	}
1032	_XimUnregCommitInfo(ic);
1033
1034    } else  if (ev->type == KeyPress) {
1035	ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
1036	if (ret > 0) {
1037           if (ret > bytes)
1038               *state = XBufferOverflow;
1039           else if (keysym && *keysym != NoSymbol)
1040		*state = XLookupBoth;
1041	    else
1042		*state = XLookupChars;
1043	} else {
1044	    if (keysym && *keysym != NoSymbol)
1045		*state = XLookupKeySym;
1046	    else
1047		*state = XLookupNone;
1048	}
1049    } else {
1050	*state = XLookupNone;
1051	ret = 0;
1052    }
1053
1054    return ret;
1055}
1056
1057int
1058_XimProtoWcLookupString(
1059    XIC			 xic,
1060    XKeyEvent		*ev,
1061    wchar_t		*buffer,
1062    int			 bytes,
1063    KeySym		*keysym,
1064    Status		*state)
1065{
1066    Xic			 ic = (Xic)xic;
1067    Xim			 im = (Xim)ic->core.im;
1068    int			 ret;
1069    Status		 tmp_state;
1070    XimCommitInfo	 info;
1071
1072    if (!IS_SERVER_CONNECTED(im))
1073	return 0;
1074
1075    if (!state)
1076	state = &tmp_state;
1077
1078    if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
1079	if (!(info = ic->private.proto.commit_info)) {
1080           *state = XLookupNone;
1081	    return 0;
1082	}
1083
1084	ret = im->methods->ctstowcs((XIM)im, info->string,
1085			 	info->string_len, buffer, bytes, state);
1086	if (*state == XBufferOverflow)
1087           return ret;
1088	if (keysym && (info->keysym && *(info->keysym))) {
1089	    *keysym = *(info->keysym);
1090	    if (*state == XLookupChars)
1091		*state = XLookupBoth;
1092	    else
1093		*state = XLookupKeySym;
1094	}
1095	_XimUnregCommitInfo(ic);
1096
1097    } else if (ev->type == KeyPress) {
1098	ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
1099	if (ret > 0) {
1100           if (ret > bytes)
1101               *state = XBufferOverflow;
1102           else if (keysym && *keysym != NoSymbol)
1103		*state = XLookupBoth;
1104	    else
1105		*state = XLookupChars;
1106	} else {
1107	    if (keysym && *keysym != NoSymbol)
1108		*state = XLookupKeySym;
1109	    else
1110		*state = XLookupNone;
1111	}
1112    } else {
1113	*state = XLookupNone;
1114	ret = 0;
1115    }
1116
1117    return ret;
1118}
1119
1120int
1121_XimProtoUtf8LookupString(
1122    XIC			 xic,
1123    XKeyEvent		*ev,
1124    char		*buffer,
1125    int			 bytes,
1126    KeySym		*keysym,
1127    Status		*state)
1128{
1129    Xic			 ic = (Xic)xic;
1130    Xim			 im = (Xim)ic->core.im;
1131    int			 ret;
1132    Status		 tmp_state;
1133    XimCommitInfo	 info;
1134
1135    if (!IS_SERVER_CONNECTED(im))
1136	return 0;
1137
1138    if (!state)
1139	state = &tmp_state;
1140
1141    if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
1142	if (!(info = ic->private.proto.commit_info)) {
1143           *state = XLookupNone;
1144	    return 0;
1145	}
1146
1147	ret = im->methods->ctstoutf8((XIM)im, info->string,
1148			 	info->string_len, buffer, bytes, state);
1149	if (*state == XBufferOverflow)
1150           return ret;
1151	if (keysym && (info->keysym && *(info->keysym))) {
1152	    *keysym = *(info->keysym);
1153	    if (*state == XLookupChars)
1154		*state = XLookupBoth;
1155	    else
1156		*state = XLookupKeySym;
1157	}
1158	_XimUnregCommitInfo(ic);
1159
1160    } else if (ev->type == KeyPress) {
1161	ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
1162	if (ret > 0) {
1163           if (ret > bytes)
1164               *state = XBufferOverflow;
1165           else if (keysym && *keysym != NoSymbol)
1166		*state = XLookupBoth;
1167	    else
1168		*state = XLookupChars;
1169	} else {
1170	    if (keysym && *keysym != NoSymbol)
1171		*state = XLookupKeySym;
1172	    else
1173		*state = XLookupNone;
1174	}
1175    } else {
1176	*state = XLookupNone;
1177	ret = 0;
1178    }
1179
1180    return ret;
1181}
1182