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     return;
    446 }
    447 
    448 static Bool
    449 _XimForwardEventRecv(
    450     Xim		 im,
    451     Xic		 ic,
    452     XPointer	 buf)
    453 {
    454     CARD16	*buf_s = (CARD16 *)buf;
    455     Display	*d = im->core.display;
    456     XEvent	 ev;
    457 
    458     _XimProcEvent(d, ic, &ev, &buf_s[1]);
    459 
    460     (void)_XimRespSyncReply(ic, buf_s[0]);
    461 
    462     /* If no event filter is registered, the event will not be sent back
    463      * to filter for _XimUnfabricateSerial, so simply bypass it.
    464      */
    465     if (ic->private.proto.registed_filter_event
    466 	& (KEYPRESS_MASK | KEYRELEASE_MASK)) {
    467 	_XimFabricateSerial((Xim)ic->core.im, &ev.xkey);
    468     } else {
    469 	_XimPendingFilter(ic);
    470     }
    471 
    472     XPutBackEvent(d, &ev);
    473 
    474     return True;
    475 }
    476 
    477 Bool
    478 _XimForwardEventCallback(
    479     Xim		 xim,
    480     INT16	 len,
    481     XPointer	 data,
    482     XPointer	 call_data)
    483 {
    484     CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
    485     XIMID        imid = buf_s[0];
    486     XICID        icid = buf_s[1];
    487     Xim		 im = (Xim)call_data;
    488     Xic		 ic;
    489 
    490     if ((imid == im->private.proto.imid)
    491      && (ic = _XimICOfXICID(im, icid))) {
    492 	(void)_XimForwardEventRecv(im, ic, (XPointer)&buf_s[2]);
    493 	return True;
    494     }
    495     return False;
    496 }
    497 
    498 static Bool
    499 _XimRegisterTriggerkey(
    500     Xim			 im,
    501     XPointer		 buf)
    502 {
    503     CARD32		*buf_l = (CARD32 *)buf;
    504     CARD32		 len;
    505     CARD32 		*key;
    506 
    507     if (IS_DYNAMIC_EVENT_FLOW(im))	/* already Dynamic event flow mode */
    508 	return True;
    509 
    510     /*
    511      *  register onkeylist
    512      */
    513 
    514     len = buf_l[0];				/* length of on-keys */
    515     len += sizeof(INT32);			/* sizeof length of on-keys */
    516 
    517     if (!(key = Xmalloc(len))) {
    518 	_XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
    519 	return False;
    520     }
    521     memcpy((char *)key, (char *)buf_l, len);
    522     im->private.proto.im_onkeylist = key;
    523 
    524     MARK_DYNAMIC_EVENT_FLOW(im);
    525 
    526     /*
    527      *  register offkeylist
    528      */
    529 
    530     buf_l = (CARD32 *)((char *)buf + len);
    531     len = buf_l[0];				/* length of off-keys */
    532     len += sizeof(INT32);			/* sizeof length of off-keys */
    533 
    534     if (!(key = Xmalloc(len))) {
    535 	_XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
    536 	return False;
    537     }
    538 
    539     memcpy((char *)key, (char *)buf_l, len);
    540     im->private.proto.im_offkeylist = key;
    541 
    542     return True;
    543 }
    544 
    545 Bool
    546 _XimRegisterTriggerKeysCallback(
    547     Xim		 xim,
    548     INT16	 len,
    549     XPointer	 data,
    550     XPointer	 call_data)
    551 {
    552     CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
    553     Xim		 im = (Xim)call_data;
    554 
    555     (void )_XimRegisterTriggerkey(im, (XPointer)&buf_s[2]);
    556     return True;
    557 }
    558 
    559 EVENTMASK
    560 _XimGetWindowEventmask(
    561     Xic		 ic)
    562 {
    563     Xim			im = (Xim )ic->core.im;
    564     XWindowAttributes	atr;
    565 
    566     if (!XGetWindowAttributes(im->core.display, ic->core.focus_window, &atr))
    567 	return 0;
    568     return (EVENTMASK)atr.your_event_mask;
    569 }
    570 
    571 
    572 static Bool
    573 _XimTriggerNotifyCheck(
    574     Xim          im,
    575     INT16        len,
    576     XPointer	 data,
    577     XPointer     arg)
    578 {
    579     Xic		 ic  = (Xic)arg;
    580     CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
    581     CARD8	 major_opcode = *((CARD8 *)data);
    582     CARD8	 minor_opcode = *((CARD8 *)data + 1);
    583     XIMID	 imid = buf_s[0];
    584     XICID	 icid = buf_s[1];
    585 
    586     if ((major_opcode == XIM_TRIGGER_NOTIFY_REPLY)
    587      && (minor_opcode == 0)
    588      && (imid == im->private.proto.imid)
    589      && (icid == ic->private.proto.icid))
    590 	return True;
    591     if ((major_opcode == XIM_ERROR)
    592      && (minor_opcode == 0)
    593      && (buf_s[2] & XIM_IMID_VALID)
    594      && (imid == im->private.proto.imid)
    595      && (buf_s[2] & XIM_ICID_VALID)
    596      && (icid == ic->private.proto.icid))
    597 	return True;
    598     return False;
    599 }
    600 
    601 Bool
    602 _XimTriggerNotify(
    603     Xim		 im,
    604     Xic		 ic,
    605     int		 mode,
    606     CARD32	 idx)
    607 {
    608     CARD32	 buf32[BUFSIZE/4];
    609     CARD8	*buf = (CARD8 *)buf32;
    610     CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
    611     CARD32	*buf_l = (CARD32 *)&buf[XIM_HEADER_SIZE];
    612     CARD32	 reply32[BUFSIZE/4];
    613     char	*reply = (char *)reply32;
    614     XPointer	 preply;
    615     int		 buf_size;
    616     int		 ret_code;
    617     INT16	 len;
    618     EVENTMASK	 mask = _XimGetWindowEventmask(ic);
    619 
    620     buf_s[0] = im->private.proto.imid;	/* imid */
    621     buf_s[1] = ic->private.proto.icid;	/* icid */
    622     buf_l[1] = mode;			/* flag */
    623     buf_l[2] = idx;			/* index of keys list */
    624     buf_l[3] = mask;			/* select-event-mask */
    625 
    626     len = sizeof(CARD16)		/* sizeof imid */
    627 	+ sizeof(CARD16)		/* sizeof icid */
    628 	+ sizeof(CARD32)		/* sizeof flag */
    629 	+ sizeof(CARD32)		/* sizeof index of key list */
    630 	+ sizeof(EVENTMASK);		/* sizeof select-event-mask */
    631 
    632     _XimSetHeader((XPointer)buf, XIM_TRIGGER_NOTIFY, 0, &len);
    633     if (!(_XimWrite(im, len, (XPointer)buf)))
    634 	return False;
    635     _XimFlush(im);
    636     buf_size = BUFSIZE;
    637     ret_code = _XimRead(im, &len, (XPointer)reply, buf_size,
    638 				_XimTriggerNotifyCheck, (XPointer)ic);
    639     if(ret_code == XIM_TRUE) {
    640 	preply = reply;
    641     } else if(ret_code == XIM_OVERFLOW) {
    642 	if(len <= 0) {
    643 	    preply = reply;
    644 	} else {
    645 	    buf_size = len;
    646 	    preply = Xmalloc(len);
    647 	    ret_code = _XimRead(im, &len, preply, buf_size,
    648 				_XimTriggerNotifyCheck, (XPointer)ic);
    649 	    if(ret_code != XIM_TRUE) {
    650 		Xfree(preply);
    651 		return False;
    652 	    }
    653 	}
    654     } else {
    655 	return False;
    656     }
    657     buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE);
    658     if (*((CARD8 *)preply) == XIM_ERROR) {
    659 	_XimProcError(im, 0, (XPointer)&buf_s[3]);
    660 	if(reply != preply)
    661 	    Xfree(preply);
    662 	return False;
    663     }
    664     if(reply != preply)
    665 	Xfree(preply);
    666     return True;
    667 }
    668 
    669 static Bool
    670 _XimRegCommitInfo(
    671     Xic			 ic,
    672     char		*string,
    673     int			 string_len,
    674     KeySym		*keysym,
    675     int			 keysym_len)
    676 {
    677     XimCommitInfo	info;
    678 
    679     if (!(info = Xmalloc(sizeof(XimCommitInfoRec))))
    680 	return False;
    681     info->string	= string;
    682     info->string_len	= string_len;
    683     info->keysym	= keysym;
    684     info->keysym_len	= keysym_len;
    685     info->next = ic->private.proto.commit_info;
    686     ic->private.proto.commit_info = info;
    687     return True;
    688 }
    689 
    690 static void
    691 _XimUnregRealCommitInfo(
    692     Xic			ic,
    693     Bool		reverse)
    694 {
    695     XimCommitInfo	info;
    696     XimCommitInfo	prev_info = NULL;
    697 
    698     info = ic->private.proto.commit_info;
    699     while (reverse && info) {
    700 	if (!info->next)
    701 	    break;
    702 	prev_info = info;
    703 	info = info->next;
    704     }
    705     if (!info)
    706 	return;
    707 
    708     Xfree(info->string);
    709     Xfree(info->keysym);
    710     if (prev_info)
    711 	prev_info->next = info->next;
    712     else
    713 	ic->private.proto.commit_info = info->next;
    714     Xfree(info);
    715     return;
    716 }
    717 
    718 static void
    719 _XimUnregCommitInfo(
    720     Xic			ic)
    721 {
    722     _XimUnregRealCommitInfo(ic, False);
    723 }
    724 
    725 static void
    726 _XimUnregFirstCommitInfo(
    727     Xic			ic)
    728 {
    729     _XimUnregRealCommitInfo(ic, True);
    730 }
    731 
    732 void
    733 _XimFreeCommitInfo(
    734     Xic			ic)
    735 {
    736     while (ic->private.proto.commit_info)
    737 	_XimUnregCommitInfo(ic);
    738     return;
    739 }
    740 
    741 static XimCommitInfo
    742 _XimFirstCommitInfo(
    743     Xic			ic)
    744 {
    745     XimCommitInfo info = ic->private.proto.commit_info;
    746     while (info) {
    747 	if (!info->next)
    748 	    break;
    749 	info = info->next;
    750     }
    751     return info;
    752 }
    753 
    754 static Bool
    755 _XimProcKeySym(
    756     Xic			  ic,
    757     CARD32		  sym,
    758     KeySym		**xim_keysym,
    759     int			 *xim_keysym_len)
    760 {
    761     Xim			 im = (Xim)ic->core.im;
    762 
    763     if (!(*xim_keysym = Xmalloc(sizeof(KeySym)))) {
    764 	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
    765 	return False;
    766     }
    767 
    768     **xim_keysym = (KeySym)sym;
    769     *xim_keysym_len = 1;
    770 
    771     return True;
    772 }
    773 
    774 static Bool
    775 _XimProcCommit(
    776     Xic		  ic,
    777     BYTE	 *buf,
    778     int		  len,
    779     char	**xim_string,
    780     int		 *xim_string_len)
    781 {
    782     Xim		 im = (Xim)ic->core.im;
    783     char	*string;
    784 
    785     if (!(string = Xmalloc(len + 1))) {
    786 	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
    787 	return False;
    788     }
    789 
    790     (void)memcpy(string, (char *)buf, len);
    791     string[len] = '\0';
    792 
    793     *xim_string = string;
    794     *xim_string_len = len;
    795     return True;
    796 }
    797 
    798 static Bool
    799 _XimCommitRecv(
    800     Xim		 im,
    801     Xic		 ic,
    802     XPointer	 buf)
    803 {
    804     CARD16	*buf_s = (CARD16 *)buf;
    805     BITMASK16	 flag = buf_s[0];
    806     XKeyEvent	 ev;
    807     char	*string = NULL;
    808     int		 string_len = 0;
    809     KeySym	*keysym = NULL;
    810     int		 keysym_len = 0;
    811 
    812     if ((flag & XimLookupBoth) == XimLookupChars) {
    813 	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2],
    814 			 		(int)buf_s[1], &string, &string_len)))
    815 	    return False;
    816 
    817     } else if ((flag & XimLookupBoth) == XimLookupKeySym) {
    818 	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
    819 	    return False;
    820 
    821     } else if ((flag & XimLookupBoth) == XimLookupBoth) {
    822 	if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len)))
    823 	    return False;
    824 
    825 	if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5],
    826 					(int)buf_s[4], &string, &string_len))) {
    827 	    Xfree(keysym);
    828 	    return False;
    829 	}
    830     }
    831 
    832     if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) {
    833        Xfree(string);
    834 	Xfree(keysym);
    835 	_XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL);
    836 	return False;
    837     }
    838 
    839     (void)_XimRespSyncReply(ic, flag);
    840 
    841     bzero(&ev, sizeof(ev));	/* uninitialized : found when running kterm under valgrind */
    842 
    843     ev.type = KeyPress;
    844     ev.send_event = False;
    845     ev.display = im->core.display;
    846     ev.window = ic->core.focus_window;
    847     ev.keycode = 0;
    848     ev.state = 0;
    849 
    850     ev.time = 0L;
    851     ev.serial = LastKnownRequestProcessed(im->core.display);
    852 
    853     if (ic->private.proto.registed_filter_event
    854 	& (KEYPRESS_MASK | KEYRELEASE_MASK))
    855 	    _XimFabricateSerial(im, &ev);
    856     /* FIXME :
    857        I wish there were COMMENTs (!) about the data passed around.
    858     */
    859 #if 0
    860     fprintf(stderr,"%s,%d: putback k press   FIXED ev.time=0 ev.serial=%lu\n", __FILE__, __LINE__, ev.serial);
    861 #endif
    862 
    863     XPutBackEvent(im->core.display, (XEvent *)&ev);
    864 
    865     return True;
    866 }
    867 
    868 Bool
    869 _XimCommitCallback(
    870     Xim		 xim,
    871     INT16	 len,
    872     XPointer	 data,
    873     XPointer	 call_data)
    874 {
    875     CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
    876     XIMID        imid = buf_s[0];
    877     XICID        icid = buf_s[1];
    878     Xim		 im = (Xim)call_data;
    879     Xic		 ic;
    880 
    881     if ((imid == im->private.proto.imid)
    882      && (ic = _XimICOfXICID(im, icid))) {
    883 	(void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]);
    884 	return True;
    885     }
    886     return False;
    887 }
    888 
    889 void
    890 _XimProcError(
    891     Xim		 im,
    892     Xic		 ic,
    893     XPointer	 data)
    894 {
    895     return;
    896 }
    897 
    898 Bool
    899 _XimErrorCallback(
    900     Xim		 xim,
    901     INT16	 len,
    902     XPointer	 data,
    903     XPointer	 call_data)
    904 {
    905     CARD16	*buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE);
    906     BITMASK16	 flag = buf_s[2];
    907     XIMID        imid;
    908     XICID        icid;
    909     Xim		 im = (Xim)call_data;
    910     Xic		 ic = NULL;
    911 
    912     if (flag & XIM_IMID_VALID) {
    913 	imid = buf_s[0];
    914 	if (imid != im->private.proto.imid)
    915 	    return False;
    916     }
    917     if (flag & XIM_ICID_VALID) {
    918 	icid = buf_s[1];
    919 	if (!(ic = _XimICOfXICID(im, icid)))
    920 	    return False;
    921     }
    922     _XimProcError(im, ic, (XPointer)&buf_s[3]);
    923 
    924     return True;
    925 }
    926 
    927 Bool
    928 _XimError(
    929     Xim		 im,
    930     Xic		 ic,
    931     CARD16	 error_code,
    932     INT16	 detail_length,
    933     CARD16	 type,
    934     char	*detail)
    935 {
    936     CARD32	 buf32[BUFSIZE/4];
    937     CARD8	*buf = (CARD8 *)buf32;
    938     CARD16	*buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE];
    939     INT16	 len = 0;
    940 
    941     buf_s[0] = im->private.proto.imid;	/* imid */
    942     buf_s[2] = XIM_IMID_VALID;		/* flag */
    943     if (ic) {
    944     	buf_s[1] = ic->private.proto.icid;	/* icid */
    945 	buf_s[2] |= XIM_ICID_VALID;		/* flag */
    946     }
    947     buf_s[3] = error_code;			/* Error Code */
    948     buf_s[4] = detail_length;			/* length of error detail */
    949     buf_s[5] = type;				/* type of error detail */
    950 
    951     if (detail_length && detail) {
    952 	len = detail_length;
    953 	memcpy((char *)&buf_s[6], detail, len);
    954 	XIM_SET_PAD(&buf_s[6], len);
    955     }
    956 
    957     len += sizeof(CARD16)		/* sizeof imid */
    958 	 + sizeof(CARD16)		/* sizeof icid */
    959 	 + sizeof(BITMASK16)		/* sizeof flag */
    960 	 + sizeof(CARD16)		/* sizeof error_code */
    961 	 + sizeof(INT16)		/* sizeof length of detail */
    962 	 + sizeof(CARD16);		/* sizeof type */
    963 
    964     _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len);
    965     if (!(_XimWrite(im, len, (XPointer)buf)))
    966 	return False;
    967     _XimFlush(im);
    968     return True;
    969 }
    970 
    971 static int
    972 _Ximctsconvert(
    973     XlcConv	 conv,
    974     char	*from,
    975     int		 from_len,
    976     char	*to,
    977     int		 to_len,
    978     Status	*state)
    979 {
    980     int		 from_left;
    981     int		 to_left;
    982     int		 from_savelen;
    983     int		 to_savelen;
    984     int		 from_cnvlen;
    985     int		 to_cnvlen;
    986     char	*from_buf;
    987     char	*to_buf;
    988     char	 scratchbuf[BUFSIZ];
    989     Status	 tmp_state;
    990 
    991     if (!state)
    992 	state = &tmp_state;
    993 
    994     if (!conv || !from || !from_len) {
    995 	*state = XLookupNone;
    996 	return 0;
    997     }
    998 
    999     /* Reset the converter.  The CompoundText at 'from' starts in
   1000        initial state.  */
   1001     _XlcResetConverter(conv);
   1002 
   1003     from_left = from_len;
   1004     to_left = BUFSIZ;
   1005     from_cnvlen = 0;
   1006     to_cnvlen = 0;
   1007     for (;;) {
   1008 	from_buf = &from[from_cnvlen];
   1009 	from_savelen = from_left;
   1010 	to_buf = &scratchbuf[to_cnvlen];
   1011 	to_savelen = to_left;
   1012 	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
   1013 				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
   1014 	    *state = XLookupNone;
   1015 	    return 0;
   1016 	}
   1017 	from_cnvlen += (from_savelen - from_left);
   1018 	to_cnvlen += (to_savelen - to_left);
   1019 	if (from_left == 0) {
   1020 	    if (!to_cnvlen) {
   1021 		*state = XLookupNone;
   1022 		return 0;
   1023            }
   1024 	   break;
   1025 	}
   1026     }
   1027 
   1028     if (!to || !to_len || (to_len < to_cnvlen)) {
   1029        *state = XBufferOverflow;
   1030     } else {
   1031        memcpy(to, scratchbuf, to_cnvlen);
   1032        *state = XLookupChars;
   1033     }
   1034     return to_cnvlen;
   1035 }
   1036 
   1037 int
   1038 _Ximctstombs(XIM xim, char *from, int from_len,
   1039 	     char *to, int to_len, Status *state)
   1040 {
   1041     return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv,
   1042 			  from, from_len, to, to_len, state);
   1043 }
   1044 
   1045 int
   1046 _Ximctstowcs(
   1047     XIM		 xim,
   1048     char	*from,
   1049     int		 from_len,
   1050     wchar_t	*to,
   1051     int		 to_len,
   1052     Status	*state)
   1053 {
   1054     Xim		 im = (Xim)xim;
   1055     XlcConv	 conv = im->private.proto.ctow_conv;
   1056     int		 from_left;
   1057     int		 to_left;
   1058     int		 from_savelen;
   1059     int		 to_savelen;
   1060     int		 from_cnvlen;
   1061     int		 to_cnvlen;
   1062     char	*from_buf;
   1063     wchar_t	*to_buf;
   1064     wchar_t	 scratchbuf[BUFSIZ];
   1065     Status	 tmp_state;
   1066 
   1067     if (!state)
   1068 	state = &tmp_state;
   1069 
   1070     if (!conv || !from || !from_len) {
   1071 	*state = XLookupNone;
   1072 	return 0;
   1073     }
   1074 
   1075     /* Reset the converter.  The CompoundText at 'from' starts in
   1076        initial state.  */
   1077     _XlcResetConverter(conv);
   1078 
   1079     from_left = from_len;
   1080     to_left = BUFSIZ;
   1081     from_cnvlen = 0;
   1082     to_cnvlen = 0;
   1083     for (;;) {
   1084 	from_buf = &from[from_cnvlen];
   1085        from_savelen = from_left;
   1086        to_buf = &scratchbuf[to_cnvlen];
   1087        to_savelen = to_left;
   1088 	if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
   1089 				 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
   1090 	    *state = XLookupNone;
   1091 	    return 0;
   1092 	}
   1093 	from_cnvlen += (from_savelen - from_left);
   1094        to_cnvlen += (to_savelen - to_left);
   1095 	if (from_left == 0) {
   1096            if (!to_cnvlen){
   1097 		*state = XLookupNone;
   1098                return 0;
   1099            }
   1100 	    break;
   1101 	}
   1102     }
   1103 
   1104     if (!to || !to_len || (to_len < to_cnvlen)) {
   1105        *state = XBufferOverflow;
   1106     } else {
   1107        memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t));
   1108        *state = XLookupChars;
   1109     }
   1110     return to_cnvlen;
   1111 }
   1112 
   1113 int
   1114 _Ximctstoutf8(
   1115     XIM		 xim,
   1116     char	*from,
   1117     int		 from_len,
   1118     char	*to,
   1119     int		 to_len,
   1120     Status	*state)
   1121 {
   1122     return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv,
   1123 			  from, from_len, to, to_len, state);
   1124 }
   1125 
   1126 int
   1127 _XimProtoMbLookupString(
   1128     XIC			 xic,
   1129     XKeyEvent		*ev,
   1130     char		*buffer,
   1131     int			 bytes,
   1132     KeySym		*keysym,
   1133     Status		*state)
   1134 {
   1135     Xic			 ic = (Xic)xic;
   1136     Xim			 im = (Xim)ic->core.im;
   1137     int			 ret;
   1138     Status		 tmp_state;
   1139     XimCommitInfo	 info;
   1140 
   1141     if (!IS_SERVER_CONNECTED(im))
   1142 	return 0;
   1143 
   1144     if (!state)
   1145 	state = &tmp_state;
   1146 
   1147     if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */
   1148 	if (!(info = _XimFirstCommitInfo(ic))) {
   1149 	    *state = XLookupNone;
   1150 	    return 0;
   1151 	}
   1152 
   1153 	ret = im->methods->ctstombs((XIM)im, info->string,
   1154 			 	info->string_len, buffer, bytes, state);
   1155 	if (*state == XBufferOverflow)
   1156             return ret;
   1157 	if (keysym && (info->keysym && *(info->keysym))) {
   1158 	    *keysym = *(info->keysym);
   1159 	    if (*state == XLookupChars)
   1160 		*state = XLookupBoth;
   1161 	    else
   1162 		*state = XLookupKeySym;
   1163 	}
   1164 	_XimUnregFirstCommitInfo(ic);
   1165 
   1166     } else  if (ev->type == KeyPress) {
   1167 	ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL);
   1168 	if (ret > 0) {
   1169            if (ret > bytes)
   1170                *state = XBufferOverflow;
   1171            else if (keysym && *keysym != NoSymbol)
   1172 		*state = XLookupBoth;
   1173 	    else
   1174 		*state = XLookupChars;
   1175 	} else {
   1176 	    if (keysym && *keysym != NoSymbol)
   1177 		*state = XLookupKeySym;
   1178 	    else
   1179 		*state = XLookupNone;
   1180 	}
   1181     } else {
   1182 	*state = XLookupNone;
   1183 	ret = 0;
   1184     }
   1185 
   1186     return ret;
   1187 }
   1188 
   1189 int
   1190 _XimProtoWcLookupString(
   1191     XIC			 xic,
   1192     XKeyEvent		*ev,
   1193     wchar_t		*buffer,
   1194     int			 bytes,
   1195     KeySym		*keysym,
   1196     Status		*state)
   1197 {
   1198     Xic			 ic = (Xic)xic;
   1199     Xim			 im = (Xim)ic->core.im;
   1200     int			 ret;
   1201     Status		 tmp_state;
   1202     XimCommitInfo	 info;
   1203 
   1204     if (!IS_SERVER_CONNECTED(im))
   1205 	return 0;
   1206 
   1207     if (!state)
   1208 	state = &tmp_state;
   1209 
   1210     if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
   1211 	if (!(info = _XimFirstCommitInfo(ic))) {
   1212            *state = XLookupNone;
   1213 	    return 0;
   1214 	}
   1215 
   1216 	ret = im->methods->ctstowcs((XIM)im, info->string,
   1217 			 	info->string_len, buffer, bytes, state);
   1218 	if (*state == XBufferOverflow)
   1219            return ret;
   1220 	if (keysym && (info->keysym && *(info->keysym))) {
   1221 	    *keysym = *(info->keysym);
   1222 	    if (*state == XLookupChars)
   1223 		*state = XLookupBoth;
   1224 	    else
   1225 		*state = XLookupKeySym;
   1226 	}
   1227 	_XimUnregFirstCommitInfo(ic);
   1228 
   1229     } else if (ev->type == KeyPress) {
   1230 	ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL);
   1231 	if (ret > 0) {
   1232            if (ret > bytes)
   1233                *state = XBufferOverflow;
   1234            else if (keysym && *keysym != NoSymbol)
   1235 		*state = XLookupBoth;
   1236 	    else
   1237 		*state = XLookupChars;
   1238 	} else {
   1239 	    if (keysym && *keysym != NoSymbol)
   1240 		*state = XLookupKeySym;
   1241 	    else
   1242 		*state = XLookupNone;
   1243 	}
   1244     } else {
   1245 	*state = XLookupNone;
   1246 	ret = 0;
   1247     }
   1248 
   1249     return ret;
   1250 }
   1251 
   1252 int
   1253 _XimProtoUtf8LookupString(
   1254     XIC			 xic,
   1255     XKeyEvent		*ev,
   1256     char		*buffer,
   1257     int			 bytes,
   1258     KeySym		*keysym,
   1259     Status		*state)
   1260 {
   1261     Xic			 ic = (Xic)xic;
   1262     Xim			 im = (Xim)ic->core.im;
   1263     int			 ret;
   1264     Status		 tmp_state;
   1265     XimCommitInfo	 info;
   1266 
   1267     if (!IS_SERVER_CONNECTED(im))
   1268 	return 0;
   1269 
   1270     if (!state)
   1271 	state = &tmp_state;
   1272 
   1273     if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */
   1274 	if (!(info = _XimFirstCommitInfo(ic))) {
   1275            *state = XLookupNone;
   1276 	    return 0;
   1277 	}
   1278 
   1279 	ret = im->methods->ctstoutf8((XIM)im, info->string,
   1280 			 	info->string_len, buffer, bytes, state);
   1281 	if (*state == XBufferOverflow)
   1282            return ret;
   1283 	if (keysym && (info->keysym && *(info->keysym))) {
   1284 	    *keysym = *(info->keysym);
   1285 	    if (*state == XLookupChars)
   1286 		*state = XLookupBoth;
   1287 	    else
   1288 		*state = XLookupKeySym;
   1289 	}
   1290 	_XimUnregFirstCommitInfo(ic);
   1291 
   1292     } else if (ev->type == KeyPress) {
   1293 	ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL);
   1294 	if (ret > 0) {
   1295            if (ret > bytes)
   1296                *state = XBufferOverflow;
   1297            else if (keysym && *keysym != NoSymbol)
   1298 		*state = XLookupBoth;
   1299 	    else
   1300 		*state = XLookupChars;
   1301 	} else {
   1302 	    if (keysym && *keysym != NoSymbol)
   1303 		*state = XLookupKeySym;
   1304 	    else
   1305 		*state = XLookupNone;
   1306 	}
   1307     } else {
   1308 	*state = XLookupNone;
   1309 	ret = 0;
   1310     }
   1311 
   1312     return ret;
   1313 }
   1314