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