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