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 callback 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 size_t blen; 331 length_in_bytes = (cbrec.text->encoding_is_wchar)? 332 sizeof(wchar_t) * cbrec.text->length: /* wchar */ 333 strlen(cbrec.text->string.mbs); /* mb */ 334 blen = XIM_HEADER_SIZE + 335 sz_CARD16 + 336 2 + length_in_bytes + 337 XIM_PAD(2 + length_in_bytes) + 338 2 + 2 + sz_CARD32 * cbrec.text->length; 339 buf = Xmalloc(blen); 340 buf_len = (INT16) blen; 341 } 342 _XimSetHeader((XPointer)buf, XIM_STR_CONVERSION_REPLY, 0, &buf_len); 343 buf_len -= XIM_HEADER_SIZE; /* added by _XimSetHeader (HACK) */ 344 p = XIM_HEADER_SIZE; 345 *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; 346 *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; 347 *(CARD16*)&buf[p] = (CARD16)cbrec.text->length; p += sz_CARD16; 348 memcpy(&buf[p],&cbrec.text->string.mbs,length_in_bytes); 349 p += length_in_bytes; 350 *(CARD16*)&buf[p] = (CARD16)(sz_CARD32*cbrec.text->length); 351 p += XIM_PAD(2); 352 for (i = 0; i < (int)cbrec.text->length; i++) { 353 *(CARD32*)&buf[p] = (CARD32)cbrec.text->feedback[i]; 354 p += sz_CARD32; 355 } 356 357 if (!(_XimWriteData(im, buf_len, buf))) { 358 return XimCbError; 359 } 360 _XimFlushData(im); 361 362 Xfree(buf); 363 } 364 365 return XimCbSuccess; 366} 367 368static XimCbStatus 369_XimPreeditStartCallback(Xim im, 370 Xic ic, 371 char* proto, 372 int len) 373{ 374 XICCallback* cb = &ic->core.preedit_attr.start_callback; 375 int ret; 376 377 /* invoke the callback 378 */ 379 if (cb && cb->callback){ 380 ret = (*(cb->callback))((XIC)ic, cb->client_data, (XPointer)NULL); 381 } 382 else { 383 384 /* no callback registered 385 */ 386 _XimError(im, ic, 387 (CARD16)XIM_BadSomething, 388 (INT16)len, 389 (CARD16)XIM_PREEDIT_START, 390 (char*)proto); /* send XIM_ERROR */ 391 return XimCbNoCallback; 392 } 393 394 /* send a reply 395 */ 396 { 397 CARD32 buf32[(sz_ximPacketHeader + sz_ximPreeditStartReply) / 4]; 398 CARD8 *buf = (CARD8 *)buf32; 399 INT16 buf_len = sz_XIMID + sz_XICID + sz_ximPreeditStartReply; 400 int p; 401 402 _XimSetHeader((XPointer)buf, XIM_PREEDIT_START_REPLY, 0, &buf_len); 403 p = XIM_HEADER_SIZE; 404 *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; 405 *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; 406 *(INT32*)&buf[p] = (INT32)ret; 407 408 if (!(_XimWriteData(im, buf_len, buf))) { 409 return XimCbError; 410 } 411 _XimFlushData(im); 412 } 413 414 return XimCbSuccess; 415} 416 417static XimCbStatus 418_XimPreeditDoneCallback(Xim im, 419 Xic ic, 420 char* proto, 421 int len) 422{ 423 XICCallback* cb = &ic->core.preedit_attr.done_callback; 424 425 /* invoke the callback 426 */ 427 if (cb && cb->callback) { 428 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 429 } 430 else { 431 432 /* no callback registered 433 */ 434 return XimCbNoCallback; 435 } 436 437 return XimCbSuccess; 438} 439 440static void 441_read_text_from_packet(Xim im, 442 char* buf, 443 XIMText** text_ptr) 444{ 445 int status; 446 XIMText* text; 447 int tmp_len; 448 char* tmp_buf; 449 Status s = 0; 450 451 status = (int)*(BITMASK32*)buf; buf += sz_BITMASK32; 452 453 /* string part 454 */ 455 if (status & 0x00000001) /* "no string" bit on */ { 456 buf += sz_CARD16; /* skip "length of preedit string" */ 457 buf += 2; /* pad */ 458 *text_ptr = (XIMText*)NULL; 459 return; 460 } 461 462 *text_ptr = text = Xmalloc(sizeof(XIMText)); 463 if (text == (XIMText*)NULL) return; 464 465 tmp_len = (int)*(CARD16*)buf; 466 buf += sz_CARD16; 467 if ((tmp_buf = Xmalloc(tmp_len + 1))) { 468 memcpy(tmp_buf, buf, tmp_len); 469 tmp_buf[tmp_len] = '\0'; 470 471 text->encoding_is_wchar = False; 472 text->length = im->methods->ctstombs((XIM)im, 473 tmp_buf, tmp_len, 474 NULL, 0, &s); /* CT? HM */ 475 if (s != XLookupNone) { 476#ifndef NO_DEC_I18N_FIX 477 /* Allow for NULL-terminated */ 478 if ((text->string.multi_byte = Xmalloc(text->length * 479 XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) { 480#else 481 if (text->string.multi_byte = Xmalloc(text->length+1)) { 482#endif 483 int tmp; 484#ifndef NO_DEC_I18N_FIX 485 char *char_tmp; 486 int char_len; 487#endif 488 tmp = im->methods->ctstombs((XIM)im, 489 tmp_buf, tmp_len, 490#ifndef NO_DEC_I18N_FIX 491 text->string.multi_byte, 492 text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1, 493#else 494 text->string.multi_byte, text->length, 495#endif 496 &s); 497 text->string.multi_byte[tmp] = '\0'; 498#ifndef NO_DEC_I18N_FIX 499 text->length = 0; 500 char_tmp = text->string.multi_byte; 501 while (*char_tmp != '\0') { 502 char_len = mblen(char_tmp, strlen(char_tmp)); 503 char_tmp = char_tmp + char_len; 504 (text->length)++; 505 } 506#endif 507 } 508 } 509 else { 510 text->length = 0; 511 text->string.multi_byte = NULL; 512 } 513 514 Xfree(tmp_buf); 515 } 516 buf += tmp_len; 517 518 buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */ 519 520 /* feedback part 521 */ 522 if (status & 0x00000002) /* "no feedback" bit on */ { 523 text->feedback = (XIMFeedback*)NULL; 524 } 525 else { 526 int i, j; 527 528 i = (int)*(CARD16*)buf; buf += sz_CARD16; 529 buf += sz_CARD16; /* skip `unused' */ 530 text->feedback = Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32))); 531 j = 0; 532 while (i > 0) { 533 text->feedback[j] = (XIMFeedback)*(CARD32*)buf; 534 buf += sz_CARD32; 535 i -= sz_CARD32; 536 j++; 537 } 538 /* 539 * text->length tells how long both the status string and 540 * the feedback array are. If there's "no string" the 541 * text->length was set to zero previously. See above. 542 * But if there is feedback (i.e. not "no feedback") then 543 * we need to convey the length of the feedback array. 544 * It might have been better if the protocol sent two 545 * different values, one for the length of the status 546 * string and one for the length of the feedback array. 547 */ 548 if (status & 0x00000001) /* "no string" bit on */ { 549 text->length = j; 550 } 551 } 552} 553 554static void 555_free_memory_for_text(XIMText* text) 556{ 557 if (text) { 558 Xfree(text->string.multi_byte); 559 Xfree(text->feedback); 560 Xfree(text); 561 } 562} 563 564static XimCbStatus 565_XimPreeditDrawCallback(Xim im, 566 Xic ic, 567 char* proto, 568 int len) 569{ 570 XICCallback* cb = &ic->core.preedit_attr.draw_callback; 571 XIMPreeditDrawCallbackStruct cbs; 572 573 /* invoke the callback 574 */ 575 if (cb && cb->callback) { 576 cbs.caret = (int)*(INT32*)proto; proto += sz_INT32; 577 cbs.chg_first = (int)*(INT32*)proto; proto += sz_INT32; 578 cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32; 579 _read_text_from_packet(im, proto, &cbs.text); 580 581 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 582 583 _free_memory_for_text((XIMText*)cbs.text); 584 } 585 else { 586 587 /* no callback registered 588 */ 589 return XimCbNoCallback; 590 } 591 592 return XimCbSuccess; 593} 594 595static XimCbStatus 596_XimPreeditCaretCallback(Xim im, 597 Xic ic, 598 char* proto, 599 int len) 600{ 601 XICCallback* cb = &ic->core.preedit_attr.caret_callback; 602 XIMPreeditCaretCallbackStruct cbs; 603 604 /* invoke the callback 605 */ 606 if (cb && cb->callback) { 607 cbs.position = (int)*(INT32*)proto; proto += sz_INT32; 608 cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32; 609 cbs.style = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32; 610 611 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 612 } 613 else { 614 615 /* no callback registered 616 */ 617 _XimError(im, ic, 618 (CARD16)XIM_BadSomething, 619 (INT16)len, 620 (CARD16)XIM_PREEDIT_CARET, 621 (char*)proto); /* send XIM_ERROR */ 622 return XimCbNoCallback; 623 } 624 625 /* Send a reply 626 */ 627 { 628 CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply]; 629 INT16 rlen = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply; 630 int p; 631 632 _XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &rlen); 633 p = XIM_HEADER_SIZE; 634 *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; 635 *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; 636 *(CARD32*)&buf[p] = (CARD32)cbs.position; 637 638 if (!(_XimWriteData(im, rlen, buf))) { 639 return XimCbError; 640 } 641 _XimFlushData(im); 642 } 643 644 return XimCbSuccess; 645} 646 647static XimCbStatus 648_XimStatusStartCallback(Xim im, 649 Xic ic, 650 char* proto, 651 int len) 652{ 653 XICCallback* cb = &ic->core.status_attr.start_callback; 654 655 /* invoke the callback 656 */ 657 if (cb && cb->callback) { 658 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 659 } 660 else { 661 662 /* no callback registered 663 */ 664 return XimCbNoCallback; 665 } 666 667 return XimCbSuccess; 668} 669 670static XimCbStatus 671_XimStatusDoneCallback(Xim im, 672 Xic ic, 673 char* proto, 674 int len) 675{ 676 XICCallback* cb = &ic->core.status_attr.done_callback; 677 678 /* invoke the callback 679 */ 680 if (cb && cb->callback) { 681 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 682 } 683 else { 684 685 /* no callback registered 686 */ 687 return XimCbNoCallback; 688 } 689 690 return XimCbSuccess; 691} 692 693static XimCbStatus 694_XimStatusDrawCallback(Xim im, 695 Xic ic, 696 char* proto, 697 int len) 698{ 699 XICCallback* cb = &ic->core.status_attr.draw_callback; 700 XIMStatusDrawCallbackStruct cbs; 701 702 /* invoke the callback 703 */ 704 if (cb && cb->callback) { 705 cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32; 706 if (cbs.type == XIMTextType) { 707 _read_text_from_packet(im, proto, &cbs.data.text); 708 } 709 else if (cbs.type == XIMBitmapType) { 710 cbs.data.bitmap = (Pixmap)*(CARD32*)proto; 711 } 712 713 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 714 715 if (cbs.type == XIMTextType) 716 _free_memory_for_text((XIMText *)cbs.data.text); 717 } 718 else { 719 720 /* no callback registered 721 */ 722 return XimCbNoCallback; 723 } 724 725 return XimCbSuccess; 726} 727 728static XimCbStatus 729_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len ) 730{ 731 XICCallback *cb = &ic->core.preedit_attr.state_notify_callback; 732 733 /* invoke the callback 734 */ 735 if( cb && cb->callback ) { 736 XIMPreeditStateNotifyCallbackStruct cbrec; 737 738 cbrec.state = *(BITMASK32 *)proto; 739 (*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec ); 740 } 741 else { 742 /* no callback registered 743 */ 744 return XimCbNoCallback; 745 } 746 747 return XimCbSuccess; 748} 749 750