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