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