imCallbk.c revision b4ee4795
1/***********************************************************************
2Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
3Copyright 1994 by FUJITSU LIMITED
4Copyright 1994 by Sony Corporation
5
6                        All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and its
9documentation for any purpose and without fee is hereby granted,
10provided that the above copyright notice appear in all copies and that
11both that copyright notice and this permission notice appear in
12supporting documentation, and that the names of Digital, FUJITSU
13LIMITED and Sony Corporation not be used in advertising or publicity
14pertaining to distribution of the software without specific, written
15prior permission.
16
17DIGITAL, FUJITSU LIMITED AND SONY CORPORATION DISCLAIMS ALL WARRANTIES
18WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
19MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL, FUJITSU LIMITED
20AND SONY CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
22USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
23OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24PERFORMANCE OF THIS SOFTWARE.
25
26  Author: Hiroyuki Miyamoto  Digital Equipment Corporation
27                             miyamoto@jrd.dec.com
28  Modifier: Takashi Fujiwara FUJITSU LIMITED
29			     fujiwara@a80.tech.yk.fujitsu.co.jp
30	    Makoto Wakamatsu Sony Corporation
31		 	     makoto@sm.sony.co.jp
32
33***********************************************************************/
34
35#ifdef HAVE_CONFIG_H
36#include <config.h>
37#endif
38#include "Xlibint.h"
39#include "Xlcint.h"
40#include "Ximint.h"
41#include "XlcPubI.h"
42#ifdef X_LOCALE
43#define mblen(a,b)	_Xmblen(a,b)
44extern int _Xmblen ();
45#endif
46
47#define sz_CARD8                 1
48#define sz_INT8                  1
49#define sz_CARD16                2
50#define sz_INT16                 2
51#define sz_BITMASK16             sz_CARD16
52#define sz_CARD32                4
53#define sz_INT32                 4
54#define sz_BITMASK32             sz_CARD32
55#define sz_XIMID                 sizeof(XIMID)
56#define sz_XICID                 sizeof(XICID)
57#define sz_XIMATTRID             sizeof(XIMATTRID)
58#define sz_XICATTRID             sizeof(XICATTRID)
59#define sz_ximPacketHeader       (XIM_HEADER_SIZE + sz_XIMID + sz_XICID)
60#define sz_ximGeometry           0
61#define sz_ximStrConversion      (sz_CARD32 + sz_CARD32 + sz_CARD32 + sz_CARD32)
62#define sz_ximPreeditStart       0
63#define sz_ximPreeditStartReply  sz_INT32
64#define sz_ximPreeditCaret       (sz_INT32 + sz_CARD32 + sz_CARD32)
65#define sz_ximPreeditCaretReply  sz_CARD32
66#define sz_ximPreeditDone        0
67#define sz_ximStatusStart        0
68#define sz_ximStatusDone         0
69
70typedef enum {
71    XimCbSuccess,
72    XimCbNoCallback,
73    XimCbError,
74    XimCbQueued,
75    XimCbBadContextID,
76    XimCbBadOpcode
77} XimCbStatus;
78
79typedef XimCbStatus (*XimCb)(
80			     Xim, Xic, char*, int
81			     );
82
83#define PACKET_TO_MAJOROPCODE(p) (*(CARD8*)((CARD8*)(p)))
84#define PACKET_TO_MINOROPCODE(p) (*(CARD8*)((CARD8*)(p) + sz_CARD8))
85#define PACKET_TO_LENGTH(p) (*(CARD16*)((CARD8*)(p) + sz_CARD8 + sz_CARD8))
86#define PACKET_TO_IMID(p) (*(XIMID*)((CARD8*)(p) + XIM_HEADER_SIZE))
87#define PACKET_TO_ICID(p) (*(XICID*)((CARD8*)(p) + XIM_HEADER_SIZE + sz_XIMID))
88
89#define _XimWriteData(im,len,data) \
90    (im->private.proto.write((im),(len),(XPointer)(data)))
91#define _XimReadData(im,buf,buf_len,len) \
92    (im->private.proto.read((im),(XPointer)(buf),(buf_len),&(len)))
93#define _XimFlushData(im) im->private.proto.flush((im))
94
95Private XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int);
96Private XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int);
97Private XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int);
98Private XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int);
99Private void _free_memory_for_text(XIMText*);
100Private XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int);
101Private XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int);
102Private XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int);
103Private XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int);
104Private XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int);
105Private XimCbStatus _XimPreeditStateNotifyCallback(Xim, Xic, char *, int);
106
107#if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32))
108#define RConst /**/
109#else
110#define RConst const
111#endif
112
113/* NOTE:
114 * the table below depends on the protocol number
115 * defined in the IM Protocol document.
116 */
117static RConst XimCb callback_table[] = {
118    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #000-009 */
119    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #010-019 */
120    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #020-029 */
121    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #030-039 */
122    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #040-049 */
123    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #050-059 */
124    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* #060-069 */
125    _XimGeometryCallback,	/* #070 */
126    _XimStrConversionCallback,	/* #071 */
127    NULL,			/* #072 */
128    _XimPreeditStartCallback,	/* #073 */
129    NULL,			/* #074 */
130    _XimPreeditDrawCallback,	/* #075 */
131    _XimPreeditCaretCallback,	/* #076 */
132    NULL,			/* #077 */
133    _XimPreeditDoneCallback,	/* #078 */
134    _XimStatusStartCallback,	/* #079 */
135    _XimStatusDrawCallback,	/* #080 */
136    _XimStatusDoneCallback,	/* #081 */
137    _XimPreeditStateNotifyCallback	/* #082 */
138    };
139
140
141Private Bool
142_XimIsReadyForProcess(Xic ic)
143{
144    return(!ic->private.proto.waitCallback); /* check HM */
145}
146
147Private void
148_XimProcessPendingCallbacks(Xic ic)
149{
150    XimPendingCallback pcbq;
151
152    while (((pcbq = ic->private.proto.pend_cb_que) != (XimPendingCallback)NULL)
153	   && _XimIsReadyForProcess(ic)) {
154	(void) (*callback_table[pcbq->major_opcode])(pcbq->im,
155						     pcbq->ic,
156						     pcbq->proto,
157						     pcbq->proto_len);
158	ic->private.proto.pend_cb_que = pcbq->next;
159	Xfree(pcbq->proto);	/* free memory of XimPendingCallback */
160	Xfree(pcbq);
161    }
162}
163
164Private void
165_XimPutCbIntoQueue(Xic ic, XimPendingCallback call_data)
166{
167    XimPendingCallback pcbq = ic->private.proto.pend_cb_que;
168
169    /* Queuing is FIFO
170     */
171    while (pcbq != (XimPendingCallback)NULL) {
172	if (pcbq->next == (XimPendingCallback)NULL) {
173	    break;
174	}
175	pcbq = pcbq->next;
176    }
177    if (pcbq == (XimPendingCallback)NULL) {
178	ic->private.proto.pend_cb_que = call_data;
179    }
180    else {
181	pcbq->next = call_data;
182    }
183}
184
185Public Bool
186_XimCbDispatch(Xim xim,
187	       INT16 len,
188	       XPointer data,
189	       XPointer call_data)
190{
191    /* `data' points to the beginning of the packet defined in IM Protocol doc.
192     */
193    int major_opcode = PACKET_TO_MAJOROPCODE(data);
194    XIMID imid = PACKET_TO_IMID(data);
195    XICID icid = PACKET_TO_ICID(data);
196    Xim im = (Xim)call_data;	/* check HM */
197    Xic ic = _XimICOfXICID(im, icid);
198    char* proto;
199    int proto_len;
200
201    /* check validity of im/ic
202     */
203    if ((imid != im->private.proto.imid) || !ic) {
204	return False; /* status = XimCbBadContextID; */
205    }
206
207    /* process pending callbacks
208     */
209    _XimProcessPendingCallbacks(ic);
210
211    /* check if the protocol should be processed here
212     */
213    if (major_opcode > 82) {
214	return False; /* status = XimCbBadOpcode; */
215    }
216    if (!callback_table[major_opcode]) {
217	return False; /* status = XimCbBadOpcode; */
218    }
219
220    /* move the pointer ahead by the IM Protocol packet header size
221     */
222    proto = (char*)data + sz_ximPacketHeader;
223    proto_len = (int)len - sz_ximPacketHeader;
224
225    /* check if it can be processed right away
226     * and if no, queue the protocol, otherwise invoke a callback
227     */
228    if (!_XimIsReadyForProcess(ic)) {
229
230	/* queue the protocol
231	 */
232	XimPendingCallback pcb;
233	char *proto_buf = (proto_len > 0) ? (char*)Xmalloc(proto_len) : NULL;
234
235	pcb = (XimPendingCallback)Xmalloc(sizeof(XimPendingCallbackRec));
236	if (pcb && (proto_len <= 0 || proto_buf)) {
237	    if (proto_len > 0)
238		memcpy(proto_buf, proto, proto_len);
239
240	    pcb->major_opcode = major_opcode;
241	    pcb->im = im;
242	    pcb->ic = ic;
243	    pcb->proto = proto_buf;
244	    pcb->proto_len = proto_len;
245	    pcb->next = (XimPendingCallback)NULL; /* queue is FIFO */
246	    _XimPutCbIntoQueue(ic, pcb);
247	    /* status = XimCbQueued; */
248	} else {
249	    /* status = XimCbError; */
250	}
251    }
252    else {
253	/* invoke each callback according to the major opcode.
254	 * `proto' points to the next address of IM-ID and IC-ID.
255	 * `proto_len' specifies the packet length.
256	 */
257	(void) (*callback_table[major_opcode])(im, ic, proto, proto_len);
258    }
259    return True;
260}
261
262Private XimCbStatus
263_XimGeometryCallback(Xim im,
264		     Xic ic,
265		     char* proto,
266		     int len)
267{
268    XICCallback* cb = &ic->core.geometry_callback;
269
270    /* invoke the callack
271     */
272    if (cb && cb->callback) {
273	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
274    }
275    else {
276
277	/* no callback registered
278	 */
279	return XimCbNoCallback;
280    }
281
282    return XimCbSuccess;
283}
284
285Private XimCbStatus
286_XimStrConversionCallback(Xim im,
287			  Xic ic,
288			  char* proto,
289			  int len)
290{
291    XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */
292    XIMStringConversionCallbackStruct cbrec;
293
294    /* invoke the callback
295     */
296    if (cb && cb->callback) {
297	int p = XIM_HEADER_SIZE;
298	cbrec.position = (XIMStringConversionPosition)
299	    *(CARD32*)&proto[p]; p += sz_CARD32;
300	cbrec.direction = (XIMCaretDirection)
301	    *(CARD32*)&proto[p]; p += sz_CARD32;
302	cbrec.operation = (XIMStringConversionOperation)
303	    *(CARD32*)&proto[p]; p += sz_CARD32;
304	cbrec.factor = (unsigned short)
305	    *(CARD32*)&proto[p];
306
307	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec);
308    }
309    else {
310
311	/* no callback registered
312	 */
313	_XimError(im, ic,
314		  (CARD16)XIM_BadSomething,
315		  (INT16)len,
316		  (CARD16)XIM_STR_CONVERSION,
317		  (char*)proto); /* send XIM_ERROR */
318	return XimCbNoCallback;
319    }
320
321    /* send a reply
322     */
323    {
324	CARD8	*buf;
325	INT16	 buf_len;
326	int	 p, length_in_bytes, i;
327
328	/* Assumption:
329	 * `cbrec.text->length' means the string length in characters
330	 */
331	{
332	    length_in_bytes = (cbrec.text->encoding_is_wchar)?
333		sizeof(wchar_t) * cbrec.text->length: /* wchar */
334		strlen(cbrec.text->string.mbs);	/* mb */
335	    buf_len = XIM_HEADER_SIZE +
336		sz_CARD16 +
337		2 + length_in_bytes +
338		XIM_PAD(2 + length_in_bytes) +
339		2 + 2 + sz_CARD32 * cbrec.text->length;
340	    buf = (CARD8*)Xmalloc(buf_len);
341	}
342	_XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len);
343	buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */
344	p = XIM_HEADER_SIZE;
345	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
346	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
347	*(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16;
348	memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes);
349	p += length_in_bytes;
350	*(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length);
351	p += XIM_PAD(2);
352	for (i = 0; i < (int)cbrec.text->length; i++) {
353	    *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i];
354	    p += sz_CARD32;
355	}
356
357	if (!(_XimWriteData(im, buf_len, buf))) {
358	    return XimCbError;
359	}
360	_XimFlushData(im);
361
362	Xfree(buf);
363    }
364
365    return XimCbSuccess;
366}
367
368Private XimCbStatus
369_XimPreeditStartCallback(Xim im,
370			 Xic ic,
371			 char* proto,
372			 int len)
373{
374    XICCallback* cb = &ic->core.preedit_attr.start_callback;
375    int ret;
376
377    /* invoke the callback
378     */
379    if (cb && cb->callback){
380	ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL);
381    }
382    else {
383
384	/* no callback registered
385	 */
386	_XimError(im, ic,
387		  (CARD16)XIM_BadSomething,
388		  (INT16)len,
389		  (CARD16)XIM_PREEDIT_START,
390		  (char*)proto); /* send XIM_ERROR */
391	return XimCbNoCallback;
392    }
393
394    /* send a reply
395     */
396    {
397	CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4];
398	CARD8 *buf = (CARD8 *)buf32;
399	INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply;
400	int p;
401
402	_XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len);
403	p = XIM_HEADER_SIZE;
404	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
405	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
406	*(INT32*)&buf[p]  = (INT32)ret;
407
408	if (!(_XimWriteData(im, buf_len, buf))) {
409	    return XimCbError;
410	}
411	_XimFlushData(im);
412    }
413
414    return XimCbSuccess;
415}
416
417Private XimCbStatus
418_XimPreeditDoneCallback(Xim im,
419			Xic ic,
420			char* proto,
421			int len)
422{
423    XICCallback* cb = &ic->core.preedit_attr.done_callback;
424
425    /* invoke the callback
426     */
427    if (cb && cb->callback) {
428	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
429    }
430    else {
431
432	/* no callback registered
433	 */
434	return XimCbNoCallback;
435    }
436
437    return XimCbSuccess;
438}
439
440Private void
441_read_text_from_packet(Xim im,
442		       char* buf,
443		       XIMText** text_ptr)
444{
445    int status;
446    XIMText* text;
447    int tmp_len;
448    char* tmp_buf;
449    Status s = 0;
450
451    status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32;
452
453    /* string part
454     */
455    if (status & 0x00000001) /* "no string" bit on */ {
456	buf += sz_CARD16;	/* skip "length of preedit string" */
457	buf += 2;		/* pad */
458	*text_ptr = (XIMText*)NULL;
459	return;
460    }
461
462    *text_ptr = text = (XIMText*)Xmalloc(sizeof(XIMText));
463    if (text == (XIMText*)NULL) return;
464
465	tmp_len = (int)*(CARD16*)buf;
466	buf += sz_CARD16;
467	if ((tmp_buf = (char*)Xmalloc(tmp_len + 1))) {
468	    memcpy(tmp_buf, buf, tmp_len);
469	    tmp_buf[tmp_len] = '\0';
470
471	    text->encoding_is_wchar = False;
472	    text->length = im->methods->ctstombs((XIM)im,
473					tmp_buf, tmp_len,
474					NULL, 0, &s); /* CT? HM */
475	    if (s != XLookupNone) {
476#ifndef NO_DEC_I18N_FIX
477                /* Allow for NULL-terminated */
478                if ((text->string.multi_byte =
479                    (char*)Xmalloc(text->length *
480                      XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) {
481#else
482		if (text->string.multi_byte = (char*)Xmalloc(text->length+1)) {
483#endif
484			int tmp;
485#ifndef NO_DEC_I18N_FIX
486                        char *char_tmp;
487                        int char_len;
488#endif
489			tmp = im->methods->ctstombs((XIM)im,
490					   tmp_buf, tmp_len,
491#ifndef NO_DEC_I18N_FIX
492                                           text->string.multi_byte,
493                                           text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1,
494#else
495					   text->string.multi_byte, text->length,
496#endif
497					   &s);
498			text->string.multi_byte[tmp] = '\0';
499#ifndef NO_DEC_I18N_FIX
500                        text->length = 0;
501                        char_tmp =  text->string.multi_byte;
502                        while (*char_tmp != '\0') {
503                              char_len = mblen(char_tmp, strlen(char_tmp));
504                              char_tmp = char_tmp + char_len;
505                              (text->length)++;
506                        }
507#endif
508		}
509	    }
510	    else {
511		text->length = 0;
512		text->string.multi_byte = NULL;
513	    }
514
515	    Xfree(tmp_buf);
516	}
517	buf += tmp_len;
518
519	buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */
520
521    /* feedback part
522     */
523    if (status & 0x00000002) /* "no feedback" bit on */ {
524	text->feedback = (XIMFeedback*)NULL;
525    }
526    else {
527	int i, j;
528
529	i = (int)*(CARD16*)buf; buf += sz_CARD16;
530	buf += sz_CARD16; /* skip `unused' */
531	text->feedback = (XIMFeedback*)Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32)));
532	j = 0;
533	while (i > 0) {
534	    text->feedback[j] = (XIMFeedback)*(CARD32*)buf;
535	    buf += sz_CARD32;
536	    i -= sz_CARD32;
537	    j++;
538	}
539	/*
540	 * text->length tells how long both the status string and
541	 * the feedback array are. If there's "no string" the
542	 * text->length was set to zero previously. See above.
543	 * But if there is feedback (i.e. not "no feedback") then
544	 * we need to convey the length of the feedback array.
545	 * It might have been better if the protocol sent two
546	 * different values, one for the length of the status
547	 * string and one for the length of the feedback array.
548	 */
549	if (status & 0x00000001) /* "no string" bit on */ {
550	    text->length = j;
551	}
552    }
553}
554
555Private void
556_free_memory_for_text(XIMText* text)
557{
558    if (text) {
559	if (text->string.multi_byte)
560	    Xfree(text->string.multi_byte);
561	if (text->feedback)
562	    Xfree(text->feedback);
563	Xfree(text);
564    }
565}
566
567Private XimCbStatus
568_XimPreeditDrawCallback(Xim im,
569			Xic ic,
570			char* proto,
571			int len)
572{
573    XICCallback* cb = &ic->core.preedit_attr.draw_callback;
574    XIMPreeditDrawCallbackStruct cbs;
575
576    /* invoke the callback
577     */
578    if (cb && cb->callback) {
579	cbs.caret      = (int)*(INT32*)proto; proto += sz_INT32;
580	cbs.chg_first  = (int)*(INT32*)proto; proto += sz_INT32;
581	cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32;
582	_read_text_from_packet(im, proto, &cbs.text);
583
584	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
585
586	_free_memory_for_text((XIMText*)cbs.text);
587    }
588    else {
589
590	/* no callback registered
591	 */
592	return XimCbNoCallback;
593    }
594
595    return XimCbSuccess;
596}
597
598Private XimCbStatus
599_XimPreeditCaretCallback(Xim im,
600			 Xic ic,
601			 char* proto,
602			 int len)
603{
604    XICCallback* cb = &ic->core.preedit_attr.caret_callback;
605    XIMPreeditCaretCallbackStruct cbs;
606
607    /* invoke the callback
608     */
609    if (cb && cb->callback) {
610	cbs.position  = (int)*(INT32*)proto; proto += sz_INT32;
611	cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32;
612	cbs.style     = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32;
613
614	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
615    }
616    else {
617
618	/* no callback registered
619	 */
620	_XimError(im, ic,
621		  (CARD16)XIM_BadSomething,
622		  (INT16)len,
623		  (CARD16)XIM_PREEDIT_CARET,
624		  (char*)proto); /* send XIM_ERROR */
625	return XimCbNoCallback;
626    }
627
628    /* Send a reply
629     */
630    {
631	CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply];
632	INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply;
633	int p;
634
635	_XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len);
636	p = XIM_HEADER_SIZE;
637	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
638	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
639	*(CARD32*)&buf[p] = (CARD32)cbs.position;
640
641	if (!(_XimWriteData(im, len, buf))) {
642	    return XimCbError;
643	}
644	_XimFlushData(im);
645    }
646
647    return XimCbSuccess;
648}
649
650Private XimCbStatus
651_XimStatusStartCallback(Xim im,
652			Xic ic,
653			char* proto,
654			int len)
655{
656    XICCallback* cb = &ic->core.status_attr.start_callback;
657
658    /* invoke the callback
659     */
660    if (cb && cb->callback) {
661	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
662    }
663    else {
664
665	/* no callback registered
666	 */
667	return XimCbNoCallback;
668    }
669
670    return XimCbSuccess;
671}
672
673Private XimCbStatus
674_XimStatusDoneCallback(Xim im,
675		       Xic ic,
676		       char* proto,
677		       int len)
678{
679    XICCallback* cb = &ic->core.status_attr.done_callback;
680
681    /* invoke the callback
682     */
683    if (cb && cb->callback) {
684	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
685    }
686    else {
687
688	/* no callback registered
689	 */
690	return XimCbNoCallback;
691    }
692
693    return XimCbSuccess;
694}
695
696Private XimCbStatus
697_XimStatusDrawCallback(Xim im,
698		       Xic ic,
699		       char* proto,
700		       int len)
701{
702    XICCallback* cb = &ic->core.status_attr.draw_callback;
703    XIMStatusDrawCallbackStruct cbs;
704
705    /* invoke the callback
706     */
707    if (cb && cb->callback) {
708	cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32;
709	if (cbs.type == XIMTextType) {
710	    _read_text_from_packet(im, proto, &cbs.data.text);
711	}
712	else if (cbs.type == XIMBitmapType) {
713	    cbs.data.bitmap = (Pixmap)*(CARD32*)proto;
714	}
715
716	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
717
718	if (cbs.type == XIMTextType)
719	    _free_memory_for_text((XIMText *)cbs.data.text);
720    }
721    else {
722
723	/* no callback registered
724	 */
725	return XimCbNoCallback;
726    }
727
728    return XimCbSuccess;
729}
730
731Private XimCbStatus
732_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len )
733{
734    XICCallback	*cb = &ic->core.preedit_attr.state_notify_callback;
735
736    /* invoke the callack
737     */
738    if( cb  &&  cb->callback ) {
739	XIMPreeditStateNotifyCallbackStruct cbrec;
740
741	cbrec.state = *(BITMASK32 *)proto;
742	(*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec );
743    }
744    else {
745	/* no callback registered
746	 */
747	return XimCbNoCallback;
748    }
749
750    return XimCbSuccess;
751}
752
753