imCallbk.c revision b4ee4795
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 95Private XimCbStatus _XimGeometryCallback(Xim, Xic, char*, int); 96Private XimCbStatus _XimStrConversionCallback(Xim, Xic, char*, int); 97Private XimCbStatus _XimPreeditStartCallback(Xim, Xic, char*, int); 98Private XimCbStatus _XimPreeditDoneCallback(Xim, Xic, char*, int); 99Private void _free_memory_for_text(XIMText*); 100Private XimCbStatus _XimPreeditDrawCallback(Xim, Xic, char*, int); 101Private XimCbStatus _XimPreeditCaretCallback(Xim, Xic, char*, int); 102Private XimCbStatus _XimStatusStartCallback(Xim, Xic, char*, int); 103Private XimCbStatus _XimStatusDoneCallback(Xim, Xic, char*, int); 104Private XimCbStatus _XimStatusDrawCallback(Xim, Xic, char*, int); 105Private 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 141Private Bool 142_XimIsReadyForProcess(Xic ic) 143{ 144 return(!ic->private.proto.waitCallback); /* check HM */ 145} 146 147Private 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 164Private 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 185Public Bool 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) ? (char*)Xmalloc(proto_len) : NULL; 234 235 pcb = (XimPendingCallback)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 } 251 } 252 else { 253 /* invoke each callback according to the major opcode. 254 * `proto' points to the next address of IM-ID and IC-ID. 255 * `proto_len' specifies the packet length. 256 */ 257 (void) (*callback_table[major_opcode])(im, ic, proto, proto_len); 258 } 259 return True; 260} 261 262Private XimCbStatus 263_XimGeometryCallback(Xim im, 264 Xic ic, 265 char* proto, 266 int len) 267{ 268 XICCallback* cb = &ic->core.geometry_callback; 269 270 /* invoke the callack 271 */ 272 if (cb && cb->callback) { 273 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 274 } 275 else { 276 277 /* no callback registered 278 */ 279 return XimCbNoCallback; 280 } 281 282 return XimCbSuccess; 283} 284 285Private XimCbStatus 286_XimStrConversionCallback(Xim im, 287 Xic ic, 288 char* proto, 289 int len) 290{ 291 XICCallback* cb = &ic->core.string_conversion_callback; /* check HM */ 292 XIMStringConversionCallbackStruct cbrec; 293 294 /* invoke the callback 295 */ 296 if (cb && cb->callback) { 297 int p = XIM_HEADER_SIZE; 298 cbrec.position = (XIMStringConversionPosition) 299 *(CARD32*)&proto[p]; p += sz_CARD32; 300 cbrec.direction = (XIMCaretDirection) 301 *(CARD32*)&proto[p]; p += sz_CARD32; 302 cbrec.operation = (XIMStringConversionOperation) 303 *(CARD32*)&proto[p]; p += sz_CARD32; 304 cbrec.factor = (unsigned short) 305 *(CARD32*)&proto[p]; 306 307 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbrec); 308 } 309 else { 310 311 /* no callback registered 312 */ 313 _XimError(im, ic, 314 (CARD16)XIM_BadSomething, 315 (INT16)len, 316 (CARD16)XIM_STR_CONVERSION, 317 (char*)proto); /* send XIM_ERROR */ 318 return XimCbNoCallback; 319 } 320 321 /* send a reply 322 */ 323 { 324 CARD8 *buf; 325 INT16 buf_len; 326 int p, length_in_bytes, i; 327 328 /* Assumption: 329 * `cbrec.text->length' means the string length in characters 330 */ 331 { 332 length_in_bytes = (cbrec.text->encoding_is_wchar)? 333 sizeof(wchar_t) * cbrec.text->length: /* wchar */ 334 strlen(cbrec.text->string.mbs); /* mb */ 335 buf_len = XIM_HEADER_SIZE + 336 sz_CARD16 + 337 2 + length_in_bytes + 338 XIM_PAD(2 + length_in_bytes) + 339 2 + 2 + sz_CARD32 * cbrec.text->length; 340 buf = (CARD8*)Xmalloc(buf_len); 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 368Private 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 417Private 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 440Private 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 = (XIMText*)Xmalloc(sizeof(XIMText)); 463 if (text == (XIMText*)NULL) return; 464 465 tmp_len = (int)*(CARD16*)buf; 466 buf += sz_CARD16; 467 if ((tmp_buf = (char*)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 = 479 (char*)Xmalloc(text->length * 480 XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1))) { 481#else 482 if (text->string.multi_byte = (char*)Xmalloc(text->length+1)) { 483#endif 484 int tmp; 485#ifndef NO_DEC_I18N_FIX 486 char *char_tmp; 487 int char_len; 488#endif 489 tmp = im->methods->ctstombs((XIM)im, 490 tmp_buf, tmp_len, 491#ifndef NO_DEC_I18N_FIX 492 text->string.multi_byte, 493 text->length * XLC_PUBLIC(im->core.lcd,mb_cur_max) + 1, 494#else 495 text->string.multi_byte, text->length, 496#endif 497 &s); 498 text->string.multi_byte[tmp] = '\0'; 499#ifndef NO_DEC_I18N_FIX 500 text->length = 0; 501 char_tmp = text->string.multi_byte; 502 while (*char_tmp != '\0') { 503 char_len = mblen(char_tmp, strlen(char_tmp)); 504 char_tmp = char_tmp + char_len; 505 (text->length)++; 506 } 507#endif 508 } 509 } 510 else { 511 text->length = 0; 512 text->string.multi_byte = NULL; 513 } 514 515 Xfree(tmp_buf); 516 } 517 buf += tmp_len; 518 519 buf += XIM_PAD(sz_CARD16 + tmp_len); /* pad */ 520 521 /* feedback part 522 */ 523 if (status & 0x00000002) /* "no feedback" bit on */ { 524 text->feedback = (XIMFeedback*)NULL; 525 } 526 else { 527 int i, j; 528 529 i = (int)*(CARD16*)buf; buf += sz_CARD16; 530 buf += sz_CARD16; /* skip `unused' */ 531 text->feedback = (XIMFeedback*)Xmalloc(i*(sizeof(XIMFeedback)/sizeof(CARD32))); 532 j = 0; 533 while (i > 0) { 534 text->feedback[j] = (XIMFeedback)*(CARD32*)buf; 535 buf += sz_CARD32; 536 i -= sz_CARD32; 537 j++; 538 } 539 /* 540 * text->length tells how long both the status string and 541 * the feedback array are. If there's "no string" the 542 * text->length was set to zero previously. See above. 543 * But if there is feedback (i.e. not "no feedback") then 544 * we need to convey the length of the feedback array. 545 * It might have been better if the protocol sent two 546 * different values, one for the length of the status 547 * string and one for the length of the feedback array. 548 */ 549 if (status & 0x00000001) /* "no string" bit on */ { 550 text->length = j; 551 } 552 } 553} 554 555Private void 556_free_memory_for_text(XIMText* text) 557{ 558 if (text) { 559 if (text->string.multi_byte) 560 Xfree(text->string.multi_byte); 561 if (text->feedback) 562 Xfree(text->feedback); 563 Xfree(text); 564 } 565} 566 567Private XimCbStatus 568_XimPreeditDrawCallback(Xim im, 569 Xic ic, 570 char* proto, 571 int len) 572{ 573 XICCallback* cb = &ic->core.preedit_attr.draw_callback; 574 XIMPreeditDrawCallbackStruct cbs; 575 576 /* invoke the callback 577 */ 578 if (cb && cb->callback) { 579 cbs.caret = (int)*(INT32*)proto; proto += sz_INT32; 580 cbs.chg_first = (int)*(INT32*)proto; proto += sz_INT32; 581 cbs.chg_length = (int)*(INT32*)proto; proto += sz_INT32; 582 _read_text_from_packet(im, proto, &cbs.text); 583 584 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 585 586 _free_memory_for_text((XIMText*)cbs.text); 587 } 588 else { 589 590 /* no callback registered 591 */ 592 return XimCbNoCallback; 593 } 594 595 return XimCbSuccess; 596} 597 598Private XimCbStatus 599_XimPreeditCaretCallback(Xim im, 600 Xic ic, 601 char* proto, 602 int len) 603{ 604 XICCallback* cb = &ic->core.preedit_attr.caret_callback; 605 XIMPreeditCaretCallbackStruct cbs; 606 607 /* invoke the callback 608 */ 609 if (cb && cb->callback) { 610 cbs.position = (int)*(INT32*)proto; proto += sz_INT32; 611 cbs.direction = (XIMCaretDirection)*(CARD32*)proto; proto += sz_CARD32; 612 cbs.style = (XIMCaretStyle)*(CARD32*)proto; proto += sz_CARD32; 613 614 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 615 } 616 else { 617 618 /* no callback registered 619 */ 620 _XimError(im, ic, 621 (CARD16)XIM_BadSomething, 622 (INT16)len, 623 (CARD16)XIM_PREEDIT_CARET, 624 (char*)proto); /* send XIM_ERROR */ 625 return XimCbNoCallback; 626 } 627 628 /* Send a reply 629 */ 630 { 631 CARD8 buf[sz_ximPacketHeader + sz_ximPreeditCaretReply]; 632 INT16 len = sz_XIMID + sz_XICID + sz_ximPreeditCaretReply; 633 int p; 634 635 _XimSetHeader((XPointer)buf, XIM_PREEDIT_CARET_REPLY, 0, &len); 636 p = XIM_HEADER_SIZE; 637 *(CARD16*)&buf[p] = (CARD16)im->private.proto.imid; p += sz_CARD16; 638 *(CARD16*)&buf[p] = (CARD16)ic->private.proto.icid; p += sz_CARD16; 639 *(CARD32*)&buf[p] = (CARD32)cbs.position; 640 641 if (!(_XimWriteData(im, len, buf))) { 642 return XimCbError; 643 } 644 _XimFlushData(im); 645 } 646 647 return XimCbSuccess; 648} 649 650Private XimCbStatus 651_XimStatusStartCallback(Xim im, 652 Xic ic, 653 char* proto, 654 int len) 655{ 656 XICCallback* cb = &ic->core.status_attr.start_callback; 657 658 /* invoke the callback 659 */ 660 if (cb && cb->callback) { 661 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 662 } 663 else { 664 665 /* no callback registered 666 */ 667 return XimCbNoCallback; 668 } 669 670 return XimCbSuccess; 671} 672 673Private XimCbStatus 674_XimStatusDoneCallback(Xim im, 675 Xic ic, 676 char* proto, 677 int len) 678{ 679 XICCallback* cb = &ic->core.status_attr.done_callback; 680 681 /* invoke the callback 682 */ 683 if (cb && cb->callback) { 684 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL); 685 } 686 else { 687 688 /* no callback registered 689 */ 690 return XimCbNoCallback; 691 } 692 693 return XimCbSuccess; 694} 695 696Private XimCbStatus 697_XimStatusDrawCallback(Xim im, 698 Xic ic, 699 char* proto, 700 int len) 701{ 702 XICCallback* cb = &ic->core.status_attr.draw_callback; 703 XIMStatusDrawCallbackStruct cbs; 704 705 /* invoke the callback 706 */ 707 if (cb && cb->callback) { 708 cbs.type = (XIMStatusDataType)*(CARD32*)proto; proto += sz_CARD32; 709 if (cbs.type == XIMTextType) { 710 _read_text_from_packet(im, proto, &cbs.data.text); 711 } 712 else if (cbs.type == XIMBitmapType) { 713 cbs.data.bitmap = (Pixmap)*(CARD32*)proto; 714 } 715 716 (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&cbs); 717 718 if (cbs.type == XIMTextType) 719 _free_memory_for_text((XIMText *)cbs.data.text); 720 } 721 else { 722 723 /* no callback registered 724 */ 725 return XimCbNoCallback; 726 } 727 728 return XimCbSuccess; 729} 730 731Private XimCbStatus 732_XimPreeditStateNotifyCallback( Xim im, Xic ic, char* proto, int len ) 733{ 734 XICCallback *cb = &ic->core.preedit_attr.state_notify_callback; 735 736 /* invoke the callack 737 */ 738 if( cb && cb->callback ) { 739 XIMPreeditStateNotifyCallbackStruct cbrec; 740 741 cbrec.state = *(BITMASK32 *)proto; 742 (*cb->callback)( (XIC)ic, cb->client_data, (XPointer)&cbrec ); 743 } 744 else { 745 /* no callback registered 746 */ 747 return XimCbNoCallback; 748 } 749 750 return XimCbSuccess; 751} 752 753