11ab64890Smrg/***********************************************************************
21ab64890SmrgCopyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
31ab64890SmrgCopyright 1994 by FUJITSU LIMITED
41ab64890SmrgCopyright 1994 by Sony Corporation
51ab64890Smrg
61ab64890Smrg                        All Rights Reserved
71ab64890Smrg
861b2299dSmrgPermission to use, copy, modify, and distribute this software and its
961b2299dSmrgdocumentation for any purpose and without fee is hereby granted,
101ab64890Smrgprovided that the above copyright notice appear in all copies and that
1161b2299dSmrgboth that copyright notice and this permission notice appear in
121ab64890Smrgsupporting documentation, and that the names of Digital, FUJITSU
131ab64890SmrgLIMITED and Sony Corporation not be used in advertising or publicity
141ab64890Smrgpertaining to distribution of the software without specific, written
1561b2299dSmrgprior permission.
161ab64890Smrg
171ab64890SmrgDIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES
181ab64890SmrgWITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
191ab64890SmrgMERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED
201ab64890SmrgAND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
211ab64890SmrgCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
221ab64890SmrgUSE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
231ab64890SmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
241ab64890SmrgPERFORMANCE OF THIS SOFTWARE.
251ab64890Smrg
261ab64890Smrg  Author: Hiroyuki Miyamoto  Digital Equipment Corporation
271ab64890Smrg                             miyamoto@jrd.dec.com
281ab64890Smrg  Modifier: Takashi Fujiwara FUJITSU LIMITED
291ab64890Smrg			     fujiwara@a80.tech.yk.fujitsu.co.jp
301ab64890Smrg	    Makoto Wakamatsu Sony Corporation
311ab64890Smrg		 	     makoto@sm.sony.co.jp
3261b2299dSmrg
331ab64890Smrg***********************************************************************/
341ab64890Smrg
351ab64890Smrg#ifdef HAVE_CONFIG_H
361ab64890Smrg#include <config.h>
371ab64890Smrg#endif
381ab64890Smrg#include "Xlibint.h"
391ab64890Smrg#include "Xlcint.h"
401ab64890Smrg#include "Ximint.h"
411ab64890Smrg#include "XlcPubI.h"
421ab64890Smrg
431ab64890Smrg#define sz_CARD8                 1
441ab64890Smrg#define sz_INT8                  1
451ab64890Smrg#define sz_CARD16                2
461ab64890Smrg#define sz_INT16                 2
471ab64890Smrg#define sz_BITMASK16             sz_CARD16
481ab64890Smrg#define sz_CARD32                4
491ab64890Smrg#define sz_INT32                 4
501ab64890Smrg#define sz_BITMASK32             sz_CARD32
511ab64890Smrg#define sz_XIMID                 sizeof(XIMID)
521ab64890Smrg#define sz_XICID                 sizeof(XICID)
531ab64890Smrg#define sz_XIMATTRID             sizeof(XIMATTRID)
541ab64890Smrg#define sz_XICATTRID             sizeof(XICATTRID)
551ab64890Smrg#define sz_ximPacketHeader       (XIM_HEADER_SIZE + sz_XIMID + sz_XICID)
561ab64890Smrg#define sz_ximGeometry           0
571ab64890Smrg#define sz_ximStrConversion      (sz_CARD32 + sz_CARD32 + sz_CARD32 + sz_CARD32)
581ab64890Smrg#define sz_ximPreeditStart       0
591ab64890Smrg#define sz_ximPreeditStartReply  sz_INT32
601ab64890Smrg#define sz_ximPreeditCaret       (sz_INT32 + sz_CARD32 + sz_CARD32)
611ab64890Smrg#define sz_ximPreeditCaretReply  sz_CARD32
621ab64890Smrg#define sz_ximPreeditDone        0
631ab64890Smrg#define sz_ximStatusStart        0
641ab64890Smrg#define sz_ximStatusDone         0
651ab64890Smrg
661ab64890Smrgtypedef enum {
6761b2299dSmrg    XimCbSuccess,
6861b2299dSmrg    XimCbNoCallback,
6961b2299dSmrg    XimCbError,
7061b2299dSmrg    XimCbQueued,
7161b2299dSmrg    XimCbBadContextID,
721ab64890Smrg    XimCbBadOpcode
731ab64890Smrg} XimCbStatus;
741ab64890Smrg
751ab64890Smrgtypedef XimCbStatus (*XimCb)(
761ab64890Smrg			     Xim, Xic, char*, int
771ab64890Smrg			     );
781ab64890Smrg
791ab64890Smrg#define PACKET_TO_MAJOROPCODE(p) (*(CARD8*)((CARD8*)(p)))
801ab64890Smrg#define PACKET_TO_MINOROPCODE(p) (*(CARD8*)((CARD8*)(p) + sz_CARD8))
811ab64890Smrg#define PACKET_TO_LENGTH(p) (*(CARD16*)((CARD8*)(p) + sz_CARD8 + sz_CARD8))
821ab64890Smrg#define PACKET_TO_IMID(p) (*(XIMID*)((CARD8*)(p) + XIM_HEADER_SIZE))
831ab64890Smrg#define PACKET_TO_ICID(p) (*(XICID*)((CARD8*)(p) + XIM_HEADER_SIZE + sz_XIMID))
841ab64890Smrg
851ab64890Smrg#define _XimWriteData(im,len,data) \
861ab64890Smrg    (im->private.proto.write((im),(len),(XPointer)(data)))
871ab64890Smrg#define _XimReadData(im,buf,buf_len,len) \
881ab64890Smrg    (im->private.proto.read((im),(XPointer)(buf),(buf_len),&(len)))
891ab64890Smrg#define _XimFlushData(im) im->private.proto.flush((im))
901ab64890Smrg
91eb411b4bSmrgstatic XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int);
92eb411b4bSmrgstatic XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int);
93eb411b4bSmrgstatic XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int);
94eb411b4bSmrgstatic XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int);
95eb411b4bSmrgstatic void _free_memory_for_text(XIMText*);
96eb411b4bSmrgstatic XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int);
97eb411b4bSmrgstatic XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int);
98eb411b4bSmrgstatic XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int);
99eb411b4bSmrgstatic XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int);
100eb411b4bSmrgstatic XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int);
101eb411b4bSmrgstatic XimCbStatus _XimPreeditStateNotifyCallback(Xim, Xic, char *, int);
1021ab64890Smrg
1031ab64890Smrg#if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32))
1041ab64890Smrg#define RConst /**/
1051ab64890Smrg#else
1061ab64890Smrg#define RConst const
1071ab64890Smrg#endif
1081ab64890Smrg
1091ab64890Smrg/* NOTE:
11061b2299dSmrg * the table below depends on the protocol number
1111ab64890Smrg * defined in the IM Protocol document.
1121ab64890Smrg */
1131ab64890Smrgstatic RConst XimCb callback_table[] = {
1141ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #000-009 */
1151ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #010-019 */
1161ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #020-029 */
1171ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #030-039 */
1181ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #040-049 */
1191ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #050-059 */
1201ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #060-069 */
1211ab64890Smrg    _XimGeometryCallback,	/* #070 */
1221ab64890Smrg    _XimStrConversionCallback,	/* #071 */
1231ab64890Smrg    NULL,			/* #072 */
1241ab64890Smrg    _XimPreeditStartCallback,	/* #073 */
1251ab64890Smrg    NULL,			/* #074 */
1261ab64890Smrg    _XimPreeditDrawCallback,	/* #075 */
1271ab64890Smrg    _XimPreeditCaretCallback,	/* #076 */
1281ab64890Smrg    NULL,			/* #077 */
1291ab64890Smrg    _XimPreeditDoneCallback,	/* #078 */
1301ab64890Smrg    _XimStatusStartCallback,	/* #079 */
1311ab64890Smrg    _XimStatusDrawCallback,	/* #080 */
1321ab64890Smrg    _XimStatusDoneCallback,	/* #081 */
1331ab64890Smrg    _XimPreeditStateNotifyCallback	/* #082 */
1341ab64890Smrg    };
1351ab64890Smrg
1361ab64890Smrg
137eb411b4bSmrgstatic Bool
1381ab64890Smrg_XimIsReadyForProcess(Xic ic)
1391ab64890Smrg{
1401ab64890Smrg    return(!ic->private.proto.waitCallback); /* check HM */
1411ab64890Smrg}
1421ab64890Smrg
143eb411b4bSmrgstatic void
1441ab64890Smrg_XimProcessPendingCallbacks(Xic ic)
1451ab64890Smrg{
1461ab64890Smrg    XimPendingCallback pcbq;
1471ab64890Smrg
14861b2299dSmrg    while (((pcbq = ic->private.proto.pend_cb_que) != (XimPendingCallback)NULL)
1491ab64890Smrg	   && _XimIsReadyForProcess(ic)) {
15061b2299dSmrg	(void) (*callback_table[pcbq->major_opcode])(pcbq->im,
15161b2299dSmrg						     pcbq->ic,
15261b2299dSmrg						     pcbq->proto,
1531ab64890Smrg						     pcbq->proto_len);
1541ab64890Smrg	ic->private.proto.pend_cb_que = pcbq->next;
1551ab64890Smrg	Xfree(pcbq->proto);	/* free memory of XimPendingCallback */
1561ab64890Smrg	Xfree(pcbq);
1571ab64890Smrg    }
1581ab64890Smrg}
1591ab64890Smrg
160eb411b4bSmrgstatic void
1611ab64890Smrg_XimPutCbIntoQueue(Xic ic, XimPendingCallback call_data)
1621ab64890Smrg{
1631ab64890Smrg    XimPendingCallback pcbq = ic->private.proto.pend_cb_que;
1641ab64890Smrg
1651ab64890Smrg    /* Queuing is FIFO
1661ab64890Smrg     */
1671ab64890Smrg    while (pcbq != (XimPendingCallback)NULL) {
1681ab64890Smrg	if (pcbq->next == (XimPendingCallback)NULL) {
1691ab64890Smrg	    break;
1701ab64890Smrg	}
1711ab64890Smrg	pcbq = pcbq->next;
1721ab64890Smrg    }
1731ab64890Smrg    if (pcbq == (XimPendingCallback)NULL) {
1741ab64890Smrg	ic->private.proto.pend_cb_que = call_data;
1751ab64890Smrg    }
1761ab64890Smrg    else {
1771ab64890Smrg	pcbq->next = call_data;
1781ab64890Smrg    }
1791ab64890Smrg}
1801ab64890Smrg
181eb411b4bSmrgBool
18261b2299dSmrg_XimCbDispatch(Xim xim,
18361b2299dSmrg	       INT16 len,
18461b2299dSmrg	       XPointer data,
1851ab64890Smrg	       XPointer call_data)
1861ab64890Smrg{
1871ab64890Smrg    /* `data' points to the beginning of the packet defined in IM Protocol doc.
1881ab64890Smrg     */
1891ab64890Smrg    int major_opcode = PACKET_TO_MAJOROPCODE(data);
1901ab64890Smrg    XIMID imid = PACKET_TO_IMID(data);
1911ab64890Smrg    XICID icid = PACKET_TO_ICID(data);
1921ab64890Smrg    Xim im = (Xim)call_data;	/* check HM */
1931ab64890Smrg    Xic ic = _XimICOfXICID(im, icid);
1941ab64890Smrg    char* proto;
1951ab64890Smrg    int proto_len;
1961ab64890Smrg
1971ab64890Smrg    /* check validity of im/ic
1981ab64890Smrg     */
1991ab64890Smrg    if ((imid != im->private.proto.imid) || !ic) {
2001ab64890Smrg	return False; /* status = XimCbBadContextID; */
2011ab64890Smrg    }
2021ab64890Smrg
2031ab64890Smrg    /* process pending callbacks
2041ab64890Smrg     */
2051ab64890Smrg    _XimProcessPendingCallbacks(ic);
2061ab64890Smrg
2071ab64890Smrg    /* check if the protocol should be processed here
2081ab64890Smrg     */
2091ab64890Smrg    if (major_opcode > 82) {
2101ab64890Smrg	return False; /* status = XimCbBadOpcode; */
2111ab64890Smrg    }
2121ab64890Smrg    if (!callback_table[major_opcode]) {
2131ab64890Smrg	return False; /* status = XimCbBadOpcode; */
2141ab64890Smrg    }
2151ab64890Smrg
2161ab64890Smrg    /* move the pointer ahead by the IM Protocol packet header size
2171ab64890Smrg     */
2181ab64890Smrg    proto = (char*)data + sz_ximPacketHeader;
2191ab64890Smrg    proto_len = (int)len - sz_ximPacketHeader;
2201ab64890Smrg
2211ab64890Smrg    /* check if it can be processed right away
2221ab64890Smrg     * and if no, queue the protocol, otherwise invoke a callback
2231ab64890Smrg     */
2241ab64890Smrg    if (!_XimIsReadyForProcess(ic)) {
2251ab64890Smrg
2261ab64890Smrg	/* queue the protocol
2271ab64890Smrg	 */
2281ab64890Smrg	XimPendingCallback pcb;
229818534a1Smrg	char *proto_buf = (proto_len > 0) ? Xmalloc(proto_len) : NULL;
2301ab64890Smrg
231818534a1Smrg	pcb = Xmalloc(sizeof(XimPendingCallbackRec));
2321ab64890Smrg	if (pcb && (proto_len <= 0 || proto_buf)) {
2331ab64890Smrg	    if (proto_len > 0)
2341ab64890Smrg		memcpy(proto_buf, proto, proto_len);
2351ab64890Smrg
2361ab64890Smrg	    pcb->major_opcode = major_opcode;
2371ab64890Smrg	    pcb->im = im;
2381ab64890Smrg	    pcb->ic = ic;
2391ab64890Smrg	    pcb->proto = proto_buf;
2401ab64890Smrg	    pcb->proto_len = proto_len;
2411ab64890Smrg	    pcb->next = (XimPendingCallback)NULL; /* queue is FIFO */
2421ab64890Smrg	    _XimPutCbIntoQueue(ic, pcb);
2431ab64890Smrg	    /* status = XimCbQueued; */
2441ab64890Smrg	} else {
2451ab64890Smrg	    /* status = XimCbError; */
2466cc2b21fSmrg	    Xfree(pcb);
2476cc2b21fSmrg	    Xfree(proto_buf);
2481ab64890Smrg	}
2491ab64890Smrg    }
2501ab64890Smrg    else {
2511ab64890Smrg	/* invoke each callback according to the major opcode.
2521ab64890Smrg	 * `proto' points to the next address of IM-ID and IC-ID.
2531ab64890Smrg	 * `proto_len' specifies the packet length.
2541ab64890Smrg	 */
2551ab64890Smrg	(void) (*callback_table[major_opcode])(im, ic, proto, proto_len);
2561ab64890Smrg    }
2571ab64890Smrg    return True;
2581ab64890Smrg}
2591ab64890Smrg
260eb411b4bSmrgstatic XimCbStatus
26161b2299dSmrg_XimGeometryCallback(Xim im,
26261b2299dSmrg		     Xic ic,
26361b2299dSmrg		     char* proto,
2641ab64890Smrg		     int len)
2651ab64890Smrg{
2661ab64890Smrg    XICCallback* cb = &ic->core.geometry_callback;
2671ab64890Smrg
2689c019ec5Smaya    /* invoke the callback
2691ab64890Smrg     */
27061b2299dSmrg    if (cb && cb->callback) {
2711ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
2721ab64890Smrg    }
2731ab64890Smrg    else {
2741ab64890Smrg
2751ab64890Smrg	/* no callback registered
2761ab64890Smrg	 */
2771ab64890Smrg	return XimCbNoCallback;
2781ab64890Smrg    }
2791ab64890Smrg
2801ab64890Smrg    return XimCbSuccess;
2811ab64890Smrg}
2821ab64890Smrg
283eb411b4bSmrgstatic XimCbStatus
28461b2299dSmrg_XimStrConversionCallback(Xim im,
28561b2299dSmrg			  Xic ic,
28661b2299dSmrg			  char* proto,
2871ab64890Smrg			  int len)
2881ab64890Smrg{
2891ab64890Smrg    XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */
2901ab64890Smrg    XIMStringConversionCallbackStruct cbrec;
2911ab64890Smrg
2921ab64890Smrg    /* invoke the callback
2931ab64890Smrg     */
2941ab64890Smrg    if (cb && cb->callback) {
2951ab64890Smrg	int p = XIM_HEADER_SIZE;
2961ab64890Smrg	cbrec.position = (XIMStringConversionPosition)
2971ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
2981ab64890Smrg	cbrec.direction = (XIMCaretDirection)
2991ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
3001ab64890Smrg	cbrec.operation = (XIMStringConversionOperation)
3011ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
3021ab64890Smrg	cbrec.factor = (unsigned short)
3031ab64890Smrg	    *(CARD32*)&proto[p];
3041ab64890Smrg
3051ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec);
3061ab64890Smrg    }
3071ab64890Smrg    else {
3081ab64890Smrg
3091ab64890Smrg	/* no callback registered
3101ab64890Smrg	 */
31161b2299dSmrg	_XimError(im, ic,
31261b2299dSmrg		  (CARD16)XIM_BadSomething,
31361b2299dSmrg		  (INT16)len,
31461b2299dSmrg		  (CARD16)XIM_STR_CONVERSION,
3151ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
3161ab64890Smrg	return XimCbNoCallback;
3171ab64890Smrg    }
3181ab64890Smrg
3191ab64890Smrg    /* send a reply
3201ab64890Smrg     */
3211ab64890Smrg    {
3221ab64890Smrg	CARD8	*buf;
3231ab64890Smrg	INT16	 buf_len;
3241ab64890Smrg	int	 p, length_in_bytes, i;
3251ab64890Smrg
3261ab64890Smrg	/* Assumption:
3271ab64890Smrg	 * `cbrec.text->length' means the string length in characters
3281ab64890Smrg	 */
3291ab64890Smrg	{
33007fb9b8fSmrg	    size_t blen;
3311ab64890Smrg	    length_in_bytes = (cbrec.text->encoding_is_wchar)?
3321ab64890Smrg		sizeof(wchar_t) * cbrec.text->length: /* wchar */
3331ab64890Smrg		strlen(cbrec.text->string.mbs);	/* mb */
33407fb9b8fSmrg	    blen = XIM_HEADER_SIZE +
3351ab64890Smrg		sz_CARD16 +
33661b2299dSmrg		2 + length_in_bytes +
3371ab64890Smrg		XIM_PAD(2 + length_in_bytes) +
3381ab64890Smrg		2 + 2 + sz_CARD32 * cbrec.text->length;
33907fb9b8fSmrg	    buf = Xmalloc(blen);
34007fb9b8fSmrg	    buf_len = (INT16) blen;
3411ab64890Smrg	}
3421ab64890Smrg	_XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len);
3431ab64890Smrg	buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */
3441ab64890Smrg	p = XIM_HEADER_SIZE;
3451ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
3461ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
3471ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16;
3481ab64890Smrg	memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes);
3491ab64890Smrg	p += length_in_bytes;
3501ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length);
3511ab64890Smrg	p += XIM_PAD(2);
3521ab64890Smrg	for (i = 0; i < (int)cbrec.text->length; i++) {
3531ab64890Smrg	    *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i];
3541ab64890Smrg	    p += sz_CARD32;
3551ab64890Smrg	}
3561ab64890Smrg
3571ab64890Smrg	if (!(_XimWriteData(im, buf_len, buf))) {
3581ab64890Smrg	    return XimCbError;
3591ab64890Smrg	}
3601ab64890Smrg	_XimFlushData(im);
3611ab64890Smrg
3621ab64890Smrg	Xfree(buf);
3631ab64890Smrg    }
3641ab64890Smrg
3651ab64890Smrg    return XimCbSuccess;
3661ab64890Smrg}
3671ab64890Smrg
368eb411b4bSmrgstatic XimCbStatus
36961b2299dSmrg_XimPreeditStartCallback(Xim im,
37061b2299dSmrg			 Xic ic,
37161b2299dSmrg			 char* proto,
3721ab64890Smrg			 int len)
3731ab64890Smrg{
3741ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.start_callback;
3751ab64890Smrg    int ret;
3761ab64890Smrg
3771ab64890Smrg    /* invoke the callback
3781ab64890Smrg     */
3791ab64890Smrg    if (cb && cb->callback){
3801ab64890Smrg	ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL);
3811ab64890Smrg    }
3821ab64890Smrg    else {
3831ab64890Smrg
38461b2299dSmrg	/* no callback registered
3851ab64890Smrg	 */
38661b2299dSmrg	_XimError(im, ic,
38761b2299dSmrg		  (CARD16)XIM_BadSomething,
38861b2299dSmrg		  (INT16)len,
38961b2299dSmrg		  (CARD16)XIM_PREEDIT_START,
3901ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
3911ab64890Smrg	return XimCbNoCallback;
3921ab64890Smrg    }
3931ab64890Smrg
3941ab64890Smrg    /* send a reply
3951ab64890Smrg     */
3961ab64890Smrg    {
3971ab64890Smrg	CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4];
3981ab64890Smrg	CARD8 *buf = (CARD8 *)buf32;
3991ab64890Smrg	INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply;
4001ab64890Smrg	int p;
4011ab64890Smrg
4021ab64890Smrg	_XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len);
4031ab64890Smrg	p = XIM_HEADER_SIZE;
4041ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
4051ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
4061ab64890Smrg	*(INT32*)&buf[p]  = (INT32)ret;
4071ab64890Smrg
4081ab64890Smrg	if (!(_XimWriteData(im, buf_len, buf))) {
4091ab64890Smrg	    return XimCbError;
4101ab64890Smrg	}
4111ab64890Smrg	_XimFlushData(im);
4121ab64890Smrg    }
4131ab64890Smrg
4141ab64890Smrg    return XimCbSuccess;
4151ab64890Smrg}
4161ab64890Smrg
417eb411b4bSmrgstatic XimCbStatus
41861b2299dSmrg_XimPreeditDoneCallback(Xim im,
41961b2299dSmrg			Xic ic,
42061b2299dSmrg			char* proto,
4211ab64890Smrg			int len)
4221ab64890Smrg{
4231ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.done_callback;
4241ab64890Smrg
4251ab64890Smrg    /* invoke the callback
4261ab64890Smrg     */
4271ab64890Smrg    if (cb && cb->callback) {
4281ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
4291ab64890Smrg    }
4301ab64890Smrg    else {
4311ab64890Smrg
4321ab64890Smrg	/* no callback registered
4331ab64890Smrg	 */
4341ab64890Smrg	return XimCbNoCallback;
4351ab64890Smrg    }
4361ab64890Smrg
4371ab64890Smrg    return XimCbSuccess;
4381ab64890Smrg}
4391ab64890Smrg
440eb411b4bSmrgstatic void
44161b2299dSmrg_read_text_from_packet(Xim im,
44261b2299dSmrg		       char* buf,
4431ab64890Smrg		       XIMText** text_ptr)
4441ab64890Smrg{
4451ab64890Smrg    int status;
4461ab64890Smrg    XIMText* text;
4471ab64890Smrg    int tmp_len;
4481ab64890Smrg    char* tmp_buf;
4491ab64890Smrg    Status s = 0;
4501ab64890Smrg
4511ab64890Smrg    status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32;
4521ab64890Smrg
4531ab64890Smrg    /* string part
4541ab64890Smrg     */
4551ab64890Smrg    if (status & 0x00000001) /* "no string" bit on */ {
4561ab64890Smrg	buf += sz_CARD16;	/* skip "length of preedit string" */
4571ab64890Smrg	buf += 2;		/* pad */
4581ab64890Smrg	*text_ptr = (XIMText*)NULL;
4591ab64890Smrg	return;
4601ab64890Smrg    }
4611ab64890Smrg
462818534a1Smrg    *text_ptr = text = Xmalloc(sizeof(XIMText));
4631ab64890Smrg    if (text == (XIMText*)NULL) return;
4641ab64890Smrg
4651ab64890Smrg	tmp_len = (int)*(CARD16*)buf;
4661ab64890Smrg	buf += sz_CARD16;
467818534a1Smrg	if ((tmp_buf = Xmalloc(tmp_len + 1))) {
4681ab64890Smrg	    memcpy(tmp_buf, buf, tmp_len);
4691ab64890Smrg	    tmp_buf[tmp_len] = '\0';
4701ab64890Smrg
4711ab64890Smrg	    text->encoding_is_wchar = False;
47261b2299dSmrg	    text->length = im->methods->ctstombs((XIM)im,
47361b2299dSmrg					tmp_buf, tmp_len,
4741ab64890Smrg					NULL, 0, &s); /* CT? HM */
4751ab64890Smrg	    if (s != XLookupNone) {
4761ab64890Smrg#ifndef NO_DEC_I18N_FIX
4771ab64890Smrg                /* Allow for NULL-terminated */
478818534a1Smrg                if ((text->string.multi_byte = Xmalloc(text->length *
4791ab64890Smrg                      XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) {
4801ab64890Smrg#else
481818534a1Smrg		if (text->string.multi_byte = Xmalloc(text->length+1)) {
4821ab64890Smrg#endif
4831ab64890Smrg			int tmp;
4841ab64890Smrg#ifndef NO_DEC_I18N_FIX
4851ab64890Smrg                        char *char_tmp;
4861ab64890Smrg                        int char_len;
4871ab64890Smrg#endif
4881ab64890Smrg			tmp = im->methods->ctstombs((XIM)im,
48961b2299dSmrg					   tmp_buf, tmp_len,
4901ab64890Smrg#ifndef NO_DEC_I18N_FIX
4911ab64890Smrg                                           text->string.multi_byte,
4921ab64890Smrg                                           text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1,
4931ab64890Smrg#else
49461b2299dSmrg					   text->string.multi_byte, text->length,
4951ab64890Smrg#endif
4961ab64890Smrg					   &s);
4971ab64890Smrg			text->string.multi_byte[tmp] = '\0';
4981ab64890Smrg#ifndef NO_DEC_I18N_FIX
4991ab64890Smrg                        text->length = 0;
5001ab64890Smrg                        char_tmp =  text->string.multi_byte;
5011ab64890Smrg                        while (*char_tmp != '\0') {
5021ab64890Smrg                              char_len = mblen(char_tmp, strlen(char_tmp));
5031ab64890Smrg                              char_tmp = char_tmp + char_len;
5041ab64890Smrg                              (text->length)++;
5051ab64890Smrg                        }
5061ab64890Smrg#endif
5071ab64890Smrg		}
5081ab64890Smrg	    }
5091ab64890Smrg	    else {
5101ab64890Smrg		text->length = 0;
5111ab64890Smrg		text->string.multi_byte = NULL;
5121ab64890Smrg	    }
5131ab64890Smrg
5141ab64890Smrg	    Xfree(tmp_buf);
5151ab64890Smrg	}
5161ab64890Smrg	buf += tmp_len;
5171ab64890Smrg
5181ab64890Smrg	buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */
5191ab64890Smrg
5201ab64890Smrg    /* feedback part
5211ab64890Smrg     */
5221ab64890Smrg    if (status & 0x00000002) /* "no feedback" bit on */ {
5231ab64890Smrg	text->feedback = (XIMFeedback*)NULL;
5241ab64890Smrg    }
5251ab64890Smrg    else {
5261ab64890Smrg	int i, j;
5271ab64890Smrg
5281ab64890Smrg	i = (int)*(CARD16*)buf; buf += sz_CARD16;
5291ab64890Smrg	buf += sz_CARD16; /* skip `unused' */
530818534a1Smrg	text->feedback = Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32)));
5311ab64890Smrg	j = 0;
5321ab64890Smrg	while (i > 0) {
5331ab64890Smrg	    text->feedback[j] = (XIMFeedback)*(CARD32*)buf;
5341ab64890Smrg	    buf += sz_CARD32;
5351ab64890Smrg	    i -= sz_CARD32;
5361ab64890Smrg	    j++;
5371ab64890Smrg	}
53861b2299dSmrg	/*
5391ab64890Smrg	 * text->length tells how long both the status string and
5401ab64890Smrg	 * the feedback array are. If there's "no string" the
5411ab64890Smrg	 * text->length was set to zero previously. See above.
5421ab64890Smrg	 * But if there is feedback (i.e. not "no feedback") then
5431ab64890Smrg	 * we need to convey the length of the feedback array.
5441ab64890Smrg	 * It might have been better if the protocol sent two
5451ab64890Smrg	 * different values, one for the length of the status
5461ab64890Smrg	 * string and one for the length of the feedback array.
5471ab64890Smrg	 */
5481ab64890Smrg	if (status & 0x00000001) /* "no string" bit on */ {
5491ab64890Smrg	    text->length = j;
5501ab64890Smrg	}
5511ab64890Smrg    }
5521ab64890Smrg}
5531ab64890Smrg
554eb411b4bSmrgstatic void
5551ab64890Smrg_free_memory_for_text(XIMText* text)
5561ab64890Smrg{
5571ab64890Smrg    if (text) {
5580f8248bfSmrg        Xfree(text->string.multi_byte);
5590f8248bfSmrg        Xfree(text->feedback);
5601ab64890Smrg	Xfree(text);
5611ab64890Smrg    }
5621ab64890Smrg}
5631ab64890Smrg
564eb411b4bSmrgstatic XimCbStatus
56561b2299dSmrg_XimPreeditDrawCallback(Xim im,
56661b2299dSmrg			Xic ic,
56761b2299dSmrg			char* proto,
5681ab64890Smrg			int len)
5691ab64890Smrg{
5701ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.draw_callback;
5711ab64890Smrg    XIMPreeditDrawCallbackStruct cbs;
5721ab64890Smrg
5731ab64890Smrg    /* invoke the callback
5741ab64890Smrg     */
5751ab64890Smrg    if (cb && cb->callback) {
5761ab64890Smrg	cbs.caret      = (int)*(INT32*)proto; proto += sz_INT32;
5771ab64890Smrg	cbs.chg_first  = (int)*(INT32*)proto; proto += sz_INT32;
5781ab64890Smrg	cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32;
5791ab64890Smrg	_read_text_from_packet(im, proto, &cbs.text);
5801ab64890Smrg
5811ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
5821ab64890Smrg
5831ab64890Smrg	_free_memory_for_text((XIMText*)cbs.text);
5841ab64890Smrg    }
5851ab64890Smrg    else {
5861ab64890Smrg
5871ab64890Smrg	/* no callback registered
5881ab64890Smrg	 */
5891ab64890Smrg	return XimCbNoCallback;
5901ab64890Smrg    }
5911ab64890Smrg
5921ab64890Smrg    return XimCbSuccess;
5931ab64890Smrg}
5941ab64890Smrg
595eb411b4bSmrgstatic XimCbStatus
59661b2299dSmrg_XimPreeditCaretCallback(Xim im,
59761b2299dSmrg			 Xic ic,
5981ab64890Smrg			 char* proto,
5991ab64890Smrg			 int len)
6001ab64890Smrg{
6011ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.caret_callback;
6021ab64890Smrg    XIMPreeditCaretCallbackStruct cbs;
6031ab64890Smrg
6041ab64890Smrg    /* invoke the callback
6051ab64890Smrg     */
6061ab64890Smrg    if (cb && cb->callback) {
6071ab64890Smrg	cbs.position  = (int)*(INT32*)proto; proto += sz_INT32;
6081ab64890Smrg	cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32;
6091ab64890Smrg	cbs.style     = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32;
6101ab64890Smrg
6111ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
6121ab64890Smrg    }
6131ab64890Smrg    else {
6141ab64890Smrg
61561b2299dSmrg	/* no callback registered
6161ab64890Smrg	 */
61761b2299dSmrg	_XimError(im, ic,
61861b2299dSmrg		  (CARD16)XIM_BadSomething,
61961b2299dSmrg		  (INT16)len,
62061b2299dSmrg		  (CARD16)XIM_PREEDIT_CARET,
6211ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
6221ab64890Smrg	return XimCbNoCallback;
6231ab64890Smrg    }
6241ab64890Smrg
6251ab64890Smrg    /* Send a reply
6261ab64890Smrg     */
6271ab64890Smrg    {
6281ab64890Smrg	CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply];
6293233502eSmrg	INT16 rlen = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply;
6301ab64890Smrg	int p;
6311ab64890Smrg
6323233502eSmrg	_XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &rlen);
6331ab64890Smrg	p = XIM_HEADER_SIZE;
6341ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
6351ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
6361ab64890Smrg	*(CARD32*)&buf[p] = (CARD32)cbs.position;
6371ab64890Smrg
6383233502eSmrg	if (!(_XimWriteData(im, rlen, buf))) {
6391ab64890Smrg	    return XimCbError;
6401ab64890Smrg	}
6411ab64890Smrg	_XimFlushData(im);
6421ab64890Smrg    }
6431ab64890Smrg
6441ab64890Smrg    return XimCbSuccess;
6451ab64890Smrg}
6461ab64890Smrg
647eb411b4bSmrgstatic XimCbStatus
64861b2299dSmrg_XimStatusStartCallback(Xim im,
64961b2299dSmrg			Xic ic,
65061b2299dSmrg			char* proto,
6511ab64890Smrg			int len)
6521ab64890Smrg{
6531ab64890Smrg    XICCallback* cb = &ic->core.status_attr.start_callback;
6541ab64890Smrg
6551ab64890Smrg    /* invoke the callback
6561ab64890Smrg     */
6571ab64890Smrg    if (cb && cb->callback) {
6581ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
6591ab64890Smrg    }
6601ab64890Smrg    else {
6611ab64890Smrg
6621ab64890Smrg	/* no callback registered
6631ab64890Smrg	 */
6641ab64890Smrg	return XimCbNoCallback;
6651ab64890Smrg    }
6661ab64890Smrg
6671ab64890Smrg    return XimCbSuccess;
6681ab64890Smrg}
6691ab64890Smrg
670eb411b4bSmrgstatic XimCbStatus
67161b2299dSmrg_XimStatusDoneCallback(Xim im,
67261b2299dSmrg		       Xic ic,
67361b2299dSmrg		       char* proto,
6741ab64890Smrg		       int len)
6751ab64890Smrg{
6761ab64890Smrg    XICCallback* cb = &ic->core.status_attr.done_callback;
6771ab64890Smrg
6781ab64890Smrg    /* invoke the callback
6791ab64890Smrg     */
6801ab64890Smrg    if (cb && cb->callback) {
6811ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
6821ab64890Smrg    }
6831ab64890Smrg    else {
6841ab64890Smrg
6851ab64890Smrg	/* no callback registered
6861ab64890Smrg	 */
6871ab64890Smrg	return XimCbNoCallback;
6881ab64890Smrg    }
6891ab64890Smrg
6901ab64890Smrg    return XimCbSuccess;
6911ab64890Smrg}
6921ab64890Smrg
693eb411b4bSmrgstatic XimCbStatus
69461b2299dSmrg_XimStatusDrawCallback(Xim im,
69561b2299dSmrg		       Xic ic,
69661b2299dSmrg		       char* proto,
6971ab64890Smrg		       int len)
6981ab64890Smrg{
6991ab64890Smrg    XICCallback* cb = &ic->core.status_attr.draw_callback;
7001ab64890Smrg    XIMStatusDrawCallbackStruct cbs;
7011ab64890Smrg
7021ab64890Smrg    /* invoke the callback
7031ab64890Smrg     */
7041ab64890Smrg    if (cb && cb->callback) {
7051ab64890Smrg	cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32;
7061ab64890Smrg	if (cbs.type == XIMTextType) {
7071ab64890Smrg	    _read_text_from_packet(im, proto, &cbs.data.text);
7081ab64890Smrg	}
7091ab64890Smrg	else if (cbs.type == XIMBitmapType) {
7101ab64890Smrg	    cbs.data.bitmap = (Pixmap)*(CARD32*)proto;
7111ab64890Smrg	}
7121ab64890Smrg
7131ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
7141ab64890Smrg
7151ab64890Smrg	if (cbs.type == XIMTextType)
7161ab64890Smrg	    _free_memory_for_text((XIMText *)cbs.data.text);
7171ab64890Smrg    }
7181ab64890Smrg    else {
7191ab64890Smrg
7201ab64890Smrg	/* no callback registered
7211ab64890Smrg	 */
7221ab64890Smrg	return XimCbNoCallback;
7231ab64890Smrg    }
7241ab64890Smrg
7251ab64890Smrg    return XimCbSuccess;
7261ab64890Smrg}
7271ab64890Smrg
728eb411b4bSmrgstatic XimCbStatus
7291ab64890Smrg_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len )
7301ab64890Smrg{
7311ab64890Smrg    XICCallback	*cb = &ic->core.preedit_attr.state_notify_callback;
7321ab64890Smrg
7339c019ec5Smaya    /* invoke the callback
7341ab64890Smrg     */
73561b2299dSmrg    if( cb  &&  cb->callback ) {
7361ab64890Smrg	XIMPreeditStateNotifyCallbackStruct cbrec;
7371ab64890Smrg
7381ab64890Smrg	cbrec.state = *(BITMASK32 *)proto;
7391ab64890Smrg	(*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec );
7401ab64890Smrg    }
7411ab64890Smrg    else {
7421ab64890Smrg	/* no callback registered
7431ab64890Smrg	 */
7441ab64890Smrg	return XimCbNoCallback;
7451ab64890Smrg    }
7461ab64890Smrg
7471ab64890Smrg    return XimCbSuccess;
7481ab64890Smrg}
7491ab64890Smrg
750