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