imCallbk.c revision 818534a1
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
95static XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int);
96static XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int);
97static XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int);
98static XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int);
99static void _free_memory_for_text(XIMText*);
100static XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int);
101static XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int);
102static XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int);
103static XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int);
104static XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int);
105static 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
141static Bool
142_XimIsReadyForProcess(Xic ic)
143{
144    return(!ic->private.proto.waitCallback); /* check HM */
145}
146
147static 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
164static 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
185Bool
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) ? Xmalloc(proto_len) : NULL;
234
235	pcb = 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	    Xfree(pcb);
251	    Xfree(proto_buf);
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
264static 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
287static 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 = 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
370static 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
419static 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
442static 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 = Xmalloc(sizeof(XIMText));
465    if (text == (XIMText*)NULL) return;
466
467	tmp_len = (int)*(CARD16*)buf;
468	buf += sz_CARD16;
469	if ((tmp_buf = 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 = Xmalloc(text->length *
481                      XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) {
482#else
483		if (text->string.multi_byte = Xmalloc(text->length+1)) {
484#endif
485			int tmp;
486#ifndef NO_DEC_I18N_FIX
487                        char *char_tmp;
488                        int char_len;
489#endif
490			tmp = im->methods->ctstombs((XIM)im,
491					   tmp_buf, tmp_len,
492#ifndef NO_DEC_I18N_FIX
493                                           text->string.multi_byte,
494                                           text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1,
495#else
496					   text->string.multi_byte, text->length,
497#endif
498					   &s);
499			text->string.multi_byte[tmp] = '\0';
500#ifndef NO_DEC_I18N_FIX
501                        text->length = 0;
502                        char_tmp =  text->string.multi_byte;
503                        while (*char_tmp != '\0') {
504                              char_len = mblen(char_tmp, strlen(char_tmp));
505                              char_tmp = char_tmp + char_len;
506                              (text->length)++;
507                        }
508#endif
509		}
510	    }
511	    else {
512		text->length = 0;
513		text->string.multi_byte = NULL;
514	    }
515
516	    Xfree(tmp_buf);
517	}
518	buf += tmp_len;
519
520	buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */
521
522    /* feedback part
523     */
524    if (status & 0x00000002) /* "no feedback" bit on */ {
525	text->feedback = (XIMFeedback*)NULL;
526    }
527    else {
528	int i, j;
529
530	i = (int)*(CARD16*)buf; buf += sz_CARD16;
531	buf += sz_CARD16; /* skip `unused' */
532	text->feedback = Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32)));
533	j = 0;
534	while (i > 0) {
535	    text->feedback[j] = (XIMFeedback)*(CARD32*)buf;
536	    buf += sz_CARD32;
537	    i -= sz_CARD32;
538	    j++;
539	}
540	/*
541	 * text->length tells how long both the status string and
542	 * the feedback array are. If there's "no string" the
543	 * text->length was set to zero previously. See above.
544	 * But if there is feedback (i.e. not "no feedback") then
545	 * we need to convey the length of the feedback array.
546	 * It might have been better if the protocol sent two
547	 * different values, one for the length of the status
548	 * string and one for the length of the feedback array.
549	 */
550	if (status & 0x00000001) /* "no string" bit on */ {
551	    text->length = j;
552	}
553    }
554}
555
556static void
557_free_memory_for_text(XIMText* text)
558{
559    if (text) {
560	if (text->string.multi_byte)
561	    Xfree(text->string.multi_byte);
562	if (text->feedback)
563	    Xfree(text->feedback);
564	Xfree(text);
565    }
566}
567
568static XimCbStatus
569_XimPreeditDrawCallback(Xim im,
570			Xic ic,
571			char* proto,
572			int len)
573{
574    XICCallback* cb = &ic->core.preedit_attr.draw_callback;
575    XIMPreeditDrawCallbackStruct cbs;
576
577    /* invoke the callback
578     */
579    if (cb && cb->callback) {
580	cbs.caret      = (int)*(INT32*)proto; proto += sz_INT32;
581	cbs.chg_first  = (int)*(INT32*)proto; proto += sz_INT32;
582	cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32;
583	_read_text_from_packet(im, proto, &cbs.text);
584
585	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
586
587	_free_memory_for_text((XIMText*)cbs.text);
588    }
589    else {
590
591	/* no callback registered
592	 */
593	return XimCbNoCallback;
594    }
595
596    return XimCbSuccess;
597}
598
599static XimCbStatus
600_XimPreeditCaretCallback(Xim im,
601			 Xic ic,
602			 char* proto,
603			 int len)
604{
605    XICCallback* cb = &ic->core.preedit_attr.caret_callback;
606    XIMPreeditCaretCallbackStruct cbs;
607
608    /* invoke the callback
609     */
610    if (cb && cb->callback) {
611	cbs.position  = (int)*(INT32*)proto; proto += sz_INT32;
612	cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32;
613	cbs.style     = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32;
614
615	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
616    }
617    else {
618
619	/* no callback registered
620	 */
621	_XimError(im, ic,
622		  (CARD16)XIM_BadSomething,
623		  (INT16)len,
624		  (CARD16)XIM_PREEDIT_CARET,
625		  (char*)proto); /* send XIM_ERROR */
626	return XimCbNoCallback;
627    }
628
629    /* Send a reply
630     */
631    {
632	CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply];
633	INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply;
634	int p;
635
636	_XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len);
637	p = XIM_HEADER_SIZE;
638	*(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16;
639	*(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16;
640	*(CARD32*)&buf[p] = (CARD32)cbs.position;
641
642	if (!(_XimWriteData(im, len, buf))) {
643	    return XimCbError;
644	}
645	_XimFlushData(im);
646    }
647
648    return XimCbSuccess;
649}
650
651static XimCbStatus
652_XimStatusStartCallback(Xim im,
653			Xic ic,
654			char* proto,
655			int len)
656{
657    XICCallback* cb = &ic->core.status_attr.start_callback;
658
659    /* invoke the callback
660     */
661    if (cb && cb->callback) {
662	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
663    }
664    else {
665
666	/* no callback registered
667	 */
668	return XimCbNoCallback;
669    }
670
671    return XimCbSuccess;
672}
673
674static XimCbStatus
675_XimStatusDoneCallback(Xim im,
676		       Xic ic,
677		       char* proto,
678		       int len)
679{
680    XICCallback* cb = &ic->core.status_attr.done_callback;
681
682    /* invoke the callback
683     */
684    if (cb && cb->callback) {
685	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
686    }
687    else {
688
689	/* no callback registered
690	 */
691	return XimCbNoCallback;
692    }
693
694    return XimCbSuccess;
695}
696
697static XimCbStatus
698_XimStatusDrawCallback(Xim im,
699		       Xic ic,
700		       char* proto,
701		       int len)
702{
703    XICCallback* cb = &ic->core.status_attr.draw_callback;
704    XIMStatusDrawCallbackStruct cbs;
705
706    /* invoke the callback
707     */
708    if (cb && cb->callback) {
709	cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32;
710	if (cbs.type == XIMTextType) {
711	    _read_text_from_packet(im, proto, &cbs.data.text);
712	}
713	else if (cbs.type == XIMBitmapType) {
714	    cbs.data.bitmap = (Pixmap)*(CARD32*)proto;
715	}
716
717	(*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs);
718
719	if (cbs.type == XIMTextType)
720	    _free_memory_for_text((XIMText *)cbs.data.text);
721    }
722    else {
723
724	/* no callback registered
725	 */
726	return XimCbNoCallback;
727    }
728
729    return XimCbSuccess;
730}
731
732static XimCbStatus
733_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len )
734{
735    XICCallback	*cb = &ic->core.preedit_attr.state_notify_callback;
736
737    /* invoke the callack
738     */
739    if( cb  &&  cb->callback ) {
740	XIMPreeditStateNotifyCallbackStruct cbrec;
741
742	cbrec.state = *(BITMASK32 *)proto;
743	(*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec );
744    }
745    else {
746	/* no callback registered
747	 */
748	return XimCbNoCallback;
749    }
750
751    return XimCbSuccess;
752}
753
754