TMkey.c revision fdf6a26f
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1994, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71#define XK_MISCELLANY 72#define XK_LATIN1 73#define XK_LATIN2 74#define XK_LATIN3 75#define XK_LATIN4 76 77#ifdef HAVE_CONFIG_H 78#include <config.h> 79#endif 80#include "IntrinsicI.h" 81#include <X11/keysymdef.h> 82#ifdef XKB 83#include <X11/XKBlib.h> 84#endif 85 86#define FLUSHKEYCACHE(ctx) \ 87 memset((void *)&ctx->keycache, 0, sizeof(TMKeyCache)) 88 89/* 90 * The following array reorders the modifier bits so that the most common ones 91 * (used by a translator) are in the top-most bits with respect to the size of 92 * the keycache. The array currently just reverses the bits as a good guess. 93 * This might be more trouble than it is worth, but it seems to help. 94 */ 95 96#define FM(i) i >> (8 - TMKEYCACHELOG2) 97 98/* *INDENT-OFF* */ 99static const unsigned char modmix[256] = { 100FM(0x0f), FM(0x8f), FM(0x4f), FM(0xcf), FM(0x2f), FM(0xaf), FM(0x6f), FM(0xef), 101FM(0x1f), FM(0x9f), FM(0x5f), FM(0xdf), FM(0x3f), FM(0xbf), FM(0x7f), FM(0xff), 102FM(0x07), FM(0x87), FM(0x47), FM(0xc7), FM(0x27), FM(0xa7), FM(0x67), FM(0xe7), 103FM(0x17), FM(0x97), FM(0x57), FM(0xd7), FM(0x37), FM(0xb7), FM(0x77), FM(0xf7), 104FM(0x0b), FM(0x8b), FM(0x4b), FM(0xcb), FM(0x2b), FM(0xab), FM(0x6b), FM(0xeb), 105FM(0x1b), FM(0x9b), FM(0x5b), FM(0xdb), FM(0x3b), FM(0xbb), FM(0x7b), FM(0xfb), 106FM(0x03), FM(0x83), FM(0x43), FM(0xc3), FM(0x23), FM(0xa3), FM(0x63), FM(0xe3), 107FM(0x13), FM(0x93), FM(0x53), FM(0xd3), FM(0x33), FM(0xb3), FM(0x73), FM(0xf3), 108FM(0x0d), FM(0x8d), FM(0x4d), FM(0xcd), FM(0x2d), FM(0xad), FM(0x6d), FM(0xed), 109FM(0x1d), FM(0x9d), FM(0x5d), FM(0xdd), FM(0x3d), FM(0xbd), FM(0x7d), FM(0xfd), 110FM(0x05), FM(0x85), FM(0x45), FM(0xc5), FM(0x25), FM(0xa5), FM(0x65), FM(0xe5), 111FM(0x15), FM(0x95), FM(0x55), FM(0xd5), FM(0x35), FM(0xb5), FM(0x75), FM(0xf5), 112FM(0x09), FM(0x89), FM(0x49), FM(0xc9), FM(0x29), FM(0xa9), FM(0x69), FM(0xe9), 113FM(0x19), FM(0x99), FM(0x59), FM(0xd9), FM(0x39), FM(0xb9), FM(0x79), FM(0xf9), 114FM(0x01), FM(0x81), FM(0x41), FM(0xc1), FM(0x21), FM(0xa1), FM(0x61), FM(0xe1), 115FM(0x11), FM(0x91), FM(0x51), FM(0xd1), FM(0x31), FM(0xb1), FM(0x71), FM(0xf1), 116FM(0x00), FM(0x8e), FM(0x4e), FM(0xce), FM(0x2e), FM(0xae), FM(0x6e), FM(0xee), 117FM(0x1e), FM(0x9e), FM(0x5e), FM(0xde), FM(0x3e), FM(0xbe), FM(0x7e), FM(0xfe), 118FM(0x08), FM(0x88), FM(0x48), FM(0xc8), FM(0x28), FM(0xa8), FM(0x68), FM(0xe8), 119FM(0x18), FM(0x98), FM(0x58), FM(0xd8), FM(0x38), FM(0xb8), FM(0x78), FM(0xf8), 120FM(0x04), FM(0x84), FM(0x44), FM(0xc4), FM(0x24), FM(0xa4), FM(0x64), FM(0xe4), 121FM(0x14), FM(0x94), FM(0x54), FM(0xd4), FM(0x34), FM(0xb4), FM(0x74), FM(0xf4), 122FM(0x0c), FM(0x8c), FM(0x4c), FM(0xcc), FM(0x2c), FM(0xac), FM(0x6c), FM(0xec), 123FM(0x1c), FM(0x9c), FM(0x5c), FM(0xdc), FM(0x3c), FM(0xbc), FM(0x7c), FM(0xfc), 124FM(0x02), FM(0x82), FM(0x42), FM(0xc2), FM(0x22), FM(0xa2), FM(0x62), FM(0xe2), 125FM(0x12), FM(0x92), FM(0x52), FM(0xd2), FM(0x32), FM(0xb2), FM(0x72), FM(0xf2), 126FM(0x0a), FM(0x8a), FM(0x4a), FM(0xca), FM(0x2a), FM(0xaa), FM(0x6a), FM(0xea), 127FM(0x1a), FM(0x9a), FM(0x5a), FM(0xda), FM(0x3a), FM(0xba), FM(0x7a), FM(0xfa), 128FM(0x06), FM(0x86), FM(0x46), FM(0xc6), FM(0x26), FM(0xa6), FM(0x66), FM(0xe6), 129FM(0x16), FM(0x96), FM(0x56), FM(0xd6), FM(0x36), FM(0xb6), FM(0x76), FM(0xf6), 130FM(0x0e), FM(0x8e), FM(0x4e), FM(0xce), FM(0x2e), FM(0xae), FM(0x6e), FM(0xee), 131FM(0x1e), FM(0x9e), FM(0x5e), FM(0xde), FM(0x3e), FM(0xbe), FM(0x7e), FM(0xfe) 132}; 133/* *INDENT-ON* */ 134#undef FM 135 136#define MOD_RETURN(ctx, key) (ctx)->keycache.modifiers_return[key] 137 138#define TRANSLATE(ctx,pd,dpy,key,mod,mod_ret,sym_ret) \ 139{ \ 140 int _i_ = (((key) - (TMLongCard) (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 141 (TMKEYCACHESIZE-1)); \ 142 if ((key) == 0) { /* Xlib XIM composed input */ \ 143 mod_ret = 0; \ 144 sym_ret = 0; \ 145 } else if ( /* not Xlib XIM composed input */ \ 146 (ctx)->keycache.keycode[_i_] == (key) && \ 147 (ctx)->keycache.modifiers[_i_] == (mod)) { \ 148 mod_ret = MOD_RETURN(ctx, key); \ 149 sym_ret = (ctx)->keycache.keysym[_i_]; \ 150 } else { \ 151 XtTranslateKeycode(dpy, (KeyCode) key, mod, &mod_ret, &sym_ret); \ 152 (ctx)->keycache.keycode[_i_] = (KeyCode) (key); \ 153 (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 154 (ctx)->keycache.keysym[_i_] = sym_ret; \ 155 MOD_RETURN(ctx, key) = (unsigned char)mod_ret; \ 156 } \ 157} 158 159#define UPDATE_CACHE(ctx, pd, key, mod, mod_ret, sym_ret) \ 160{ \ 161 int _i_ = (((key) - (TMLongCard) (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 162 (TMKEYCACHESIZE-1)); \ 163 (ctx)->keycache.keycode[_i_] = (KeyCode) (key); \ 164 (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 165 (ctx)->keycache.keysym[_i_] = sym_ret; \ 166 MOD_RETURN(ctx, key) = (unsigned char)(mod_ret); \ 167} 168 169/* usual number of expected keycodes in XtKeysymToKeycodeList */ 170#define KEYCODE_ARRAY_SIZE 10 171 172Boolean 173_XtComputeLateBindings(Display *dpy, 174 LateBindingsPtr lateModifiers, 175 Modifiers *computed, 176 Modifiers *computedMask) 177{ 178 int i, j, ref; 179 ModToKeysymTable *temp; 180 XtPerDisplay perDisplay; 181 KeySym tempKeysym = NoSymbol; 182 183 perDisplay = _XtGetPerDisplay(dpy); 184 if (perDisplay == NULL) { 185 XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 186 "displayError", "invalidDisplay", XtCXtToolkitError, 187 "Can't find display structure", NULL, NULL); 188 return FALSE; 189 } 190 _InitializeKeysymTables(dpy, perDisplay); 191 for (ref = 0; lateModifiers[ref].keysym; ref++) { 192 Boolean found = FALSE; 193 194 for (i = 0; i < 8; i++) { 195 temp = &(perDisplay->modsToKeysyms[i]); 196 for (j = 0; j < temp->count; j++) { 197 if (perDisplay->modKeysyms[temp->idx + j] == 198 lateModifiers[ref].keysym) { 199 *computedMask = *computedMask | temp->mask; 200 if (!lateModifiers[ref].knot) 201 *computed |= temp->mask; 202 tempKeysym = lateModifiers[ref].keysym; 203 found = TRUE; 204 break; 205 } 206 } 207 if (found) 208 break; 209 } 210 if (!found && !lateModifiers[ref].knot) 211 if (!lateModifiers[ref].pair && (tempKeysym == NoSymbol)) 212 return FALSE; 213 /* if you didn't find the modifier and the modifier must be 214 asserted then return FALSE. If you didn't find the modifier 215 and the modifier must be off, then it is OK . Don't 216 return FALSE if this is the first member of a pair or if 217 it is the second member of a pair when the first member 218 was bound to a modifier */ 219 if (!lateModifiers[ref].pair) 220 tempKeysym = NoSymbol; 221 } 222 return TRUE; 223} 224 225void 226_XtAllocTMContext(XtPerDisplay pd) 227{ 228 TMKeyContext ctx; 229 230 ctx = (TMKeyContext) _XtHeapAlloc(&pd->heap, sizeof(TMKeyContextRec)); 231 ctx->event = NULL; 232 ctx->serial = 0; 233 ctx->keysym = NoSymbol; 234 ctx->modifiers = 0; 235 FLUSHKEYCACHE(ctx); 236 pd->tm_context = ctx; 237} 238 239static unsigned int 240num_bits(unsigned long mask) 241{ 242 register unsigned long y; 243 244 y = (mask >> 1) & 033333333333; 245 y = mask - y - ((y >> 1) & 033333333333); 246 return ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077)); 247} 248 249Boolean 250_XtMatchUsingDontCareMods(TMTypeMatch typeMatch, 251 TMModifierMatch modMatch, 252 TMEventPtr eventSeq) 253{ 254 Modifiers modifiers_return; 255 KeySym keysym_return; 256 Modifiers useful_mods; 257 Modifiers computed = 0; 258 Modifiers computedMask = 0; 259 Boolean resolved = TRUE; 260 Display *dpy = eventSeq->xev->xany.display; 261 XtPerDisplay pd; 262 263 if (modMatch->lateModifiers != NULL) 264 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 265 &computed, &computedMask); 266 if (!resolved) 267 return FALSE; 268 computed = (Modifiers) (computed | modMatch->modifiers); 269 computedMask = (Modifiers) (computedMask | modMatch->modifierMask); /* gives do-care mask */ 270 271 if ((computed & computedMask) == (eventSeq->event.modifiers & computedMask)) { 272 TMKeyContext tm_context; 273 int num_modbits; 274 int i; 275 276 pd = _XtGetPerDisplay(dpy); 277 tm_context = pd->tm_context; 278 TRANSLATE(tm_context, pd, dpy, (KeyCode) eventSeq->event.eventCode, 279 (unsigned) 0, modifiers_return, keysym_return); 280 281 if ((keysym_return & typeMatch->eventCodeMask) == typeMatch->eventCode) { 282 tm_context->event = eventSeq->xev; 283 tm_context->serial = eventSeq->xev->xany.serial; 284 tm_context->keysym = keysym_return; 285 tm_context->modifiers = (Modifiers) 0; 286 return TRUE; 287 } 288 useful_mods = ~computedMask & modifiers_return; 289 if (useful_mods == 0) 290 return FALSE; 291 292 switch (num_modbits = (int) num_bits(useful_mods)) { 293 case 1: 294 case 8: 295 /* 296 * one modbit should never happen, in fact the implementation 297 * of XtTranslateKey and XmTranslateKey guarantee that it 298 * won't, so don't care if the loop is set up for the case 299 * when one modbit is set. 300 * The performance implications of all eight modbits being 301 * set is horrendous. This isn't a problem with Xt/Xaw based 302 * applications. We can only hope that Motif's virtual 303 * modifiers won't result in all eight modbits being set. 304 */ 305 for (i = (int) useful_mods; i > 0; i--) { 306 TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 307 (Modifiers) i, modifiers_return, keysym_return); 308 if (keysym_return == 309 (typeMatch->eventCode & typeMatch->eventCodeMask)) { 310 tm_context->event = eventSeq->xev; 311 tm_context->serial = eventSeq->xev->xany.serial; 312 tm_context->keysym = keysym_return; 313 tm_context->modifiers = (Modifiers) i; 314 return TRUE; 315 } 316 } 317 break; 318 default: /* (2..7) */ 319 { 320 /* 321 * Only translate using combinations of the useful modifiers. 322 * to minimize the chance of invalidating the cache. 323 */ 324 static char pows[] = { 0, 1, 3, 7, 15, 31, 63, 127 }; 325 Modifiers tmod, mod_masks[8]; 326 int j; 327 328 for (tmod = 1, i = 0; tmod <= (Mod5Mask << 1); tmod <<= 1) 329 if (tmod & useful_mods) 330 mod_masks[i++] = tmod; 331 for (j = (int) pows[num_modbits]; j > 0; j--) { 332 tmod = 0; 333 for (i = 0; i < num_modbits; i++) 334 if (j & (1 << i)) 335 tmod |= mod_masks[i]; 336 TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 337 tmod, modifiers_return, keysym_return); 338 if (keysym_return == 339 (typeMatch->eventCode & typeMatch->eventCodeMask)) { 340 tm_context->event = eventSeq->xev; 341 tm_context->serial = eventSeq->xev->xany.serial; 342 tm_context->keysym = keysym_return; 343 tm_context->modifiers = (Modifiers) i; 344 return TRUE; 345 } 346 } 347 } 348 break; 349 } /* switch (num_modbits) */ 350 } 351 return FALSE; 352} 353 354void 355XtConvertCase(Display *dpy, 356 KeySym keysym, 357 KeySym *lower_return, 358 KeySym *upper_return) 359{ 360 XtPerDisplay pd; 361 CaseConverterPtr ptr; 362 363 DPY_TO_APPCON(dpy); 364 365 LOCK_APP(app); 366 pd = _XtGetPerDisplay(dpy); 367 368 *lower_return = *upper_return = keysym; 369 for (ptr = pd->case_cvt; ptr; ptr = ptr->next) 370 if (ptr->start <= keysym && keysym <= ptr->stop) { 371 (*ptr->proc) (dpy, keysym, lower_return, upper_return); 372 return; 373 } 374 XConvertCase(keysym, lower_return, upper_return); 375 UNLOCK_APP(app); 376} 377 378Boolean 379_XtMatchUsingStandardMods(TMTypeMatch typeMatch, 380 TMModifierMatch modMatch, 381 TMEventPtr eventSeq) 382{ 383 Modifiers modifiers_return; 384 KeySym keysym_return; 385 Modifiers computed = 0; 386 Modifiers computedMask = 0; 387 Display *dpy = eventSeq->xev->xany.display; 388 XtPerDisplay pd = _XtGetPerDisplay(dpy); 389 TMKeyContext tm_context = pd->tm_context; 390 Modifiers translateModifiers; 391 392 /* To maximize cache utilization, we mask off nonstandard modifiers 393 before cache lookup. For a given key translator, standard modifiers 394 are constant per KeyCode. If a key translator uses no standard 395 modifiers this implementation will never reference the cache. 396 */ 397 398 modifiers_return = MOD_RETURN(tm_context, eventSeq->event.eventCode); 399 if (!modifiers_return) { 400 XtTranslateKeycode(dpy, (KeyCode) eventSeq->event.eventCode, 401 (Modifiers) eventSeq->event.modifiers, 402 &modifiers_return, &keysym_return); 403 translateModifiers = 404 (Modifiers) (eventSeq->event.modifiers & modifiers_return); 405 UPDATE_CACHE(tm_context, pd, eventSeq->event.eventCode, 406 translateModifiers, modifiers_return, keysym_return); 407 } 408 else { 409 translateModifiers = 410 (Modifiers) (eventSeq->event.modifiers & modifiers_return); 411 TRANSLATE(tm_context, pd, dpy, (KeyCode) eventSeq->event.eventCode, 412 translateModifiers, modifiers_return, keysym_return); 413 } 414 415 if ((typeMatch->eventCode & typeMatch->eventCodeMask) == 416 (keysym_return & typeMatch->eventCodeMask)) { 417 Boolean resolved = TRUE; 418 419 if (modMatch->lateModifiers != NULL) 420 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 421 &computed, &computedMask); 422 if (!resolved) 423 return FALSE; 424 computed = (Modifiers) (computed | modMatch->modifiers); 425 computedMask = (Modifiers) (computedMask | modMatch->modifierMask); 426 427 if ((computed & computedMask) == 428 (eventSeq->event.modifiers & ~modifiers_return & computedMask)) { 429 tm_context->event = eventSeq->xev; 430 tm_context->serial = eventSeq->xev->xany.serial; 431 tm_context->keysym = keysym_return; 432 tm_context->modifiers = translateModifiers; 433 return TRUE; 434 } 435 } 436 return FALSE; 437} 438 439void 440_XtBuildKeysymTables(Display *dpy, register XtPerDisplay pd) 441{ 442 ModToKeysymTable *table; 443 int maxCount, i, j, k, tempCount, idx; 444 KeySym keysym, tempKeysym; 445 XModifierKeymap *modKeymap; 446 KeyCode keycode; 447 448#define KeysymTableSize 16 449 450 FLUSHKEYCACHE(pd->tm_context); 451 452 XFree((char *) pd->keysyms); 453 pd->keysyms_serial = NextRequest(dpy); 454 pd->keysyms = XGetKeyboardMapping(dpy, (KeyCode) pd->min_keycode, 455 pd->max_keycode - pd->min_keycode + 1, 456 &pd->keysyms_per_keycode); 457 XtFree((char *) pd->modKeysyms); 458 459 pd->modKeysyms = XtMallocArray(KeysymTableSize, (Cardinal) sizeof(KeySym)); 460 maxCount = KeysymTableSize; 461 tempCount = 0; 462 463 XtFree((char *) pd->modsToKeysyms); 464 table = XtMallocArray(8, (Cardinal) sizeof(ModToKeysymTable)); 465 pd->modsToKeysyms = table; 466 467 table[0].mask = ShiftMask; 468 table[1].mask = LockMask; 469 table[2].mask = ControlMask; 470 table[3].mask = Mod1Mask; 471 table[4].mask = Mod2Mask; 472 table[5].mask = Mod3Mask; 473 table[6].mask = Mod4Mask; 474 table[7].mask = Mod5Mask; 475 tempKeysym = 0; 476 477 modKeymap = XGetModifierMapping(dpy); 478 for (i = 0; i < 32; i++) 479 pd->isModifier[i] = 0; 480 pd->mode_switch = 0; 481 pd->num_lock = 0; 482 for (i = 0; i < 8; i++) { 483 table[i].idx = tempCount; 484 table[i].count = 0; 485 for (j = 0; j < modKeymap->max_keypermod; j++) { 486 keycode = modKeymap->modifiermap[i * modKeymap->max_keypermod + j]; 487 if (keycode != 0) { 488 pd->isModifier[keycode >> 3] |= 489 (unsigned char) (1 << (keycode & 7)); 490 for (k = 0; k < pd->keysyms_per_keycode; k++) { 491 idx = ((keycode - pd->min_keycode) * 492 pd->keysyms_per_keycode) + k; 493 keysym = pd->keysyms[idx]; 494 if ((keysym == XK_Mode_switch) && (i > 2)) 495 pd->mode_switch = 496 (pd->mode_switch | (Modifiers) (1 << i)); 497 if ((keysym == XK_Num_Lock) && (i > 2)) 498 pd->num_lock = (pd->num_lock | (Modifiers) (1 << i)); 499 if (keysym != 0 && keysym != tempKeysym) { 500 if (tempCount == maxCount) { 501 maxCount += KeysymTableSize; 502 pd->modKeysyms = 503 XtReallocArray(pd->modKeysyms, 504 (Cardinal) maxCount, 505 (Cardinal) sizeof(KeySym)); 506 } 507 pd->modKeysyms[tempCount++] = keysym; 508 table[i].count++; 509 tempKeysym = keysym; 510 } 511 } 512 } 513 } 514 } 515 pd->lock_meaning = NoSymbol; 516 for (i = 0; i < table[1].count; i++) { 517 keysym = pd->modKeysyms[table[1].idx + i]; 518 if (keysym == XK_Caps_Lock) { 519 pd->lock_meaning = XK_Caps_Lock; 520 break; 521 } 522 else if (keysym == XK_Shift_Lock) { 523 pd->lock_meaning = XK_Shift_Lock; 524 } 525 } 526 XFreeModifiermap(modKeymap); 527} 528 529void 530XtTranslateKeycode(Display *dpy, 531 _XtKeyCode keycode, 532 Modifiers modifiers, 533 Modifiers *modifiers_return, 534 KeySym *keysym_return) 535{ 536 XtPerDisplay pd; 537 538 DPY_TO_APPCON(dpy); 539 540 LOCK_APP(app); 541 pd = _XtGetPerDisplay(dpy); 542 _InitializeKeysymTables(dpy, pd); 543 (*pd->defaultKeycodeTranslator) (dpy, keycode, modifiers, modifiers_return, 544 keysym_return); 545 UNLOCK_APP(app); 546} 547 548/* This code should match XTranslateKey (internal, sigh) in Xlib */ 549void 550XtTranslateKey(register Display *dpy, 551 _XtKeyCode keycode, 552 Modifiers modifiers, 553 Modifiers *modifiers_return, 554 KeySym *keysym_return) 555{ 556#ifndef XKB 557 XtPerDisplay pd; 558 int per; 559 register KeySym *syms; 560 KeySym sym, lsym, usym; 561 562 DPY_TO_APPCON(dpy); 563 564 LOCK_APP(app); 565 pd = _XtGetPerDisplay(dpy); 566 *modifiers_return = (ShiftMask | LockMask) | pd->mode_switch | pd->num_lock; 567 if (((int) keycode < pd->min_keycode) || ((int) keycode > pd->max_keycode)) { 568 *keysym_return = NoSymbol; 569 UNLOCK_APP(app); 570 return; 571 } 572 per = pd->keysyms_per_keycode; 573 syms = &pd->keysyms[(keycode - pd->min_keycode) * per]; 574 while ((per > 2) && (syms[per - 1] == NoSymbol)) 575 per--; 576 if ((per > 2) && (modifiers & pd->mode_switch)) { 577 syms += 2; 578 per -= 2; 579 } 580 if ((modifiers & pd->num_lock) && 581 (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { 582 if ((modifiers & ShiftMask) || 583 ((modifiers & LockMask) && (pd->lock_meaning == XK_Shift_Lock))) 584 *keysym_return = syms[0]; 585 else 586 *keysym_return = syms[1]; 587 } 588 else if (!(modifiers & ShiftMask) && 589 (!(modifiers & LockMask) || (pd->lock_meaning == NoSymbol))) { 590 if ((per == 1) || (syms[1] == NoSymbol)) 591 XtConvertCase(dpy, syms[0], keysym_return, &usym); 592 else 593 *keysym_return = syms[0]; 594 } 595 else if (!(modifiers & LockMask) || (pd->lock_meaning != XK_Caps_Lock)) { 596 if ((per == 1) || ((usym = syms[1]) == NoSymbol)) 597 XtConvertCase(dpy, syms[0], &lsym, &usym); 598 *keysym_return = usym; 599 } 600 else { 601 if ((per == 1) || ((sym = syms[1]) == NoSymbol)) 602 sym = syms[0]; 603 XtConvertCase(dpy, sym, &lsym, &usym); 604 if (!(modifiers & ShiftMask) && (sym != syms[0]) && 605 ((sym != usym) || (lsym == usym))) 606 XtConvertCase(dpy, syms[0], &lsym, &usym); 607 *keysym_return = usym; 608 } 609 610 if (*keysym_return == XK_VoidSymbol) 611 *keysym_return = NoSymbol; 612 UNLOCK_APP(app); 613#else 614 XkbLookupKeySym(dpy, (KeyCode) keycode, modifiers, modifiers_return, 615 keysym_return); 616#endif 617} 618 619void 620XtSetKeyTranslator(Display *dpy, XtKeyProc translator) 621{ 622 XtPerDisplay pd; 623 624 DPY_TO_APPCON(dpy); 625 626 LOCK_APP(app); 627 pd = _XtGetPerDisplay(dpy); 628 629 pd->defaultKeycodeTranslator = translator; 630 FLUSHKEYCACHE(pd->tm_context); 631 /* XXX should now redo grabs */ 632 UNLOCK_APP(app); 633} 634 635void 636XtRegisterCaseConverter(Display *dpy, 637 XtCaseProc proc, 638 KeySym start, 639 KeySym stop) 640{ 641 XtPerDisplay pd; 642 CaseConverterPtr ptr, prev; 643 644 DPY_TO_APPCON(dpy); 645 646 LOCK_APP(app); 647 pd = _XtGetPerDisplay(dpy); 648 649 ptr = (CaseConverterPtr) __XtMalloc(sizeof(CaseConverterRec)); 650 ptr->start = start; 651 ptr->stop = stop; 652 ptr->proc = proc; 653 ptr->next = pd->case_cvt; 654 pd->case_cvt = ptr; 655 656 /* Remove obsolete case converters from the list */ 657 prev = ptr; 658 for (ptr = ptr->next; ptr; ptr = prev->next) { 659 if (start <= ptr->start && stop >= ptr->stop) { 660 prev->next = ptr->next; 661 XtFree((char *) ptr); 662 } 663 else 664 prev = ptr; 665 } 666 FLUSHKEYCACHE(pd->tm_context); 667 /* XXX should now redo grabs */ 668 UNLOCK_APP(app); 669} 670 671KeySym * 672XtGetKeysymTable(Display *dpy, 673 KeyCode *min_keycode_return, 674 int *keysyms_per_keycode_return) 675{ 676 XtPerDisplay pd; 677 KeySym *retval; 678 679 DPY_TO_APPCON(dpy); 680 681 LOCK_APP(app); 682 pd = _XtGetPerDisplay(dpy); 683 _InitializeKeysymTables(dpy, pd); 684 *min_keycode_return = (KeyCode) pd->min_keycode; /* %%% */ 685 *keysyms_per_keycode_return = pd->keysyms_per_keycode; 686 retval = pd->keysyms; 687 UNLOCK_APP(app); 688 return retval; 689} 690 691void 692XtKeysymToKeycodeList(Display *dpy, 693 KeySym keysym, 694 KeyCode **keycodes_return, 695 Cardinal *keycount_return) 696{ 697 XtPerDisplay pd; 698 unsigned keycode; 699 int per; 700 register KeySym *syms; 701 register int i, j; 702 KeySym lsym, usym; 703 unsigned maxcodes = 0; 704 unsigned ncodes = 0; 705 KeyCode *keycodes, *codeP = NULL; 706 707 DPY_TO_APPCON(dpy); 708 709 LOCK_APP(app); 710 pd = _XtGetPerDisplay(dpy); 711 _InitializeKeysymTables(dpy, pd); 712 keycodes = NULL; 713 per = pd->keysyms_per_keycode; 714 for (syms = pd->keysyms, keycode = (unsigned) pd->min_keycode; 715 (int) keycode <= pd->max_keycode; syms += per, keycode++) { 716 int match = 0; 717 718 for (j = 0; j < per; j++) { 719 if (syms[j] == keysym) { 720 match = 1; 721 break; 722 } 723 } 724 if (!match) 725 for (i = 1; i < 5; i += 2) { 726 if ((per == i) || ((per > i) && (syms[i] == NoSymbol))) { 727 XtConvertCase(dpy, syms[i - 1], &lsym, &usym); 728 if ((lsym == keysym) || (usym == keysym)) { 729 match = 1; 730 break; 731 } 732 } 733 } 734 if (match) { 735 if (ncodes == maxcodes) { 736 KeyCode *old = keycodes; 737 738 maxcodes += KEYCODE_ARRAY_SIZE; 739 keycodes = XtMallocArray(maxcodes, (Cardinal) sizeof(KeyCode)); 740 if (ncodes) { 741 (void) memcpy(keycodes, old, ncodes * sizeof(KeyCode)); 742 XtFree((char *) old); 743 } 744 codeP = &keycodes[ncodes]; 745 } 746 *codeP++ = (KeyCode) keycode; 747 ncodes++; 748 } 749 } 750 *keycodes_return = keycodes; 751 *keycount_return = ncodes; 752 UNLOCK_APP(app); 753} 754