1/****************************************************************** 2 3 Copyright 1992, 1993, 1994 by FUJITSU LIMITED 4 5Permission to use, copy, modify, distribute, and sell this software 6and its documentation for any purpose is hereby granted without fee, 7provided that the above copyright notice appear in all copies and 8that both that copyright notice and this permission notice appear 9in supporting documentation, and that the name of FUJITSU LIMITED 10not be used in advertising or publicity pertaining to distribution 11of the software without specific, written prior permission. 12FUJITSU LIMITED makes no representations about the suitability of 13this software for any purpose. 14It is provided "as is" without express or implied warranty. 15 16FUJITSU LIMITED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18EVENT SHALL FUJITSU LIMITED BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 20USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22PERFORMANCE OF THIS SOFTWARE. 23 24 Author: Takashi Fujiwara FUJITSU LIMITED 25 fujiwara@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/* 38 * index of extensions 39 */ 40 41#define XIM_EXT_SET_EVENT_MASK_IDX 0 42#ifdef EXT_FORWARD 43#define XIM_EXT_FORWARD_KEYEVENT_IDX 1 44#endif 45#ifdef EXT_MOVE 46#define XIM_EXT_MOVE_IDX 2 47#endif 48 49typedef struct _XIM_QueryExtRec { 50 Bool is_support; 51 const char *name; 52 int name_len; 53 CARD16 major_opcode; 54 CARD16 minor_opcode; 55 int idx; 56} XIM_QueryExtRec; 57 58static XIM_QueryExtRec extensions[] = { 59 {False, "XIM_EXT_SET_EVENT_MASK", 0, 0, 0, 60 XIM_EXT_SET_EVENT_MASK_IDX}, 61#ifdef EXT_FORWARD 62 {False, "XIM_EXT_FORWARD_KEYEVENT", 0, 0, 0, 63 XIM_EXT_FORWARD_KEYEVENT_IDX}, 64#endif 65#ifdef EXT_MOVE 66 {False, "XIM_EXT_MOVE", 0, 0, 0, XIM_EXT_MOVE_IDX}, 67#endif 68 {False, NULL, 0, 0, 0, 0} /* dummy */ 69}; 70 71static int 72_XimIsSupportExt( 73 int idx) 74{ 75 register int i; 76 int n = XIMNumber(extensions) - 1; 77 78 for (i = 0; i < n; i++) { 79 if (extensions[i].idx == idx) { 80 if (extensions[i].is_support) 81 return i; 82 else 83 break; 84 } 85 } 86 return -1; 87} 88 89static Bool 90_XimProcExtSetEventMask( 91 Xim im, 92 Xic ic, 93 XPointer buf) 94{ 95 EVENTMASK *buf_l = (EVENTMASK *)buf; 96 EVENTMASK select_mask = _XimGetWindowEventmask(ic); 97 98 ic->private.proto.filter_event_mask = buf_l[0]; 99 ic->private.proto.intercept_event_mask = buf_l[1]; 100 ic->private.proto.select_event_mask = buf_l[2]; 101 ic->private.proto.forward_event_mask = buf_l[3]; 102 ic->private.proto.synchronous_event_mask = buf_l[4]; 103 104 select_mask &= ~ic->private.proto.intercept_event_mask; 105 /* deselected event mask */ 106 select_mask |= ic->private.proto.select_event_mask; 107 /* selected event mask */ 108 XSelectInput(im->core.display, ic->core.focus_window, select_mask); 109 _XimReregisterFilter(ic); 110 111 if (!(_XimProcSyncReply(im, ic))) 112 return False; 113 return True; 114} 115 116static Bool 117_XimExtSetEventMaskCallback( 118 Xim xim, 119 INT16 len, 120 XPointer data, 121 XPointer call_data) 122{ 123 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 124 XIMID imid = buf_s[0]; 125 XICID icid = buf_s[1]; 126 Xim im = (Xim)call_data; 127 Xic ic; 128 129 if ((imid == im->private.proto.imid) 130 && (ic = _XimICOfXICID(im, icid))) { 131 (void)_XimProcExtSetEventMask(im, ic, (XPointer)&buf_s[2]); 132 return True; 133 } 134 return False; 135} 136 137#ifdef EXT_FORWARD 138static Bool 139_XimProcExtForwardKeyEvent( 140 Xim im, 141 Xic ic, 142 XPointer buf) 143{ 144 CARD8 *buf_b = (CARD8 *)buf; 145 CARD16 *buf_s = (CARD16 *)buf; 146 CARD32 *buf_l = (CARD32 *)buf; 147 XEvent ev; 148 XKeyEvent *kev = (XKeyEvent *)&ev; 149 150 bzero(&ev, sizeof(XEvent)); 151 kev->send_event = False; 152 kev->display = im->core.display; 153 kev->serial = buf_s[1]; /* sequence number */ 154 kev->type = buf_b[4] & 0x7f; /* xEvent.u.u.type */ 155 kev->keycode = buf_b[5]; /* Keycode */ 156 kev->state = buf_s[3]; /* state */ 157 kev->time = buf_l[2]; /* time */ 158 159 XPutBackEvent(im->core.display, &ev); 160 161 _XimRespSyncReply(ic, buf_s[0]); 162 MARK_FABRICATED(im); 163 164 return True; 165} 166 167static Bool 168_XimExtForwardKeyEventCallback( 169 Xim xim, 170 INT16 len, 171 XPointer data, 172 XPointer call_data) 173{ 174 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 175 XIMID imid = buf_s[0]; 176 XICID icid = buf_s[1]; 177 Xim im = (Xim)call_data; 178 Xic ic; 179 180 if ((imid == im->private.proto.imid) 181 && (ic = _XimICOfXICID(im, icid))) { 182 (void)_XimProcExtForwardKeyEvent(im, ic, (XPointer)&buf_s[2]); 183 return True; 184 } 185 return False; 186} 187 188static Bool 189_XimExtForwardKeyEventCheck( 190 Xim im, 191 INT16 len, 192 XPointer data, 193 XPointer arg) 194{ 195 Xic ic = (Xic)arg; 196 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 197 CARD8 major_opcode = *((CARD8 *)data); 198 CARD8 minor_opcode = *((CARD8 *)data + 1); 199 XIMID imid = buf_s[0]; 200 XICID icid = buf_s[1]; 201 202 if ((major_opcode == XIM_SYNC_REPLY) 203 && (minor_opcode == 0) 204 && (imid == im->private.proto.imid) 205 && (icid == ic->private.proto.icid)) 206 if ((major_opcode == XIM_ERROR) 207 && (minor_opcode == 0) 208 && (buf_s[2] & XIM_IMID_VALID) 209 && (imid == im->private.proto.imid) 210 && (buf_s[2] & XIM_ICID_VALID) 211 && (icid == ic->private.proto.icid)) 212 return True; 213 return False; 214} 215 216Bool 217_XimExtForwardKeyEvent( 218 Xic ic, 219 XKeyEvent *ev, 220 Bool sync) 221{ 222 Xim im = (Xim) ic->core.im; 223 CARD32 buf32[BUFSIZE/4]; 224 CARD8 *buf = (CARD8 *)buf32; 225 CARD8 *buf_b = &buf[XIM_HEADER_SIZE]; 226 CARD16 *buf_s = (CARD16 *)buf_b; 227 CARD32 *buf_l = (CARD32 *)buf_b; 228 CARD32 reply32[BUFSIZE/4]; 229 char *reply = (char *)reply32; 230 XPointer preply; 231 int buf_size; 232 int ret_code; 233 INT16 len; 234 int idx; 235 236 if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) < 0) 237 return False; 238 239 buf_s[0] = im->private.proto.imid; /* imid */ 240 buf_s[1] = ic->private.proto.icid; /* icid */ 241 buf_s[2] = sync ? XimSYNCHRONUS : 0; /* flag */ 242 buf_s[3] = (CARD16)(((XAnyEvent *)ev)->serial & ((unsigned long) 0xffff)); 243 /* sequence number */ 244 buf_b[8] = ev->type; /* xEvent.u.u.type */ 245 buf_b[9] = ev->keycode; /* keycode */ 246 buf_s[5] = ev->state; /* state */ 247 buf_l[3] = ev->time; /* time */ 248 len = sizeof(CARD16) /* sizeof imid */ 249 + sizeof(CARD16) /* sizeof icid */ 250 + sizeof(BITMASK16) /* sizeof flag */ 251 + sizeof(CARD16) /* sizeof sequence number */ 252 + sizeof(BYTE) /* sizeof xEvent.u.u.type */ 253 + sizeof(BYTE) /* sizeof keycode */ 254 + sizeof(CARD16) /* sizeof state */ 255 + sizeof(CARD32); /* sizeof time */ 256 257 _XimSetHeader((XPointer)buf, 258 extensions[idx].major_opcode, 259 extensions[idx].minor_opcode, &len); 260 if (!(_XimWrite(im, len, (XPointer)buf))) 261 return False; 262 _XimFlush(im); 263 if (sync) { 264 buf_size = BUFSIZE; 265 ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, 266 _XimExtForwardKeyEventCheck, (XPointer)ic); 267 if(ret_code == XIM_TRUE) { 268 preply = reply; 269 } else if(ret_code == XIM_OVERFLOW) { 270 if(len <= 0) { 271 preply = reply; 272 } else { 273 buf_sizex = len; 274 preply = Xmalloc(buf_size); 275 ret_code = _XimRead(im, &len, preply, buf_size, 276 _XimExtForwardKeyEventCheck, (XPointer)ic); 277 if(ret_code != XIM_TRUE) { 278 Xfree(preply); 279 return False; 280 } 281 } 282 } else 283 return False; 284 buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); 285 if (*((CARD8 *)preply) == XIM_ERROR) { 286 _XimProcError(im, 0, (XPointer)&buf_s[3]); 287 if(reply != preply) 288 Xfree(preply); 289 return False; 290 } 291 if(reply != preply) 292 Xfree(preply); 293 } 294 return True; 295} 296#endif /* EXT_FORWARD */ 297 298static int 299_XimCheckExtensionListSize(void) 300{ 301 register int i; 302 int len; 303 int total = 0; 304 int n = XIMNumber(extensions) - 1; 305 306 for (i = 0; i < n; i++) { 307 len = strlen(extensions[i].name); 308 extensions[i].name_len = len; 309 len += sizeof(BYTE); 310 total += len; 311 } 312 return total; 313} 314 315static void 316_XimSetExtensionList( 317 CARD8 *buf) 318{ 319 register int i; 320 int len; 321 int n = XIMNumber(extensions) - 1; 322 323 for (i = 0; i < n; i++) { 324 len = extensions[i].name_len; 325 buf[0] = (BYTE)len; 326 (void)strcpy((char *)&buf[1], extensions[i].name); 327 len += sizeof(BYTE); 328 buf += len; 329 } 330 return; 331} 332 333static unsigned int 334_XimCountNumberOfExtension( 335 INT16 total, 336 CARD8 *ext) 337{ 338 unsigned int n; 339 INT16 len; 340 INT16 min_len = sizeof(CARD8) 341 + sizeof(CARD8) 342 + sizeof(INT16); 343 344 n = 0; 345 while (total > min_len) { 346 len = *((INT16 *)(&ext[2])); 347 len += (min_len + XIM_PAD(len)); 348 total -= len; 349 ext += len; 350 n++; 351 } 352 return n; 353} 354 355static Bool 356_XimParseExtensionList( 357 Xim im, 358 CARD16 *data) 359{ 360 int num = XIMNumber(extensions) - 1; 361 unsigned int n; 362 CARD8 *buf; 363 register int i; 364 register int j; 365 INT16 len; 366 367 if (!(n = _XimCountNumberOfExtension(data[0], (CARD8 *)&data[1]))) 368 return True; 369 370 buf = (CARD8 *)&data[1]; 371 for (i = 0; i < n; i++) { 372 len = *((INT16 *)(&buf[2])); 373 for (j = 0; j < num; j++) { 374 if (!(strncmp(extensions[j].name, (char *)&buf[4], len))) { 375 extensions[j].major_opcode = buf[0]; 376 extensions[j].minor_opcode = buf[1]; 377 extensions[j].is_support = True; 378 break; 379 } 380 } 381 len += sizeof(CARD8) /* sizeof major_opcode */ 382 + sizeof(CARD8) /* sizeof minor_opcode */ 383 + sizeof(INT16) /* sizeof length */ 384 + XIM_PAD(len); /* sizeof pad */ 385 buf += len; 386 } 387 388 return True; 389} 390 391static Bool 392_XimQueryExtensionCheck( 393 Xim im, 394 INT16 len, 395 XPointer data, 396 XPointer arg) 397{ 398 CARD16 *buf_s = (CARD16 *)((CARD8 *)data + XIM_HEADER_SIZE); 399 CARD8 major_opcode = *((CARD8 *)data); 400 CARD8 minor_opcode = *((CARD8 *)data + 1); 401 XIMID imid = buf_s[0]; 402 403 if ((major_opcode == XIM_QUERY_EXTENSION_REPLY) 404 && (minor_opcode == 0) 405 && (imid == im->private.proto.imid)) 406 return True; 407 if ((major_opcode == XIM_ERROR) 408 && (minor_opcode == 0) 409 && (buf_s[2] & XIM_IMID_VALID) 410 && (imid == im->private.proto.imid)) 411 return True; 412 return False; 413} 414 415Bool 416_XimExtension( 417 Xim im) 418{ 419 CARD8 *buf; 420 CARD16 *buf_s; 421 int buf_len; 422 INT16 len; 423 CARD32 reply32[BUFSIZE/4]; 424 char *reply = (char *)reply32; 425 XPointer preply; 426 int buf_size; 427 int ret_code; 428 int idx; 429 430 if (!(len = _XimCheckExtensionListSize())) 431 return True; 432 433 buf_len = XIM_HEADER_SIZE 434 + sizeof(CARD16) 435 + sizeof(INT16) 436 + len 437 + XIM_PAD(len); 438 439 if (!(buf = Xmalloc(buf_len))) 440 return False; 441 buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 442 443 buf_s[0] = im->private.proto.imid; /* imid */ 444 buf_s[1] = len; /* length of Extensions */ 445 _XimSetExtensionList((CARD8 *)&buf_s[2]); 446 /* extensions supported */ 447 XIM_SET_PAD(&buf_s[2], len); /* pad */ 448 len += sizeof(CARD16) /* sizeof imid */ 449 + sizeof(INT16); /* sizeof length of extensions */ 450 451 _XimSetHeader((XPointer)buf, XIM_QUERY_EXTENSION, 0, &len); 452 if (!(_XimWrite(im, len, (XPointer)buf))) { 453 XFree(buf); 454 return False; 455 } 456 XFree(buf); 457 _XimFlush(im); 458 buf_size = BUFSIZE; 459 ret_code = _XimRead(im, &len, (XPointer)reply, buf_size, 460 _XimQueryExtensionCheck, 0); 461 if(ret_code == XIM_TRUE) { 462 preply = reply; 463 } else if(ret_code == XIM_OVERFLOW) { 464 if(len <= 0) { 465 preply = reply; 466 } else { 467 buf_size = len; 468 preply = Xmalloc(buf_size); 469 ret_code = _XimRead(im, &len, preply, buf_size, 470 _XimQueryExtensionCheck, 0); 471 if(ret_code != XIM_TRUE) { 472 Xfree(preply); 473 return False; 474 } 475 } 476 } else 477 return False; 478 buf_s = (CARD16 *)((char *)preply + XIM_HEADER_SIZE); 479 if (*((CARD8 *)preply) == XIM_ERROR) { 480 _XimProcError(im, 0, (XPointer)&buf_s[3]); 481 if(reply != preply) 482 Xfree(preply); 483 return False; 484 } 485 486 if (!(_XimParseExtensionList(im, &buf_s[1]))) { 487 if(reply != preply) 488 Xfree(preply); 489 return False; 490 } 491 if(reply != preply) 492 Xfree(preply); 493 494 if ((idx = _XimIsSupportExt(XIM_EXT_SET_EVENT_MASK_IDX)) >= 0) 495 _XimRegProtoIntrCallback(im, 496 extensions[idx].major_opcode, 497 extensions[idx].minor_opcode, 498 _XimExtSetEventMaskCallback, (XPointer)im); 499#ifdef EXT_FORWARD 500 if ((idx = _XimIsSupportExt(XIM_EXT_FORWARD_KEYEVENT_IDX)) >= 0) 501 _XimRegProtoIntrCallback(im, 502 extensions[idx].major_opcode, 503 extensions[idx].minor_opcode, 504 _XimExtForwardKeyEventCallback, (XPointer)im); 505#endif 506 507 return True; 508} 509 510#ifdef EXT_MOVE 511/* flag of ExtenArgCheck */ 512#define EXT_XNSPOTLOCATION (1L<<0) 513 514/* macro for ExtenArgCheck */ 515#define SET_EXT_XNSPOTLOCATION(flag) (flag |= EXT_XNSPOTLOCATION) 516#define IS_EXT_XNSPOTLOCATION(flag) (flag & EXT_XNSPOTLOCATION) 517 518/* length of XPoint attribute */ 519#define XIM_Xpoint_length 12 520 521static Bool 522_XimExtMove( 523 Xim im, 524 Xic ic, 525 CARD16 x, 526 CARD16 y) 527{ 528 CARD32 buf32[BUFSIZE/4]; 529 CARD8 *buf = (CARD8 *)buf32; 530 CARD16 *buf_s = (CARD16 *)&buf[XIM_HEADER_SIZE]; 531 INT16 len; 532 int idx; 533 534 if ((idx = _XimIsSupportExt(XIM_EXT_MOVE_IDX)) < 0) 535 return False; 536 537 buf_s[0] = im->private.proto.imid; /* imid */ 538 buf_s[1] = ic->private.proto.icid; /* icid */ 539 buf_s[2] = x; /* X */ 540 buf_s[3] = y; /* Y */ 541 len = sizeof(CARD16) /* sizeof imid */ 542 + sizeof(CARD16) /* sizeof icid */ 543 + sizeof(INT16) /* sizeof X */ 544 + sizeof(INT16); /* sizeof Y */ 545 546 _XimSetHeader((XPointer)buf, extensions[idx].major_opcode, 547 extensions[idx].minor_opcode, &len); 548 if (!(_XimWrite(im, len, (XPointer)buf))) 549 return False; 550 _XimFlush(im); 551 return True; 552} 553 554BITMASK32 555_XimExtenArgCheck( 556 XIMArg *arg) 557{ 558 CARD32 flag = 0L; 559 if (!strcmp(arg->name, XNSpotLocation)) 560 SET_EXT_XNSPOTLOCATION(flag); 561 return flag; 562} 563 564Bool 565_XimExtenMove( 566 Xim im, 567 Xic ic, 568 CARD32 flag, 569 CARD16 *buf, 570 INT16 length) 571{ 572 if ((IS_EXT_XNSPOTLOCATION(flag)) && (length == XIM_Xpoint_length)) 573 return _XimExtMove(im, ic, buf[4], buf[5]); 574 return False; 575} 576#endif /* EXT_MOVE */ 577