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