1 /****************************************************************** 2 3 Copyright 1992, 1993, 1994 by FUJITSU LIMITED 4 5 Permission to use, copy, modify, distribute, and sell this software 6 and its documentation for any purpose is hereby granted without fee, 7 provided that the above copyright notice appear in all copies and 8 that both that copyright notice and this permission notice appear 9 in supporting documentation, and that the name of FUJITSU LIMITED 10 not be used in advertising or publicity pertaining to distribution 11 of the software without specific, written prior permission. 12 FUJITSU LIMITED makes no representations about the suitability of 13 this software for any purpose. 14 It is provided "as is" without express or implied warranty. 15 16 FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 20 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 PERFORMANCE OF THIS SOFTWARE. 23 24 Author: Takashi Fujiwara FUJITSU LIMITED 25 fujiwara (at) a80.tech.yk.fujitsu.co.jp 26 27 ******************************************************************/ 28 29 #ifdef HAVE_CONFIG_H 30 #include <config.h> 31 #endif 32 #include <X11/Xatom.h> 33 #include "Xlibint.h" 34 #include "Xlcint.h" 35 #include "Ximint.h" 36 37 Xic 38 _XimICOfXICID( 39 Xim im, 40 XICID icid) 41 { 42 Xic pic; 43 44 for (pic = (Xic)im->core.ic_chain; pic; pic = (Xic)pic->core.next) { 45 if (pic->private.proto.icid == icid) 46 return pic; 47 } 48 return (Xic)0; 49 } 50 51 static void 52 _XimProcIMSetEventMask( 53 Xim im, 54 XPointer buf) 55 { 56 EVENTMASK *buf_l = (EVENTMASK *)buf; 57 58 im->private.proto.forward_event_mask = buf_l[0]; 59 im->private.proto.synchronous_event_mask = buf_l[1]; 60 return; 61 } 62 63 static void 64 _XimProcICSetEventMask( 65 Xic ic, 66 XPointer buf) 67 { 68 EVENTMASK *buf_l = (EVENTMASK *)buf; 69 70 ic->private.proto.forward_event_mask = buf_l[0]; 71 ic->private.proto.synchronous_event_mask = buf_l[1]; 72 _XimReregisterFilter(ic); 73 return; 74 } 75 76 Bool 77 _XimSetEventMaskCallback( 78 Xim xim, 79 INT16 len, 80 XPointer data, 81 XPointer call_data) 82 { 83 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 84 XIMID imid = buf_s[0]; 85 XICID icid = buf_s[1]; 86 Xim im = (Xim)call_data; 87 Xic ic; 88 89 if (imid == im->private.proto.imid) { 90 if (icid) { 91 if (!(ic = _XimICOfXICID(im, icid))) 92 return False; 93 _XimProcICSetEventMask(ic, (XPointer)&buf_s[2]); 94 } else { 95 _XimProcIMSetEventMask(im, (XPointer)&buf_s[2]); 96 } 97 return True; 98 } 99 return False; 100 } 101 102 static Bool 103 _XimSyncCheck( 104 Xim im, 105 INT16 len, 106 XPointer data, 107 XPointer arg) 108 { 109 Xic ic = (Xic)arg; 110 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 111 CARD8 major_opcode = *((CARD8 *)data); 112 CARD8 minor_opcode = *((CARD8 *)data + 1); 113 XIMID imid = buf_s[0]; 114 XICID icid = buf_s[1]; 115 116 if ((major_opcode == XIM_SYNC_REPLY) 117 && (minor_opcode == 0) 118 && (imid == im->private.proto.imid) 119 && (icid == ic->private.proto.icid)) 120 return True; 121 if ((major_opcode == XIM_ERROR) 122 && (minor_opcode == 0) 123 && (buf_s[2] & XIM_IMID_VALID) 124 && (imid == im->private.proto.imid) 125 && (buf_s[2] & XIM_ICID_VALID) 126 && (icid == ic->private.proto.icid)) 127 return True; 128 return False; 129 } 130 131 Bool 132 _XimSync( 133 Xim im, 134 Xic ic) 135 { 136 CARD32 buf32[BUFSIZE/4]; 137 CARD8 *buf = (CARD8 *)buf32; 138 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 139 INT16 len; 140 CARD32 reply32[BUFSIZE/4]; 141 char *reply = (char *)reply32; 142 XPointer preply; 143 int buf_size; 144 int ret_code; 145 146 buf_s[0] = im->private.proto.imid; /* imid */ 147 buf_s[1] = ic->private.proto.icid; /* icid */ 148 149 len = sizeof(CARD16) /* sizeof imid */ 150 + sizeof(CARD16); /* sizeof icid */ 151 152 _XimSetHeader((XPointer)buf, XIM_SYNC, 0, &len); 153 if (!(_XimWrite(im, len, (XPointer)buf))) 154 return False; 155 _XimFlush(im); 156 buf_size = BUFSIZE; 157 ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, 158 _XimSyncCheck, (XPointer)ic); 159 if(ret_code == XIM_TRUE) { 160 preply = reply; 161 } else if(ret_code == XIM_OVERFLOW) { 162 if(len <= 0) { 163 preply = reply; 164 } else { 165 buf_size = len; 166 preply = Xmalloc(len); 167 ret_code = _XimRead(im, &len, preply, buf_size, 168 _XimSyncCheck, (XPointer)ic); 169 if(ret_code != XIM_TRUE) { 170 Xfree(preply); 171 return False; 172 } 173 } 174 } else { 175 return False; 176 } 177 buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); 178 if (*((CARD8 *)preply) == XIM_ERROR) { 179 _XimProcError(im, 0, (XPointer)&buf_s[3]); 180 if(reply != preply) 181 Xfree(preply); 182 return False; 183 } 184 if(reply != preply) 185 Xfree(preply); 186 return True; 187 } 188 189 Bool 190 _XimProcSyncReply( 191 Xim im, 192 Xic ic) 193 { 194 CARD32 buf32[BUFSIZE/4]; 195 CARD8 *buf = (CARD8 *)buf32; 196 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 197 INT16 len; 198 199 buf_s[0] = im->private.proto.imid; /* imid */ 200 buf_s[1] = ic->private.proto.icid; /* icid */ 201 202 len = sizeof(CARD16) /* sizeof imid */ 203 + sizeof(CARD16); /* sizeof icid */ 204 205 _XimSetHeader((XPointer)buf, XIM_SYNC_REPLY, 0, &len); 206 if (!(_XimWrite(im, len, (XPointer)buf))) 207 return False; 208 _XimFlush(im); 209 return True; 210 } 211 212 Bool 213 _XimRespSyncReply( 214 Xic ic, 215 BITMASK16 mode) 216 { 217 if (mode & XimSYNCHRONUS) /* SYNC Request */ 218 MARK_NEED_SYNC_REPLY(ic->core.im); 219 220 return True; 221 } 222 223 Bool 224 _XimSyncCallback( 225 Xim xim, 226 INT16 len, 227 XPointer data, 228 XPointer call_data) 229 { 230 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 231 XIMID imid = buf_s[0]; 232 XICID icid = buf_s[1]; 233 Xim im = (Xim)call_data; 234 Xic ic; 235 236 if ((imid == im->private.proto.imid) 237 && (ic = _XimICOfXICID(im, icid))) { 238 (void)_XimProcSyncReply(im, ic); 239 return True; 240 } 241 return False; 242 } 243 244 static INT16 245 _XimSetEventToWire( 246 XEvent *ev, 247 xEvent *event) 248 { 249 if (!(_XimProtoEventToWire(ev, event, False))) 250 return 0; 251 event->u.u.sequenceNumber = 252 ((XAnyEvent *)ev)->serial & (unsigned long)0xffff; 253 return sz_xEvent; 254 } 255 256 static Bool 257 _XimForwardEventCore( 258 Xic ic, 259 XEvent *ev, 260 Bool sync) 261 { 262 Xim im = (Xim)ic->core.im; 263 CARD32 buf32[BUFSIZE/4]; 264 CARD8 *buf = (CARD8 *)buf32; 265 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 266 CARD32 reply32[BUFSIZE/4]; 267 char *reply = (char *)reply32; 268 XPointer preply; 269 int buf_size; 270 int ret_code; 271 INT16 len; 272 273 bzero(buf32, sizeof(buf32)); /* valgrind noticed uninitialized memory use! */ 274 275 if (!(len = _XimSetEventToWire(ev, (xEvent *)&buf_s[4]))) 276 return False; /* X event */ 277 278 buf_s[0] = im->private.proto.imid; /* imid */ 279 buf_s[1] = ic->private.proto.icid; /* icid */ 280 buf_s[2] = sync ? XimSYNCHRONUS : 0; /* flag */ 281 buf_s[3] = 282 (CARD16)((((XAnyEvent *)ev)->serial & ~((unsigned long)0xffff)) >> 16); 283 /* serial number */ 284 285 len += sizeof(CARD16) /* sizeof imid */ 286 + sizeof(CARD16) /* sizeof icid */ 287 + sizeof(BITMASK16) /* sizeof flag */ 288 + sizeof(CARD16); /* sizeof serila number */ 289 290 _XimSetHeader((XPointer)buf, XIM_FORWARD_EVENT, 0, &len); 291 if (!(_XimWrite(im, len, (XPointer)buf))) 292 return False; 293 _XimFlush(im); 294 295 if (sync) { 296 buf_size = BUFSIZE; 297 ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, 298 _XimSyncCheck, (XPointer)ic); 299 if(ret_code == XIM_TRUE) { 300 preply = reply; 301 } else if(ret_code == XIM_OVERFLOW) { 302 if(len <= 0) { 303 preply = reply; 304 } else { 305 buf_size = len; 306 preply = Xmalloc(len); 307 ret_code = _XimRead(im, &len, preply, buf_size, 308 _XimSyncCheck, (XPointer)ic); 309 if(ret_code != XIM_TRUE) { 310 Xfree(preply); 311 return False; 312 } 313 } 314 } else { 315 return False; 316 } 317 buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); 318 if (*((CARD8 *)preply) == XIM_ERROR) { 319 _XimProcError(im, 0, (XPointer)&buf_s[3]); 320 if(reply != preply) 321 Xfree(preply); 322 return False; 323 } 324 if(reply != preply) 325 Xfree(preply); 326 } 327 return True; 328 } 329 330 Bool 331 _XimForwardEvent( 332 Xic ic, 333 XEvent *ev, 334 Bool sync) 335 { 336 #ifdef EXT_FORWARD 337 if (((ev->type == KeyPress) || (ev->type == KeyRelease))) 338 if (_XimExtForwardKeyEvent(ic, (XKeyEvent *)ev, sync)) 339 return True; 340 #endif 341 return _XimForwardEventCore(ic, ev, sync); 342 } 343 344 Bool 345 _XimFabricateSerial( 346 Xim im, 347 XKeyEvent *event) 348 { 349 /* GTK2 XIM module sets serial=0. */ 350 if (!event->serial || !im->private.proto.enable_fabricated_order) { 351 MARK_FABRICATED(im); 352 return True; 353 } 354 if (event->serial == im->private.proto.fabricated_serial) { 355 fprintf(stderr, "%s,%d: The key event is already fabricated.\n", __FILE__, __LINE__); 356 return False; 357 } 358 if (im->private.proto.fabricated_serial) 359 fprintf(stderr, "%s,%d: Tried to fabricate a wrong key event.\n", __FILE__, __LINE__); 360 361 MARK_FABRICATED(im); 362 im->private.proto.fabricated_serial = event->serial; 363 im->private.proto.fabricated_time = event->time; 364 return True; 365 } 366 367 Bool 368 _XimUnfabricateSerial( 369 Xim im, 370 Xic ic, 371 XKeyEvent *event) 372 { 373 if (!im->private.proto.enable_fabricated_order) { 374 UNMARK_FABRICATED(im); 375 return True; 376 } 377 /* GTK2 XIM module sets serial=0. */ 378 if (!event->serial) { 379 /* _XimCommitRecv() sets event->serial and call _XimFabricateSerial() 380 * but GTK2 XIM always reset event->serial=0 with XFilterEvent(). 381 */ 382 if (ic && ic->private.proto.commit_info) 383 im->private.proto.fabricated_serial = 0; 384 UNMARK_FABRICATED(im); 385 return True; 386 } 387 if (!im->private.proto.fabricated_serial) { 388 fprintf(stderr, "%s,%d: The key event is already unfabricated.\n", __FILE__, __LINE__); 389 return False; 390 } 391 if (event->serial != im->private.proto.fabricated_serial) 392 fprintf(stderr, "%s,%d: Tried to unfabricate a wrong key event.\n", __FILE__, __LINE__); 393 394 im->private.proto.fabricated_serial = 0; 395 im->private.proto.fabricated_time = 0; 396 UNMARK_FABRICATED(im); 397 return True; 398 } 399 400 Bool 401 _XimIsFabricatedSerial( 402 Xim im, 403 XKeyEvent *event) 404 { 405 /* GTK2 XIM module sets serial=0. */ 406 if (!event->serial || !im->private.proto.enable_fabricated_order) 407 return IS_FABRICATED(im) ? True : False; 408 if (event->serial == im->private.proto.fabricated_serial) 409 return True; 410 if (!im->private.proto.fabricated_serial) 411 return False; 412 /* Rotate time */ 413 if (event->time < im->private.proto.fabricated_time) { 414 if (event->time >= 1000) 415 im->private.proto.fabricated_time = 0; 416 } else if (event->time - im->private.proto.fabricated_time > 1000) { 417 fprintf(stderr, 418 "%s,%d: The application disposed a key event with %ld serial.\n", 419 __FILE__, __LINE__, 420 im->private.proto.fabricated_serial); 421 im->private.proto.enable_fabricated_order = False; 422 if (IS_FABRICATED(im)) { 423 if (event->serial) 424 im->private.proto.fabricated_serial = event->serial; 425 return True; 426 } 427 } 428 return False; 429 } 430 431 static void 432 _XimProcEvent( 433 Display *d, 434 Xic ic, 435 XEvent *ev, 436 CARD16 *buf) 437 { 438 INT16 serial = buf[0]; 439 xEvent *xev = (xEvent *)&buf[1]; 440 441 _XimProtoWireToEvent(ev, xev, False); 442 ev->xany.serial |= serial << 16; 443 ev->xany.send_event = False; 444 ev->xany.display = d; 445 return; 446 } 447 448 static Bool 449 _XimForwardEventRecv( 450 Xim im, 451 Xic ic, 452 XPointer buf) 453 { 454 CARD16 *buf_s = (CARD16 *)buf; 455 Display *d = im->core.display; 456 XEvent ev; 457 458 _XimProcEvent(d, ic, &ev, &buf_s[1]); 459 460 (void)_XimRespSyncReply(ic, buf_s[0]); 461 462 /* If no event filter is registered, the event will not be sent back 463 * to filter for _XimUnfabricateSerial, so simply bypass it. 464 */ 465 if (ic->private.proto.registed_filter_event 466 & (KEYPRESS_MASK | KEYRELEASE_MASK)) { 467 _XimFabricateSerial((Xim)ic->core.im, &ev.xkey); 468 } else { 469 _XimPendingFilter(ic); 470 } 471 472 XPutBackEvent(d, &ev); 473 474 return True; 475 } 476 477 Bool 478 _XimForwardEventCallback( 479 Xim xim, 480 INT16 len, 481 XPointer data, 482 XPointer call_data) 483 { 484 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 485 XIMID imid = buf_s[0]; 486 XICID icid = buf_s[1]; 487 Xim im = (Xim)call_data; 488 Xic ic; 489 490 if ((imid == im->private.proto.imid) 491 && (ic = _XimICOfXICID(im, icid))) { 492 (void)_XimForwardEventRecv(im, ic, (XPointer)&buf_s[2]); 493 return True; 494 } 495 return False; 496 } 497 498 static Bool 499 _XimRegisterTriggerkey( 500 Xim im, 501 XPointer buf) 502 { 503 CARD32 *buf_l = (CARD32 *)buf; 504 CARD32 len; 505 CARD32 *key; 506 507 if (IS_DYNAMIC_EVENT_FLOW(im)) /* already Dynamic event flow mode */ 508 return True; 509 510 /* 511 * register onkeylist 512 */ 513 514 len = buf_l[0]; /* length of on-keys */ 515 len += sizeof(INT32); /* sizeof length of on-keys */ 516 517 if (!(key = Xmalloc(len))) { 518 _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); 519 return False; 520 } 521 memcpy((char *)key, (char *)buf_l, len); 522 im->private.proto.im_onkeylist = key; 523 524 MARK_DYNAMIC_EVENT_FLOW(im); 525 526 /* 527 * register offkeylist 528 */ 529 530 buf_l = (CARD32 *)((char *)buf + len); 531 len = buf_l[0]; /* length of off-keys */ 532 len += sizeof(INT32); /* sizeof length of off-keys */ 533 534 if (!(key = Xmalloc(len))) { 535 _XimError(im, 0, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); 536 return False; 537 } 538 539 memcpy((char *)key, (char *)buf_l, len); 540 im->private.proto.im_offkeylist = key; 541 542 return True; 543 } 544 545 Bool 546 _XimRegisterTriggerKeysCallback( 547 Xim xim, 548 INT16 len, 549 XPointer data, 550 XPointer call_data) 551 { 552 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 553 Xim im = (Xim)call_data; 554 555 (void )_XimRegisterTriggerkey(im, (XPointer)&buf_s[2]); 556 return True; 557 } 558 559 EVENTMASK 560 _XimGetWindowEventmask( 561 Xic ic) 562 { 563 Xim im = (Xim )ic->core.im; 564 XWindowAttributes atr; 565 566 if (!XGetWindowAttributes(im->core.display, ic->core.focus_window, &atr)) 567 return 0; 568 return (EVENTMASK)atr.your_event_mask; 569 } 570 571 572 static Bool 573 _XimTriggerNotifyCheck( 574 Xim im, 575 INT16 len, 576 XPointer data, 577 XPointer arg) 578 { 579 Xic ic = (Xic)arg; 580 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 581 CARD8 major_opcode = *((CARD8 *)data); 582 CARD8 minor_opcode = *((CARD8 *)data + 1); 583 XIMID imid = buf_s[0]; 584 XICID icid = buf_s[1]; 585 586 if ((major_opcode == XIM_TRIGGER_NOTIFY_REPLY) 587 && (minor_opcode == 0) 588 && (imid == im->private.proto.imid) 589 && (icid == ic->private.proto.icid)) 590 return True; 591 if ((major_opcode == XIM_ERROR) 592 && (minor_opcode == 0) 593 && (buf_s[2] & XIM_IMID_VALID) 594 && (imid == im->private.proto.imid) 595 && (buf_s[2] & XIM_ICID_VALID) 596 && (icid == ic->private.proto.icid)) 597 return True; 598 return False; 599 } 600 601 Bool 602 _XimTriggerNotify( 603 Xim im, 604 Xic ic, 605 int mode, 606 CARD32 idx) 607 { 608 CARD32 buf32[BUFSIZE/4]; 609 CARD8 *buf = (CARD8 *)buf32; 610 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 611 CARD32 *buf_l = (CARD32 *)&buf[XIM_HEADER_SIZE]; 612 CARD32 reply32[BUFSIZE/4]; 613 char *reply = (char *)reply32; 614 XPointer preply; 615 int buf_size; 616 int ret_code; 617 INT16 len; 618 EVENTMASK mask = _XimGetWindowEventmask(ic); 619 620 buf_s[0] = im->private.proto.imid; /* imid */ 621 buf_s[1] = ic->private.proto.icid; /* icid */ 622 buf_l[1] = mode; /* flag */ 623 buf_l[2] = idx; /* index of keys list */ 624 buf_l[3] = mask; /* select-event-mask */ 625 626 len = sizeof(CARD16) /* sizeof imid */ 627 + sizeof(CARD16) /* sizeof icid */ 628 + sizeof(CARD32) /* sizeof flag */ 629 + sizeof(CARD32) /* sizeof index of key list */ 630 + sizeof(EVENTMASK); /* sizeof select-event-mask */ 631 632 _XimSetHeader((XPointer)buf, XIM_TRIGGER_NOTIFY, 0, &len); 633 if (!(_XimWrite(im, len, (XPointer)buf))) 634 return False; 635 _XimFlush(im); 636 buf_size = BUFSIZE; 637 ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, 638 _XimTriggerNotifyCheck, (XPointer)ic); 639 if(ret_code == XIM_TRUE) { 640 preply = reply; 641 } else if(ret_code == XIM_OVERFLOW) { 642 if(len <= 0) { 643 preply = reply; 644 } else { 645 buf_size = len; 646 preply = Xmalloc(len); 647 ret_code = _XimRead(im, &len, preply, buf_size, 648 _XimTriggerNotifyCheck, (XPointer)ic); 649 if(ret_code != XIM_TRUE) { 650 Xfree(preply); 651 return False; 652 } 653 } 654 } else { 655 return False; 656 } 657 buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); 658 if (*((CARD8 *)preply) == XIM_ERROR) { 659 _XimProcError(im, 0, (XPointer)&buf_s[3]); 660 if(reply != preply) 661 Xfree(preply); 662 return False; 663 } 664 if(reply != preply) 665 Xfree(preply); 666 return True; 667 } 668 669 static Bool 670 _XimRegCommitInfo( 671 Xic ic, 672 char *string, 673 int string_len, 674 KeySym *keysym, 675 int keysym_len) 676 { 677 XimCommitInfo info; 678 679 if (!(info = Xmalloc(sizeof(XimCommitInfoRec)))) 680 return False; 681 info->string = string; 682 info->string_len = string_len; 683 info->keysym = keysym; 684 info->keysym_len = keysym_len; 685 info->next = ic->private.proto.commit_info; 686 ic->private.proto.commit_info = info; 687 return True; 688 } 689 690 static void 691 _XimUnregRealCommitInfo( 692 Xic ic, 693 Bool reverse) 694 { 695 XimCommitInfo info; 696 XimCommitInfo prev_info = NULL; 697 698 info = ic->private.proto.commit_info; 699 while (reverse && info) { 700 if (!info->next) 701 break; 702 prev_info = info; 703 info = info->next; 704 } 705 if (!info) 706 return; 707 708 Xfree(info->string); 709 Xfree(info->keysym); 710 if (prev_info) 711 prev_info->next = info->next; 712 else 713 ic->private.proto.commit_info = info->next; 714 Xfree(info); 715 return; 716 } 717 718 static void 719 _XimUnregCommitInfo( 720 Xic ic) 721 { 722 _XimUnregRealCommitInfo(ic, False); 723 } 724 725 static void 726 _XimUnregFirstCommitInfo( 727 Xic ic) 728 { 729 _XimUnregRealCommitInfo(ic, True); 730 } 731 732 void 733 _XimFreeCommitInfo( 734 Xic ic) 735 { 736 while (ic->private.proto.commit_info) 737 _XimUnregCommitInfo(ic); 738 return; 739 } 740 741 static XimCommitInfo 742 _XimFirstCommitInfo( 743 Xic ic) 744 { 745 XimCommitInfo info = ic->private.proto.commit_info; 746 while (info) { 747 if (!info->next) 748 break; 749 info = info->next; 750 } 751 return info; 752 } 753 754 static Bool 755 _XimProcKeySym( 756 Xic ic, 757 CARD32 sym, 758 KeySym **xim_keysym, 759 int *xim_keysym_len) 760 { 761 Xim im = (Xim)ic->core.im; 762 763 if (!(*xim_keysym = Xmalloc(sizeof(KeySym)))) { 764 _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); 765 return False; 766 } 767 768 **xim_keysym = (KeySym)sym; 769 *xim_keysym_len = 1; 770 771 return True; 772 } 773 774 static Bool 775 _XimProcCommit( 776 Xic ic, 777 BYTE *buf, 778 int len, 779 char **xim_string, 780 int *xim_string_len) 781 { 782 Xim im = (Xim)ic->core.im; 783 char *string; 784 785 if (!(string = Xmalloc(len + 1))) { 786 _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); 787 return False; 788 } 789 790 (void)memcpy(string, (char *)buf, len); 791 string[len] = '\0'; 792 793 *xim_string = string; 794 *xim_string_len = len; 795 return True; 796 } 797 798 static Bool 799 _XimCommitRecv( 800 Xim im, 801 Xic ic, 802 XPointer buf) 803 { 804 CARD16 *buf_s = (CARD16 *)buf; 805 BITMASK16 flag = buf_s[0]; 806 XKeyEvent ev; 807 char *string = NULL; 808 int string_len = 0; 809 KeySym *keysym = NULL; 810 int keysym_len = 0; 811 812 if ((flag & XimLookupBoth) == XimLookupChars) { 813 if (!(_XimProcCommit(ic, (BYTE *)&buf_s[2], 814 (int)buf_s[1], &string, &string_len))) 815 return False; 816 817 } else if ((flag & XimLookupBoth) == XimLookupKeySym) { 818 if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) 819 return False; 820 821 } else if ((flag & XimLookupBoth) == XimLookupBoth) { 822 if (!(_XimProcKeySym(ic, *(CARD32 *)&buf_s[2], &keysym, &keysym_len))) 823 return False; 824 825 if (!(_XimProcCommit(ic, (BYTE *)&buf_s[5], 826 (int)buf_s[4], &string, &string_len))) { 827 Xfree(keysym); 828 return False; 829 } 830 } 831 832 if (!(_XimRegCommitInfo(ic, string, string_len, keysym, keysym_len))) { 833 Xfree(string); 834 Xfree(keysym); 835 _XimError(im, ic, XIM_BadAlloc, (INT16)0, (CARD16)0, (char *)NULL); 836 return False; 837 } 838 839 (void)_XimRespSyncReply(ic, flag); 840 841 bzero(&ev, sizeof(ev)); /* uninitialized : found when running kterm under valgrind */ 842 843 ev.type = KeyPress; 844 ev.send_event = False; 845 ev.display = im->core.display; 846 ev.window = ic->core.focus_window; 847 ev.keycode = 0; 848 ev.state = 0; 849 850 ev.time = 0L; 851 ev.serial = LastKnownRequestProcessed(im->core.display); 852 853 if (ic->private.proto.registed_filter_event 854 & (KEYPRESS_MASK | KEYRELEASE_MASK)) 855 _XimFabricateSerial(im, &ev); 856 /* FIXME : 857 I wish there were COMMENTs (!) about the data passed around. 858 */ 859 #if 0 860 fprintf(stderr,"%s,%d: putback k press FIXED ev.time=0 ev.serial=%lu\n", __FILE__, __LINE__, ev.serial); 861 #endif 862 863 XPutBackEvent(im->core.display, (XEvent *)&ev); 864 865 return True; 866 } 867 868 Bool 869 _XimCommitCallback( 870 Xim xim, 871 INT16 len, 872 XPointer data, 873 XPointer call_data) 874 { 875 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 876 XIMID imid = buf_s[0]; 877 XICID icid = buf_s[1]; 878 Xim im = (Xim)call_data; 879 Xic ic; 880 881 if ((imid == im->private.proto.imid) 882 && (ic = _XimICOfXICID(im, icid))) { 883 (void)_XimCommitRecv(im, ic, (XPointer)&buf_s[2]); 884 return True; 885 } 886 return False; 887 } 888 889 void 890 _XimProcError( 891 Xim im, 892 Xic ic, 893 XPointer data) 894 { 895 return; 896 } 897 898 Bool 899 _XimErrorCallback( 900 Xim xim, 901 INT16 len, 902 XPointer data, 903 XPointer call_data) 904 { 905 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 906 BITMASK16 flag = buf_s[2]; 907 XIMID imid; 908 XICID icid; 909 Xim im = (Xim)call_data; 910 Xic ic = NULL; 911 912 if (flag & XIM_IMID_VALID) { 913 imid = buf_s[0]; 914 if (imid != im->private.proto.imid) 915 return False; 916 } 917 if (flag & XIM_ICID_VALID) { 918 icid = buf_s[1]; 919 if (!(ic = _XimICOfXICID(im, icid))) 920 return False; 921 } 922 _XimProcError(im, ic, (XPointer)&buf_s[3]); 923 924 return True; 925 } 926 927 Bool 928 _XimError( 929 Xim im, 930 Xic ic, 931 CARD16 error_code, 932 INT16 detail_length, 933 CARD16 type, 934 char *detail) 935 { 936 CARD32 buf32[BUFSIZE/4]; 937 CARD8 *buf = (CARD8 *)buf32; 938 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 939 INT16 len = 0; 940 941 buf_s[0] = im->private.proto.imid; /* imid */ 942 buf_s[2] = XIM_IMID_VALID; /* flag */ 943 if (ic) { 944 buf_s[1] = ic->private.proto.icid; /* icid */ 945 buf_s[2] |= XIM_ICID_VALID; /* flag */ 946 } 947 buf_s[3] = error_code; /* Error Code */ 948 buf_s[4] = detail_length; /* length of error detail */ 949 buf_s[5] = type; /* type of error detail */ 950 951 if (detail_length && detail) { 952 len = detail_length; 953 memcpy((char *)&buf_s[6], detail, len); 954 XIM_SET_PAD(&buf_s[6], len); 955 } 956 957 len += sizeof(CARD16) /* sizeof imid */ 958 + sizeof(CARD16) /* sizeof icid */ 959 + sizeof(BITMASK16) /* sizeof flag */ 960 + sizeof(CARD16) /* sizeof error_code */ 961 + sizeof(INT16) /* sizeof length of detail */ 962 + sizeof(CARD16); /* sizeof type */ 963 964 _XimSetHeader((XPointer)buf, XIM_ERROR, 0, &len); 965 if (!(_XimWrite(im, len, (XPointer)buf))) 966 return False; 967 _XimFlush(im); 968 return True; 969 } 970 971 static int 972 _Ximctsconvert( 973 XlcConv conv, 974 char *from, 975 int from_len, 976 char *to, 977 int to_len, 978 Status *state) 979 { 980 int from_left; 981 int to_left; 982 int from_savelen; 983 int to_savelen; 984 int from_cnvlen; 985 int to_cnvlen; 986 char *from_buf; 987 char *to_buf; 988 char scratchbuf[BUFSIZ]; 989 Status tmp_state; 990 991 if (!state) 992 state = &tmp_state; 993 994 if (!conv || !from || !from_len) { 995 *state = XLookupNone; 996 return 0; 997 } 998 999 /* Reset the converter. The CompoundText at 'from' starts in 1000 initial state. */ 1001 _XlcResetConverter(conv); 1002 1003 from_left = from_len; 1004 to_left = BUFSIZ; 1005 from_cnvlen = 0; 1006 to_cnvlen = 0; 1007 for (;;) { 1008 from_buf = &from[from_cnvlen]; 1009 from_savelen = from_left; 1010 to_buf = &scratchbuf[to_cnvlen]; 1011 to_savelen = to_left; 1012 if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, 1013 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { 1014 *state = XLookupNone; 1015 return 0; 1016 } 1017 from_cnvlen += (from_savelen - from_left); 1018 to_cnvlen += (to_savelen - to_left); 1019 if (from_left == 0) { 1020 if (!to_cnvlen) { 1021 *state = XLookupNone; 1022 return 0; 1023 } 1024 break; 1025 } 1026 } 1027 1028 if (!to || !to_len || (to_len < to_cnvlen)) { 1029 *state = XBufferOverflow; 1030 } else { 1031 memcpy(to, scratchbuf, to_cnvlen); 1032 *state = XLookupChars; 1033 } 1034 return to_cnvlen; 1035 } 1036 1037 int 1038 _Ximctstombs(XIM xim, char *from, int from_len, 1039 char *to, int to_len, Status *state) 1040 { 1041 return _Ximctsconvert(((Xim)xim)->private.proto.ctom_conv, 1042 from, from_len, to, to_len, state); 1043 } 1044 1045 int 1046 _Ximctstowcs( 1047 XIM xim, 1048 char *from, 1049 int from_len, 1050 wchar_t *to, 1051 int to_len, 1052 Status *state) 1053 { 1054 Xim im = (Xim)xim; 1055 XlcConv conv = im->private.proto.ctow_conv; 1056 int from_left; 1057 int to_left; 1058 int from_savelen; 1059 int to_savelen; 1060 int from_cnvlen; 1061 int to_cnvlen; 1062 char *from_buf; 1063 wchar_t *to_buf; 1064 wchar_t scratchbuf[BUFSIZ]; 1065 Status tmp_state; 1066 1067 if (!state) 1068 state = &tmp_state; 1069 1070 if (!conv || !from || !from_len) { 1071 *state = XLookupNone; 1072 return 0; 1073 } 1074 1075 /* Reset the converter. The CompoundText at 'from' starts in 1076 initial state. */ 1077 _XlcResetConverter(conv); 1078 1079 from_left = from_len; 1080 to_left = BUFSIZ; 1081 from_cnvlen = 0; 1082 to_cnvlen = 0; 1083 for (;;) { 1084 from_buf = &from[from_cnvlen]; 1085 from_savelen = from_left; 1086 to_buf = &scratchbuf[to_cnvlen]; 1087 to_savelen = to_left; 1088 if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left, 1089 (XPointer *)&to_buf, &to_left, NULL, 0) < 0) { 1090 *state = XLookupNone; 1091 return 0; 1092 } 1093 from_cnvlen += (from_savelen - from_left); 1094 to_cnvlen += (to_savelen - to_left); 1095 if (from_left == 0) { 1096 if (!to_cnvlen){ 1097 *state = XLookupNone; 1098 return 0; 1099 } 1100 break; 1101 } 1102 } 1103 1104 if (!to || !to_len || (to_len < to_cnvlen)) { 1105 *state = XBufferOverflow; 1106 } else { 1107 memcpy(to, scratchbuf, to_cnvlen * sizeof(wchar_t)); 1108 *state = XLookupChars; 1109 } 1110 return to_cnvlen; 1111 } 1112 1113 int 1114 _Ximctstoutf8( 1115 XIM xim, 1116 char *from, 1117 int from_len, 1118 char *to, 1119 int to_len, 1120 Status *state) 1121 { 1122 return _Ximctsconvert(((Xim)xim)->private.proto.ctoutf8_conv, 1123 from, from_len, to, to_len, state); 1124 } 1125 1126 int 1127 _XimProtoMbLookupString( 1128 XIC xic, 1129 XKeyEvent *ev, 1130 char *buffer, 1131 int bytes, 1132 KeySym *keysym, 1133 Status *state) 1134 { 1135 Xic ic = (Xic)xic; 1136 Xim im = (Xim)ic->core.im; 1137 int ret; 1138 Status tmp_state; 1139 XimCommitInfo info; 1140 1141 if (!IS_SERVER_CONNECTED(im)) 1142 return 0; 1143 1144 if (!state) 1145 state = &tmp_state; 1146 1147 if ((ev->type == KeyPress) && (ev->keycode == 0)) { /* Filter function */ 1148 if (!(info = _XimFirstCommitInfo(ic))) { 1149 *state = XLookupNone; 1150 return 0; 1151 } 1152 1153 ret = im->methods->ctstombs((XIM)im, info->string, 1154 info->string_len, buffer, bytes, state); 1155 if (*state == XBufferOverflow) 1156 return ret; 1157 if (keysym && (info->keysym && *(info->keysym))) { 1158 *keysym = *(info->keysym); 1159 if (*state == XLookupChars) 1160 *state = XLookupBoth; 1161 else 1162 *state = XLookupKeySym; 1163 } 1164 _XimUnregFirstCommitInfo(ic); 1165 1166 } else if (ev->type == KeyPress) { 1167 ret = _XimLookupMBText(ic, ev, buffer, bytes, keysym, NULL); 1168 if (ret > 0) { 1169 if (ret > bytes) 1170 *state = XBufferOverflow; 1171 else if (keysym && *keysym != NoSymbol) 1172 *state = XLookupBoth; 1173 else 1174 *state = XLookupChars; 1175 } else { 1176 if (keysym && *keysym != NoSymbol) 1177 *state = XLookupKeySym; 1178 else 1179 *state = XLookupNone; 1180 } 1181 } else { 1182 *state = XLookupNone; 1183 ret = 0; 1184 } 1185 1186 return ret; 1187 } 1188 1189 int 1190 _XimProtoWcLookupString( 1191 XIC xic, 1192 XKeyEvent *ev, 1193 wchar_t *buffer, 1194 int bytes, 1195 KeySym *keysym, 1196 Status *state) 1197 { 1198 Xic ic = (Xic)xic; 1199 Xim im = (Xim)ic->core.im; 1200 int ret; 1201 Status tmp_state; 1202 XimCommitInfo info; 1203 1204 if (!IS_SERVER_CONNECTED(im)) 1205 return 0; 1206 1207 if (!state) 1208 state = &tmp_state; 1209 1210 if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ 1211 if (!(info = _XimFirstCommitInfo(ic))) { 1212 *state = XLookupNone; 1213 return 0; 1214 } 1215 1216 ret = im->methods->ctstowcs((XIM)im, info->string, 1217 info->string_len, buffer, bytes, state); 1218 if (*state == XBufferOverflow) 1219 return ret; 1220 if (keysym && (info->keysym && *(info->keysym))) { 1221 *keysym = *(info->keysym); 1222 if (*state == XLookupChars) 1223 *state = XLookupBoth; 1224 else 1225 *state = XLookupKeySym; 1226 } 1227 _XimUnregFirstCommitInfo(ic); 1228 1229 } else if (ev->type == KeyPress) { 1230 ret = _XimLookupWCText(ic, ev, buffer, bytes, keysym, NULL); 1231 if (ret > 0) { 1232 if (ret > bytes) 1233 *state = XBufferOverflow; 1234 else if (keysym && *keysym != NoSymbol) 1235 *state = XLookupBoth; 1236 else 1237 *state = XLookupChars; 1238 } else { 1239 if (keysym && *keysym != NoSymbol) 1240 *state = XLookupKeySym; 1241 else 1242 *state = XLookupNone; 1243 } 1244 } else { 1245 *state = XLookupNone; 1246 ret = 0; 1247 } 1248 1249 return ret; 1250 } 1251 1252 int 1253 _XimProtoUtf8LookupString( 1254 XIC xic, 1255 XKeyEvent *ev, 1256 char *buffer, 1257 int bytes, 1258 KeySym *keysym, 1259 Status *state) 1260 { 1261 Xic ic = (Xic)xic; 1262 Xim im = (Xim)ic->core.im; 1263 int ret; 1264 Status tmp_state; 1265 XimCommitInfo info; 1266 1267 if (!IS_SERVER_CONNECTED(im)) 1268 return 0; 1269 1270 if (!state) 1271 state = &tmp_state; 1272 1273 if (ev->type == KeyPress && ev->keycode == 0) { /* Filter function */ 1274 if (!(info = _XimFirstCommitInfo(ic))) { 1275 *state = XLookupNone; 1276 return 0; 1277 } 1278 1279 ret = im->methods->ctstoutf8((XIM)im, info->string, 1280 info->string_len, buffer, bytes, state); 1281 if (*state == XBufferOverflow) 1282 return ret; 1283 if (keysym && (info->keysym && *(info->keysym))) { 1284 *keysym = *(info->keysym); 1285 if (*state == XLookupChars) 1286 *state = XLookupBoth; 1287 else 1288 *state = XLookupKeySym; 1289 } 1290 _XimUnregFirstCommitInfo(ic); 1291 1292 } else if (ev->type == KeyPress) { 1293 ret = _XimLookupUTF8Text(ic, ev, buffer, bytes, keysym, NULL); 1294 if (ret > 0) { 1295 if (ret > bytes) 1296 *state = XBufferOverflow; 1297 else if (keysym && *keysym != NoSymbol) 1298 *state = XLookupBoth; 1299 else 1300 *state = XLookupChars; 1301 } else { 1302 if (keysym && *keysym != NoSymbol) 1303 *state = XLookupKeySym; 1304 else 1305 *state = XLookupNone; 1306 } 1307 } else { 1308 *state = XLookupNone; 1309 ret = 0; 1310 } 1311 1312 return ret; 1313 } 1314