imCallbk.c revision eb411b4b
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#ifdef X_LOCALE
431ab64890Smrg#define mblen(a,b)	_Xmblen(a,b)
441ab64890Smrgextern int _Xmblen ();
451ab64890Smrg#endif
461ab64890Smrg
471ab64890Smrg#define sz_CARD8                 1
481ab64890Smrg#define sz_INT8                  1
491ab64890Smrg#define sz_CARD16                2
501ab64890Smrg#define sz_INT16                 2
511ab64890Smrg#define sz_BITMASK16             sz_CARD16
521ab64890Smrg#define sz_CARD32                4
531ab64890Smrg#define sz_INT32                 4
541ab64890Smrg#define sz_BITMASK32             sz_CARD32
551ab64890Smrg#define sz_XIMID                 sizeof(XIMID)
561ab64890Smrg#define sz_XICID                 sizeof(XICID)
571ab64890Smrg#define sz_XIMATTRID             sizeof(XIMATTRID)
581ab64890Smrg#define sz_XICATTRID             sizeof(XICATTRID)
591ab64890Smrg#define sz_ximPacketHeader       (XIM_HEADER_SIZE + sz_XIMID + sz_XICID)
601ab64890Smrg#define sz_ximGeometry           0
611ab64890Smrg#define sz_ximStrConversion      (sz_CARD32 + sz_CARD32 + sz_CARD32 + sz_CARD32)
621ab64890Smrg#define sz_ximPreeditStart       0
631ab64890Smrg#define sz_ximPreeditStartReply  sz_INT32
641ab64890Smrg#define sz_ximPreeditCaret       (sz_INT32 + sz_CARD32 + sz_CARD32)
651ab64890Smrg#define sz_ximPreeditCaretReply  sz_CARD32
661ab64890Smrg#define sz_ximPreeditDone        0
671ab64890Smrg#define sz_ximStatusStart        0
681ab64890Smrg#define sz_ximStatusDone         0
691ab64890Smrg
701ab64890Smrgtypedef enum {
7161b2299dSmrg    XimCbSuccess,
7261b2299dSmrg    XimCbNoCallback,
7361b2299dSmrg    XimCbError,
7461b2299dSmrg    XimCbQueued,
7561b2299dSmrg    XimCbBadContextID,
761ab64890Smrg    XimCbBadOpcode
771ab64890Smrg} XimCbStatus;
781ab64890Smrg
791ab64890Smrgtypedef XimCbStatus (*XimCb)(
801ab64890Smrg			     Xim, Xic, char*, int
811ab64890Smrg			     );
821ab64890Smrg
831ab64890Smrg#define PACKET_TO_MAJOROPCODE(p) (*(CARD8*)((CARD8*)(p)))
841ab64890Smrg#define PACKET_TO_MINOROPCODE(p) (*(CARD8*)((CARD8*)(p) + sz_CARD8))
851ab64890Smrg#define PACKET_TO_LENGTH(p) (*(CARD16*)((CARD8*)(p) + sz_CARD8 + sz_CARD8))
861ab64890Smrg#define PACKET_TO_IMID(p) (*(XIMID*)((CARD8*)(p) + XIM_HEADER_SIZE))
871ab64890Smrg#define PACKET_TO_ICID(p) (*(XICID*)((CARD8*)(p) + XIM_HEADER_SIZE + sz_XIMID))
881ab64890Smrg
891ab64890Smrg#define _XimWriteData(im,len,data) \
901ab64890Smrg    (im->private.proto.write((im),(len),(XPointer)(data)))
911ab64890Smrg#define _XimReadData(im,buf,buf_len,len) \
921ab64890Smrg    (im->private.proto.read((im),(XPointer)(buf),(buf_len),&(len)))
931ab64890Smrg#define _XimFlushData(im) im->private.proto.flush((im))
941ab64890Smrg
95eb411b4bSmrgstatic XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int);
96eb411b4bSmrgstatic XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int);
97eb411b4bSmrgstatic XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int);
98eb411b4bSmrgstatic XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int);
99eb411b4bSmrgstatic void _free_memory_for_text(XIMText*);
100eb411b4bSmrgstatic XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int);
101eb411b4bSmrgstatic XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int);
102eb411b4bSmrgstatic XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int);
103eb411b4bSmrgstatic XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int);
104eb411b4bSmrgstatic XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int);
105eb411b4bSmrgstatic XimCbStatus _XimPreeditStateNotifyCallback(Xim, Xic, char *, int);
1061ab64890Smrg
1071ab64890Smrg#if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32))
1081ab64890Smrg#define RConst /**/
1091ab64890Smrg#else
1101ab64890Smrg#define RConst const
1111ab64890Smrg#endif
1121ab64890Smrg
1131ab64890Smrg/* NOTE:
11461b2299dSmrg * the table below depends on the protocol number
1151ab64890Smrg * defined in the IM Protocol document.
1161ab64890Smrg */
1171ab64890Smrgstatic RConst XimCb callback_table[] = {
1181ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #000-009 */
1191ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #010-019 */
1201ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #020-029 */
1211ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #030-039 */
1221ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #040-049 */
1231ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #050-059 */
1241ab64890Smrg    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #060-069 */
1251ab64890Smrg    _XimGeometryCallback,	/* #070 */
1261ab64890Smrg    _XimStrConversionCallback,	/* #071 */
1271ab64890Smrg    NULL,			/* #072 */
1281ab64890Smrg    _XimPreeditStartCallback,	/* #073 */
1291ab64890Smrg    NULL,			/* #074 */
1301ab64890Smrg    _XimPreeditDrawCallback,	/* #075 */
1311ab64890Smrg    _XimPreeditCaretCallback,	/* #076 */
1321ab64890Smrg    NULL,			/* #077 */
1331ab64890Smrg    _XimPreeditDoneCallback,	/* #078 */
1341ab64890Smrg    _XimStatusStartCallback,	/* #079 */
1351ab64890Smrg    _XimStatusDrawCallback,	/* #080 */
1361ab64890Smrg    _XimStatusDoneCallback,	/* #081 */
1371ab64890Smrg    _XimPreeditStateNotifyCallback	/* #082 */
1381ab64890Smrg    };
1391ab64890Smrg
1401ab64890Smrg
141eb411b4bSmrgstatic Bool
1421ab64890Smrg_XimIsReadyForProcess(Xic ic)
1431ab64890Smrg{
1441ab64890Smrg    return(!ic->private.proto.waitCallback); /* check HM */
1451ab64890Smrg}
1461ab64890Smrg
147eb411b4bSmrgstatic void
1481ab64890Smrg_XimProcessPendingCallbacks(Xic ic)
1491ab64890Smrg{
1501ab64890Smrg    XimPendingCallback pcbq;
1511ab64890Smrg
15261b2299dSmrg    while (((pcbq = ic->private.proto.pend_cb_que) != (XimPendingCallback)NULL)
1531ab64890Smrg	   && _XimIsReadyForProcess(ic)) {
15461b2299dSmrg	(void) (*callback_table[pcbq->major_opcode])(pcbq->im,
15561b2299dSmrg						     pcbq->ic,
15661b2299dSmrg						     pcbq->proto,
1571ab64890Smrg						     pcbq->proto_len);
1581ab64890Smrg	ic->private.proto.pend_cb_que = pcbq->next;
1591ab64890Smrg	Xfree(pcbq->proto);	/* free memory of XimPendingCallback */
1601ab64890Smrg	Xfree(pcbq);
1611ab64890Smrg    }
1621ab64890Smrg}
1631ab64890Smrg
164eb411b4bSmrgstatic void
1651ab64890Smrg_XimPutCbIntoQueue(Xic ic, XimPendingCallback call_data)
1661ab64890Smrg{
1671ab64890Smrg    XimPendingCallback pcbq = ic->private.proto.pend_cb_que;
1681ab64890Smrg
1691ab64890Smrg    /* Queuing is FIFO
1701ab64890Smrg     */
1711ab64890Smrg    while (pcbq != (XimPendingCallback)NULL) {
1721ab64890Smrg	if (pcbq->next == (XimPendingCallback)NULL) {
1731ab64890Smrg	    break;
1741ab64890Smrg	}
1751ab64890Smrg	pcbq = pcbq->next;
1761ab64890Smrg    }
1771ab64890Smrg    if (pcbq == (XimPendingCallback)NULL) {
1781ab64890Smrg	ic->private.proto.pend_cb_que = call_data;
1791ab64890Smrg    }
1801ab64890Smrg    else {
1811ab64890Smrg	pcbq->next = call_data;
1821ab64890Smrg    }
1831ab64890Smrg}
1841ab64890Smrg
185eb411b4bSmrgBool
18661b2299dSmrg_XimCbDispatch(Xim xim,
18761b2299dSmrg	       INT16 len,
18861b2299dSmrg	       XPointer data,
1891ab64890Smrg	       XPointer call_data)
1901ab64890Smrg{
1911ab64890Smrg    /* `data' points to the beginning of the packet defined in IM Protocol doc.
1921ab64890Smrg     */
1931ab64890Smrg    int major_opcode = PACKET_TO_MAJOROPCODE(data);
1941ab64890Smrg    XIMID imid = PACKET_TO_IMID(data);
1951ab64890Smrg    XICID icid = PACKET_TO_ICID(data);
1961ab64890Smrg    Xim im = (Xim)call_data;	/* check HM */
1971ab64890Smrg    Xic ic = _XimICOfXICID(im, icid);
1981ab64890Smrg    char* proto;
1991ab64890Smrg    int proto_len;
2001ab64890Smrg
2011ab64890Smrg    /* check validity of im/ic
2021ab64890Smrg     */
2031ab64890Smrg    if ((imid != im->private.proto.imid) || !ic) {
2041ab64890Smrg	return False; /* status = XimCbBadContextID; */
2051ab64890Smrg    }
2061ab64890Smrg
2071ab64890Smrg    /* process pending callbacks
2081ab64890Smrg     */
2091ab64890Smrg    _XimProcessPendingCallbacks(ic);
2101ab64890Smrg
2111ab64890Smrg    /* check if the protocol should be processed here
2121ab64890Smrg     */
2131ab64890Smrg    if (major_opcode > 82) {
2141ab64890Smrg	return False; /* status = XimCbBadOpcode; */
2151ab64890Smrg    }
2161ab64890Smrg    if (!callback_table[major_opcode]) {
2171ab64890Smrg	return False; /* status = XimCbBadOpcode; */
2181ab64890Smrg    }
2191ab64890Smrg
2201ab64890Smrg    /* move the pointer ahead by the IM Protocol packet header size
2211ab64890Smrg     */
2221ab64890Smrg    proto = (char*)data + sz_ximPacketHeader;
2231ab64890Smrg    proto_len = (int)len - sz_ximPacketHeader;
2241ab64890Smrg
2251ab64890Smrg    /* check if it can be processed right away
2261ab64890Smrg     * and if no, queue the protocol, otherwise invoke a callback
2271ab64890Smrg     */
2281ab64890Smrg    if (!_XimIsReadyForProcess(ic)) {
2291ab64890Smrg
2301ab64890Smrg	/* queue the protocol
2311ab64890Smrg	 */
2321ab64890Smrg	XimPendingCallback pcb;
2331ab64890Smrg	char *proto_buf = (proto_len > 0) ? (char*)Xmalloc(proto_len) : NULL;
2341ab64890Smrg
2351ab64890Smrg	pcb = (XimPendingCallback)Xmalloc(sizeof(XimPendingCallbackRec));
2361ab64890Smrg	if (pcb && (proto_len <= 0 || proto_buf)) {
2371ab64890Smrg	    if (proto_len > 0)
2381ab64890Smrg		memcpy(proto_buf, proto, proto_len);
2391ab64890Smrg
2401ab64890Smrg	    pcb->major_opcode = major_opcode;
2411ab64890Smrg	    pcb->im = im;
2421ab64890Smrg	    pcb->ic = ic;
2431ab64890Smrg	    pcb->proto = proto_buf;
2441ab64890Smrg	    pcb->proto_len = proto_len;
2451ab64890Smrg	    pcb->next = (XimPendingCallback)NULL; /* queue is FIFO */
2461ab64890Smrg	    _XimPutCbIntoQueue(ic, pcb);
2471ab64890Smrg	    /* status = XimCbQueued; */
2481ab64890Smrg	} else {
2491ab64890Smrg	    /* status = XimCbError; */
2506cc2b21fSmrg	    Xfree(pcb);
2516cc2b21fSmrg	    Xfree(proto_buf);
2521ab64890Smrg	}
2531ab64890Smrg    }
2541ab64890Smrg    else {
2551ab64890Smrg	/* invoke each callback according to the major opcode.
2561ab64890Smrg	 * `proto' points to the next address of IM-ID and IC-ID.
2571ab64890Smrg	 * `proto_len' specifies the packet length.
2581ab64890Smrg	 */
2591ab64890Smrg	(void) (*callback_table[major_opcode])(im, ic, proto, proto_len);
2601ab64890Smrg    }
2611ab64890Smrg    return True;
2621ab64890Smrg}
2631ab64890Smrg
264eb411b4bSmrgstatic XimCbStatus
26561b2299dSmrg_XimGeometryCallback(Xim im,
26661b2299dSmrg		     Xic ic,
26761b2299dSmrg		     char* proto,
2681ab64890Smrg		     int len)
2691ab64890Smrg{
2701ab64890Smrg    XICCallback* cb = &ic->core.geometry_callback;
2711ab64890Smrg
2721ab64890Smrg    /* invoke the callack
2731ab64890Smrg     */
27461b2299dSmrg    if (cb && cb->callback) {
2751ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
2761ab64890Smrg    }
2771ab64890Smrg    else {
2781ab64890Smrg
2791ab64890Smrg	/* no callback registered
2801ab64890Smrg	 */
2811ab64890Smrg	return XimCbNoCallback;
2821ab64890Smrg    }
2831ab64890Smrg
2841ab64890Smrg    return XimCbSuccess;
2851ab64890Smrg}
2861ab64890Smrg
287eb411b4bSmrgstatic XimCbStatus
28861b2299dSmrg_XimStrConversionCallback(Xim im,
28961b2299dSmrg			  Xic ic,
29061b2299dSmrg			  char* proto,
2911ab64890Smrg			  int len)
2921ab64890Smrg{
2931ab64890Smrg    XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */
2941ab64890Smrg    XIMStringConversionCallbackStruct cbrec;
2951ab64890Smrg
2961ab64890Smrg    /* invoke the callback
2971ab64890Smrg     */
2981ab64890Smrg    if (cb && cb->callback) {
2991ab64890Smrg	int p = XIM_HEADER_SIZE;
3001ab64890Smrg	cbrec.position = (XIMStringConversionPosition)
3011ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
3021ab64890Smrg	cbrec.direction = (XIMCaretDirection)
3031ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
3041ab64890Smrg	cbrec.operation = (XIMStringConversionOperation)
3051ab64890Smrg	    *(CARD32*)&proto[p]; p += sz_CARD32;
3061ab64890Smrg	cbrec.factor = (unsigned short)
3071ab64890Smrg	    *(CARD32*)&proto[p];
3081ab64890Smrg
3091ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec);
3101ab64890Smrg    }
3111ab64890Smrg    else {
3121ab64890Smrg
3131ab64890Smrg	/* no callback registered
3141ab64890Smrg	 */
31561b2299dSmrg	_XimError(im, ic,
31661b2299dSmrg		  (CARD16)XIM_BadSomething,
31761b2299dSmrg		  (INT16)len,
31861b2299dSmrg		  (CARD16)XIM_STR_CONVERSION,
3191ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
3201ab64890Smrg	return XimCbNoCallback;
3211ab64890Smrg    }
3221ab64890Smrg
3231ab64890Smrg    /* send a reply
3241ab64890Smrg     */
3251ab64890Smrg    {
3261ab64890Smrg	CARD8	*buf;
3271ab64890Smrg	INT16	 buf_len;
3281ab64890Smrg	int	 p, length_in_bytes, i;
3291ab64890Smrg
3301ab64890Smrg	/* Assumption:
3311ab64890Smrg	 * `cbrec.text->length' means the string length in characters
3321ab64890Smrg	 */
3331ab64890Smrg	{
3341ab64890Smrg	    length_in_bytes = (cbrec.text->encoding_is_wchar)?
3351ab64890Smrg		sizeof(wchar_t) * cbrec.text->length: /* wchar */
3361ab64890Smrg		strlen(cbrec.text->string.mbs);	/* mb */
33761b2299dSmrg	    buf_len = XIM_HEADER_SIZE +
3381ab64890Smrg		sz_CARD16 +
33961b2299dSmrg		2 + length_in_bytes +
3401ab64890Smrg		XIM_PAD(2 + length_in_bytes) +
3411ab64890Smrg		2 + 2 + sz_CARD32 * cbrec.text->length;
3421ab64890Smrg	    buf = (CARD8*)Xmalloc(buf_len);
3431ab64890Smrg	}
3441ab64890Smrg	_XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len);
3451ab64890Smrg	buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */
3461ab64890Smrg	p = XIM_HEADER_SIZE;
3471ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
3481ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
3491ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16;
3501ab64890Smrg	memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes);
3511ab64890Smrg	p += length_in_bytes;
3521ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length);
3531ab64890Smrg	p += XIM_PAD(2);
3541ab64890Smrg	for (i = 0; i < (int)cbrec.text->length; i++) {
3551ab64890Smrg	    *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i];
3561ab64890Smrg	    p += sz_CARD32;
3571ab64890Smrg	}
3581ab64890Smrg
3591ab64890Smrg	if (!(_XimWriteData(im, buf_len, buf))) {
3601ab64890Smrg	    return XimCbError;
3611ab64890Smrg	}
3621ab64890Smrg	_XimFlushData(im);
3631ab64890Smrg
3641ab64890Smrg	Xfree(buf);
3651ab64890Smrg    }
3661ab64890Smrg
3671ab64890Smrg    return XimCbSuccess;
3681ab64890Smrg}
3691ab64890Smrg
370eb411b4bSmrgstatic XimCbStatus
37161b2299dSmrg_XimPreeditStartCallback(Xim im,
37261b2299dSmrg			 Xic ic,
37361b2299dSmrg			 char* proto,
3741ab64890Smrg			 int len)
3751ab64890Smrg{
3761ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.start_callback;
3771ab64890Smrg    int ret;
3781ab64890Smrg
3791ab64890Smrg    /* invoke the callback
3801ab64890Smrg     */
3811ab64890Smrg    if (cb && cb->callback){
3821ab64890Smrg	ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL);
3831ab64890Smrg    }
3841ab64890Smrg    else {
3851ab64890Smrg
38661b2299dSmrg	/* no callback registered
3871ab64890Smrg	 */
38861b2299dSmrg	_XimError(im, ic,
38961b2299dSmrg		  (CARD16)XIM_BadSomething,
39061b2299dSmrg		  (INT16)len,
39161b2299dSmrg		  (CARD16)XIM_PREEDIT_START,
3921ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
3931ab64890Smrg	return XimCbNoCallback;
3941ab64890Smrg    }
3951ab64890Smrg
3961ab64890Smrg    /* send a reply
3971ab64890Smrg     */
3981ab64890Smrg    {
3991ab64890Smrg	CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4];
4001ab64890Smrg	CARD8 *buf = (CARD8 *)buf32;
4011ab64890Smrg	INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply;
4021ab64890Smrg	int p;
4031ab64890Smrg
4041ab64890Smrg	_XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len);
4051ab64890Smrg	p = XIM_HEADER_SIZE;
4061ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
4071ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
4081ab64890Smrg	*(INT32*)&buf[p]  = (INT32)ret;
4091ab64890Smrg
4101ab64890Smrg	if (!(_XimWriteData(im, buf_len, buf))) {
4111ab64890Smrg	    return XimCbError;
4121ab64890Smrg	}
4131ab64890Smrg	_XimFlushData(im);
4141ab64890Smrg    }
4151ab64890Smrg
4161ab64890Smrg    return XimCbSuccess;
4171ab64890Smrg}
4181ab64890Smrg
419eb411b4bSmrgstatic XimCbStatus
42061b2299dSmrg_XimPreeditDoneCallback(Xim im,
42161b2299dSmrg			Xic ic,
42261b2299dSmrg			char* proto,
4231ab64890Smrg			int len)
4241ab64890Smrg{
4251ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.done_callback;
4261ab64890Smrg
4271ab64890Smrg    /* invoke the callback
4281ab64890Smrg     */
4291ab64890Smrg    if (cb && cb->callback) {
4301ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
4311ab64890Smrg    }
4321ab64890Smrg    else {
4331ab64890Smrg
4341ab64890Smrg	/* no callback registered
4351ab64890Smrg	 */
4361ab64890Smrg	return XimCbNoCallback;
4371ab64890Smrg    }
4381ab64890Smrg
4391ab64890Smrg    return XimCbSuccess;
4401ab64890Smrg}
4411ab64890Smrg
442eb411b4bSmrgstatic void
44361b2299dSmrg_read_text_from_packet(Xim im,
44461b2299dSmrg		       char* buf,
4451ab64890Smrg		       XIMText** text_ptr)
4461ab64890Smrg{
4471ab64890Smrg    int status;
4481ab64890Smrg    XIMText* text;
4491ab64890Smrg    int tmp_len;
4501ab64890Smrg    char* tmp_buf;
4511ab64890Smrg    Status s = 0;
4521ab64890Smrg
4531ab64890Smrg    status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32;
4541ab64890Smrg
4551ab64890Smrg    /* string part
4561ab64890Smrg     */
4571ab64890Smrg    if (status & 0x00000001) /* "no string" bit on */ {
4581ab64890Smrg	buf += sz_CARD16;	/* skip "length of preedit string" */
4591ab64890Smrg	buf += 2;		/* pad */
4601ab64890Smrg	*text_ptr = (XIMText*)NULL;
4611ab64890Smrg	return;
4621ab64890Smrg    }
4631ab64890Smrg
4641ab64890Smrg    *text_ptr = text = (XIMText*)Xmalloc(sizeof(XIMText));
4651ab64890Smrg    if (text == (XIMText*)NULL) return;
4661ab64890Smrg
4671ab64890Smrg	tmp_len = (int)*(CARD16*)buf;
4681ab64890Smrg	buf += sz_CARD16;
4691ab64890Smrg	if ((tmp_buf = (char*)Xmalloc(tmp_len + 1))) {
4701ab64890Smrg	    memcpy(tmp_buf, buf, tmp_len);
4711ab64890Smrg	    tmp_buf[tmp_len] = '\0';
4721ab64890Smrg
4731ab64890Smrg	    text->encoding_is_wchar = False;
47461b2299dSmrg	    text->length = im->methods->ctstombs((XIM)im,
47561b2299dSmrg					tmp_buf, tmp_len,
4761ab64890Smrg					NULL, 0, &s); /* CT? HM */
4771ab64890Smrg	    if (s != XLookupNone) {
4781ab64890Smrg#ifndef NO_DEC_I18N_FIX
4791ab64890Smrg                /* Allow for NULL-terminated */
4801ab64890Smrg                if ((text->string.multi_byte =
4811ab64890Smrg                    (char*)Xmalloc(text->length *
4821ab64890Smrg                      XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) {
4831ab64890Smrg#else
4841ab64890Smrg		if (text->string.multi_byte = (char*)Xmalloc(text->length+1)) {
4851ab64890Smrg#endif
4861ab64890Smrg			int tmp;
4871ab64890Smrg#ifndef NO_DEC_I18N_FIX
4881ab64890Smrg                        char *char_tmp;
4891ab64890Smrg                        int char_len;
4901ab64890Smrg#endif
4911ab64890Smrg			tmp = im->methods->ctstombs((XIM)im,
49261b2299dSmrg					   tmp_buf, tmp_len,
4931ab64890Smrg#ifndef NO_DEC_I18N_FIX
4941ab64890Smrg                                           text->string.multi_byte,
4951ab64890Smrg                                           text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1,
4961ab64890Smrg#else
49761b2299dSmrg					   text->string.multi_byte, text->length,
4981ab64890Smrg#endif
4991ab64890Smrg					   &s);
5001ab64890Smrg			text->string.multi_byte[tmp] = '\0';
5011ab64890Smrg#ifndef NO_DEC_I18N_FIX
5021ab64890Smrg                        text->length = 0;
5031ab64890Smrg                        char_tmp =  text->string.multi_byte;
5041ab64890Smrg                        while (*char_tmp != '\0') {
5051ab64890Smrg                              char_len = mblen(char_tmp, strlen(char_tmp));
5061ab64890Smrg                              char_tmp = char_tmp + char_len;
5071ab64890Smrg                              (text->length)++;
5081ab64890Smrg                        }
5091ab64890Smrg#endif
5101ab64890Smrg		}
5111ab64890Smrg	    }
5121ab64890Smrg	    else {
5131ab64890Smrg		text->length = 0;
5141ab64890Smrg		text->string.multi_byte = NULL;
5151ab64890Smrg	    }
5161ab64890Smrg
5171ab64890Smrg	    Xfree(tmp_buf);
5181ab64890Smrg	}
5191ab64890Smrg	buf += tmp_len;
5201ab64890Smrg
5211ab64890Smrg	buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */
5221ab64890Smrg
5231ab64890Smrg    /* feedback part
5241ab64890Smrg     */
5251ab64890Smrg    if (status & 0x00000002) /* "no feedback" bit on */ {
5261ab64890Smrg	text->feedback = (XIMFeedback*)NULL;
5271ab64890Smrg    }
5281ab64890Smrg    else {
5291ab64890Smrg	int i, j;
5301ab64890Smrg
5311ab64890Smrg	i = (int)*(CARD16*)buf; buf += sz_CARD16;
5321ab64890Smrg	buf += sz_CARD16; /* skip `unused' */
5331ab64890Smrg	text->feedback = (XIMFeedback*)Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32)));
5341ab64890Smrg	j = 0;
5351ab64890Smrg	while (i > 0) {
5361ab64890Smrg	    text->feedback[j] = (XIMFeedback)*(CARD32*)buf;
5371ab64890Smrg	    buf += sz_CARD32;
5381ab64890Smrg	    i -= sz_CARD32;
5391ab64890Smrg	    j++;
5401ab64890Smrg	}
54161b2299dSmrg	/*
5421ab64890Smrg	 * text->length tells how long both the status string and
5431ab64890Smrg	 * the feedback array are. If there's "no string" the
5441ab64890Smrg	 * text->length was set to zero previously. See above.
5451ab64890Smrg	 * But if there is feedback (i.e. not "no feedback") then
5461ab64890Smrg	 * we need to convey the length of the feedback array.
5471ab64890Smrg	 * It might have been better if the protocol sent two
5481ab64890Smrg	 * different values, one for the length of the status
5491ab64890Smrg	 * string and one for the length of the feedback array.
5501ab64890Smrg	 */
5511ab64890Smrg	if (status & 0x00000001) /* "no string" bit on */ {
5521ab64890Smrg	    text->length = j;
5531ab64890Smrg	}
5541ab64890Smrg    }
5551ab64890Smrg}
5561ab64890Smrg
557eb411b4bSmrgstatic void
5581ab64890Smrg_free_memory_for_text(XIMText* text)
5591ab64890Smrg{
5601ab64890Smrg    if (text) {
5611ab64890Smrg	if (text->string.multi_byte)
5621ab64890Smrg	    Xfree(text->string.multi_byte);
5631ab64890Smrg	if (text->feedback)
5641ab64890Smrg	    Xfree(text->feedback);
5651ab64890Smrg	Xfree(text);
5661ab64890Smrg    }
5671ab64890Smrg}
5681ab64890Smrg
569eb411b4bSmrgstatic XimCbStatus
57061b2299dSmrg_XimPreeditDrawCallback(Xim im,
57161b2299dSmrg			Xic ic,
57261b2299dSmrg			char* proto,
5731ab64890Smrg			int len)
5741ab64890Smrg{
5751ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.draw_callback;
5761ab64890Smrg    XIMPreeditDrawCallbackStruct cbs;
5771ab64890Smrg
5781ab64890Smrg    /* invoke the callback
5791ab64890Smrg     */
5801ab64890Smrg    if (cb && cb->callback) {
5811ab64890Smrg	cbs.caret      = (int)*(INT32*)proto; proto += sz_INT32;
5821ab64890Smrg	cbs.chg_first  = (int)*(INT32*)proto; proto += sz_INT32;
5831ab64890Smrg	cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32;
5841ab64890Smrg	_read_text_from_packet(im, proto, &cbs.text);
5851ab64890Smrg
5861ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
5871ab64890Smrg
5881ab64890Smrg	_free_memory_for_text((XIMText*)cbs.text);
5891ab64890Smrg    }
5901ab64890Smrg    else {
5911ab64890Smrg
5921ab64890Smrg	/* no callback registered
5931ab64890Smrg	 */
5941ab64890Smrg	return XimCbNoCallback;
5951ab64890Smrg    }
5961ab64890Smrg
5971ab64890Smrg    return XimCbSuccess;
5981ab64890Smrg}
5991ab64890Smrg
600eb411b4bSmrgstatic XimCbStatus
60161b2299dSmrg_XimPreeditCaretCallback(Xim im,
60261b2299dSmrg			 Xic ic,
6031ab64890Smrg			 char* proto,
6041ab64890Smrg			 int len)
6051ab64890Smrg{
6061ab64890Smrg    XICCallback* cb = &ic->core.preedit_attr.caret_callback;
6071ab64890Smrg    XIMPreeditCaretCallbackStruct cbs;
6081ab64890Smrg
6091ab64890Smrg    /* invoke the callback
6101ab64890Smrg     */
6111ab64890Smrg    if (cb && cb->callback) {
6121ab64890Smrg	cbs.position  = (int)*(INT32*)proto; proto += sz_INT32;
6131ab64890Smrg	cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32;
6141ab64890Smrg	cbs.style     = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32;
6151ab64890Smrg
6161ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
6171ab64890Smrg    }
6181ab64890Smrg    else {
6191ab64890Smrg
62061b2299dSmrg	/* no callback registered
6211ab64890Smrg	 */
62261b2299dSmrg	_XimError(im, ic,
62361b2299dSmrg		  (CARD16)XIM_BadSomething,
62461b2299dSmrg		  (INT16)len,
62561b2299dSmrg		  (CARD16)XIM_PREEDIT_CARET,
6261ab64890Smrg		  (char*)proto); /* send XIM_ERROR */
6271ab64890Smrg	return XimCbNoCallback;
6281ab64890Smrg    }
6291ab64890Smrg
6301ab64890Smrg    /* Send a reply
6311ab64890Smrg     */
6321ab64890Smrg    {
6331ab64890Smrg	CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply];
6341ab64890Smrg	INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply;
6351ab64890Smrg	int p;
6361ab64890Smrg
6371ab64890Smrg	_XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len);
6381ab64890Smrg	p = XIM_HEADER_SIZE;
6391ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
6401ab64890Smrg	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
6411ab64890Smrg	*(CARD32*)&buf[p] = (CARD32)cbs.position;
6421ab64890Smrg
6431ab64890Smrg	if (!(_XimWriteData(im, len, buf))) {
6441ab64890Smrg	    return XimCbError;
6451ab64890Smrg	}
6461ab64890Smrg	_XimFlushData(im);
6471ab64890Smrg    }
6481ab64890Smrg
6491ab64890Smrg    return XimCbSuccess;
6501ab64890Smrg}
6511ab64890Smrg
652eb411b4bSmrgstatic XimCbStatus
65361b2299dSmrg_XimStatusStartCallback(Xim im,
65461b2299dSmrg			Xic ic,
65561b2299dSmrg			char* proto,
6561ab64890Smrg			int len)
6571ab64890Smrg{
6581ab64890Smrg    XICCallback* cb = &ic->core.status_attr.start_callback;
6591ab64890Smrg
6601ab64890Smrg    /* invoke the callback
6611ab64890Smrg     */
6621ab64890Smrg    if (cb && cb->callback) {
6631ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
6641ab64890Smrg    }
6651ab64890Smrg    else {
6661ab64890Smrg
6671ab64890Smrg	/* no callback registered
6681ab64890Smrg	 */
6691ab64890Smrg	return XimCbNoCallback;
6701ab64890Smrg    }
6711ab64890Smrg
6721ab64890Smrg    return XimCbSuccess;
6731ab64890Smrg}
6741ab64890Smrg
675eb411b4bSmrgstatic XimCbStatus
67661b2299dSmrg_XimStatusDoneCallback(Xim im,
67761b2299dSmrg		       Xic ic,
67861b2299dSmrg		       char* proto,
6791ab64890Smrg		       int len)
6801ab64890Smrg{
6811ab64890Smrg    XICCallback* cb = &ic->core.status_attr.done_callback;
6821ab64890Smrg
6831ab64890Smrg    /* invoke the callback
6841ab64890Smrg     */
6851ab64890Smrg    if (cb && cb->callback) {
6861ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
6871ab64890Smrg    }
6881ab64890Smrg    else {
6891ab64890Smrg
6901ab64890Smrg	/* no callback registered
6911ab64890Smrg	 */
6921ab64890Smrg	return XimCbNoCallback;
6931ab64890Smrg    }
6941ab64890Smrg
6951ab64890Smrg    return XimCbSuccess;
6961ab64890Smrg}
6971ab64890Smrg
698eb411b4bSmrgstatic XimCbStatus
69961b2299dSmrg_XimStatusDrawCallback(Xim im,
70061b2299dSmrg		       Xic ic,
70161b2299dSmrg		       char* proto,
7021ab64890Smrg		       int len)
7031ab64890Smrg{
7041ab64890Smrg    XICCallback* cb = &ic->core.status_attr.draw_callback;
7051ab64890Smrg    XIMStatusDrawCallbackStruct cbs;
7061ab64890Smrg
7071ab64890Smrg    /* invoke the callback
7081ab64890Smrg     */
7091ab64890Smrg    if (cb && cb->callback) {
7101ab64890Smrg	cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32;
7111ab64890Smrg	if (cbs.type == XIMTextType) {
7121ab64890Smrg	    _read_text_from_packet(im, proto, &cbs.data.text);
7131ab64890Smrg	}
7141ab64890Smrg	else if (cbs.type == XIMBitmapType) {
7151ab64890Smrg	    cbs.data.bitmap = (Pixmap)*(CARD32*)proto;
7161ab64890Smrg	}
7171ab64890Smrg
7181ab64890Smrg	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
7191ab64890Smrg
7201ab64890Smrg	if (cbs.type == XIMTextType)
7211ab64890Smrg	    _free_memory_for_text((XIMText *)cbs.data.text);
7221ab64890Smrg    }
7231ab64890Smrg    else {
7241ab64890Smrg
7251ab64890Smrg	/* no callback registered
7261ab64890Smrg	 */
7271ab64890Smrg	return XimCbNoCallback;
7281ab64890Smrg    }
7291ab64890Smrg
7301ab64890Smrg    return XimCbSuccess;
7311ab64890Smrg}
7321ab64890Smrg
733eb411b4bSmrgstatic XimCbStatus
7341ab64890Smrg_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len )
7351ab64890Smrg{
7361ab64890Smrg    XICCallback	*cb = &ic->core.preedit_attr.state_notify_callback;
7371ab64890Smrg
7381ab64890Smrg    /* invoke the callack
7391ab64890Smrg     */
74061b2299dSmrg    if( cb  &&  cb->callback ) {
7411ab64890Smrg	XIMPreeditStateNotifyCallbackStruct cbrec;
7421ab64890Smrg
7431ab64890Smrg	cbrec.state = *(BITMASK32 *)proto;
7441ab64890Smrg	(*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec );
7451ab64890Smrg    }
7461ab64890Smrg    else {
7471ab64890Smrg	/* no callback registered
7481ab64890Smrg	 */
7491ab64890Smrg	return XimCbNoCallback;
7501ab64890Smrg    }
7511ab64890Smrg
7521ab64890Smrg    return XimCbSuccess;
7531ab64890Smrg}
7541ab64890Smrg
755