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