TMkey.c revision 249c3046
1/*LINTLIBRARY*/ 2 3/*********************************************************** 4Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 5 6Permission is hereby granted, free of charge, to any person obtaining a 7copy of this software and associated documentation files (the "Software"), 8to deal in the Software without restriction, including without limitation 9the rights to use, copy, modify, merge, publish, distribute, sublicense, 10and/or sell copies of the Software, and to permit persons to whom the 11Software is furnished to do so, subject to the following conditions: 12 13The above copyright notice and this permission notice (including the next 14paragraph) shall be included in all copies or substantial portions of the 15Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23DEALINGS IN THE SOFTWARE. 24 25Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Digital not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45******************************************************************/ 46 47/* 48 49Copyright 1987, 1988, 1994, 1998 The Open Group 50 51Permission to use, copy, modify, distribute, and sell this software and its 52documentation for any purpose is hereby granted without fee, provided that 53the above copyright notice appear in all copies and that both that 54copyright notice and this permission notice appear in supporting 55documentation. 56 57The above copyright notice and this permission notice shall be included in 58all copies or substantial portions of the Software. 59 60THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 64AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 65CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 67Except as contained in this notice, the name of The Open Group shall not be 68used in advertising or otherwise to promote the sale, use or other dealings 69in this Software without prior written authorization from The Open Group. 70 71*/ 72 73#define XK_MISCELLANY 74#define XK_LATIN1 75#define XK_LATIN2 76#define XK_LATIN3 77#define XK_LATIN4 78 79#ifdef HAVE_CONFIG_H 80#include <config.h> 81#endif 82#include "IntrinsicI.h" 83#include <X11/keysymdef.h> 84#ifdef XKB 85#include <X11/XKBlib.h> 86#endif 87 88#define FLUSHKEYCACHE(ctx) \ 89 bzero((char *)&ctx->keycache, sizeof(TMKeyCache)) 90 91/* 92 * The following array reorders the modifier bits so that the most common ones 93 * (used by a translator) are in the top-most bits with respect to the size of 94 * the keycache. The array currently just reverses the bits as a good guess. 95 * This might be more trouble than it is worth, but it seems to help. 96 */ 97 98#define FM(i) i >> (8 - TMKEYCACHELOG2) 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#undef FM 134 135#define MOD_RETURN(ctx, key) (ctx)->keycache.modifiers_return[key] 136 137#define TRANSLATE(ctx,pd,dpy,key,mod,mod_ret,sym_ret) \ 138{ \ 139 int _i_ = (((key) - (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 140 (TMKEYCACHESIZE-1)); \ 141 if ((key) == 0) { /* Xlib XIM composed input */ \ 142 mod_ret = 0; \ 143 sym_ret = 0; \ 144 } else if ( /* not Xlib XIM composed input */ \ 145 (ctx)->keycache.keycode[_i_] == (key) && \ 146 (ctx)->keycache.modifiers[_i_] == (mod)) { \ 147 mod_ret = MOD_RETURN(ctx, key); \ 148 sym_ret = (ctx)->keycache.keysym[_i_]; \ 149 } else { \ 150 XtTranslateKeycode(dpy, key, mod, &mod_ret, &sym_ret); \ 151 (ctx)->keycache.keycode[_i_] = key; \ 152 (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 153 (ctx)->keycache.keysym[_i_] = sym_ret; \ 154 MOD_RETURN(ctx, key) = (unsigned char)mod_ret; \ 155 } \ 156} 157 158#define UPDATE_CACHE(ctx, pd, key, mod, mod_ret, sym_ret) \ 159{ \ 160 int _i_ = (((key) - (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 161 (TMKEYCACHESIZE-1)); \ 162 (ctx)->keycache.keycode[_i_] = key; \ 163 (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 164 (ctx)->keycache.keysym[_i_] = sym_ret; \ 165 MOD_RETURN(ctx, key) = (unsigned char)mod_ret; \ 166} 167 168/* usual number of expected keycodes in XtKeysymToKeycodeList */ 169#define KEYCODE_ARRAY_SIZE 10 170 171Boolean _XtComputeLateBindings( 172 Display *dpy, 173 LateBindingsPtr lateModifiers, 174 Modifiers *computed, 175 Modifiers *computedMask) 176{ 177 int i,j,ref; 178 ModToKeysymTable* temp; 179 XtPerDisplay perDisplay; 180 Boolean found; 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", 188 (String *)NULL, (Cardinal *)NULL); 189 return FALSE; 190 } 191 _InitializeKeysymTables(dpy, perDisplay); 192 for (ref=0; lateModifiers[ref].keysym; ref++) { 193 found = FALSE; 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; break; 204 } 205 } 206 if (found) break; 207 } 208 if (!found && !lateModifiers[ref].knot) 209 if (!lateModifiers[ref].pair && (tempKeysym == NoSymbol)) 210 return FALSE; 211 /* if you didn't find the modifier and the modifier must be 212 asserted then return FALSE. If you didn't find the modifier 213 and the modifier must be off, then it is OK . Don't 214 return FALSE if this is the first member of a pair or if 215 it is the second member of a pair when the first member 216 was bound to a modifier */ 217 if (!lateModifiers[ref].pair) tempKeysym = NoSymbol; 218 } 219 return TRUE; 220} 221 222void _XtAllocTMContext( 223 XtPerDisplay pd) 224{ 225 TMKeyContext ctx; 226 ctx = (TMKeyContext)_XtHeapAlloc(&pd->heap, 227 sizeof(TMKeyContextRec)); 228 ctx->event = NULL; 229 ctx->serial = 0; 230 ctx->keysym = NoSymbol; 231 ctx->modifiers = 0; 232 FLUSHKEYCACHE(ctx); 233 pd->tm_context = ctx; 234} 235 236static unsigned int num_bits(unsigned long mask) 237{ 238 register unsigned long y; 239 240 y = (mask >> 1) &033333333333; 241 y = mask - y - ((y >>1) & 033333333333); 242 return ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077)); 243} 244 245Boolean _XtMatchUsingDontCareMods( 246 TMTypeMatch typeMatch, 247 TMModifierMatch modMatch, 248 TMEventPtr eventSeq) 249{ 250 Modifiers modifiers_return; 251 KeySym keysym_return; 252 Modifiers useful_mods; 253 int i, num_modbits; 254 Modifiers computed = 0; 255 Modifiers computedMask = 0; 256 Boolean resolved = TRUE; 257 Display *dpy = eventSeq->xev->xany.display; 258 XtPerDisplay pd; 259 TMKeyContext tm_context; 260 261 if (modMatch->lateModifiers != NULL) 262 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 263 &computed, &computedMask); 264 if (!resolved) return FALSE; 265 computed |= modMatch->modifiers; 266 computedMask |= modMatch->modifierMask; /* gives do-care mask */ 267 268 if ( (computed & computedMask) == 269 (eventSeq->event.modifiers & computedMask) ) { 270 271 pd = _XtGetPerDisplay(dpy); 272 tm_context = pd->tm_context; 273 TRANSLATE(tm_context, pd, dpy, (KeyCode)eventSeq->event.eventCode, 274 (unsigned)0, modifiers_return, keysym_return); 275 276 if ((keysym_return & typeMatch->eventCodeMask) == typeMatch->eventCode ) { 277 tm_context->event = eventSeq->xev; 278 tm_context->serial = eventSeq->xev->xany.serial; 279 tm_context->keysym = keysym_return; 280 tm_context->modifiers = (Modifiers)0; 281 return TRUE; 282 } 283 useful_mods = ~computedMask & modifiers_return; 284 if (useful_mods == 0) return FALSE; 285 286 switch (num_modbits = num_bits(useful_mods)) { 287 case 1: 288 case 8: 289 /* 290 * one modbit should never happen, in fact the implementation 291 * of XtTranslateKey and XmTranslateKey guarantee that it 292 * won't, so don't care if the loop is set up for the case 293 * when one modbit is set. 294 * The performance implications of all eight modbits being 295 * set is horrendous. This isn't a problem with Xt/Xaw based 296 * applications. We can only hope that Motif's virtual 297 * modifiers won't result in all eight modbits being set. 298 */ 299 for (i = useful_mods; i > 0; i--) { 300 TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 301 (Modifiers)i, modifiers_return, keysym_return); 302 if (keysym_return == 303 (typeMatch->eventCode & typeMatch->eventCodeMask)) { 304 tm_context->event = eventSeq->xev; 305 tm_context->serial = eventSeq->xev->xany.serial; 306 tm_context->keysym = keysym_return; 307 tm_context->modifiers = (Modifiers)i; 308 return TRUE; 309 } 310 } 311 break; 312 default: /* (2..7) */ 313 { 314 /* 315 * Only translate using combinations of the useful modifiers. 316 * to minimize the chance of invalidating the cache. 317 */ 318 static char pows[] = { 0, 1, 3, 7, 15, 31, 63, 127 }; 319 Modifiers tmod, mod_masks[8]; 320 int j; 321 for (tmod = 1, i = 0; tmod <= (Mod5Mask<<1); tmod <<= 1) 322 if (tmod & useful_mods) mod_masks[i++] = tmod; 323 for (j = (int) pows[num_modbits]; j > 0; j--) { 324 tmod = 0; 325 for (i = 0; i < num_modbits; i++) 326 if (j & (1<<i)) tmod |= mod_masks[i]; 327 TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 328 tmod, modifiers_return, keysym_return); 329 if (keysym_return == 330 (typeMatch->eventCode & typeMatch->eventCodeMask)) { 331 tm_context->event = eventSeq->xev; 332 tm_context->serial = eventSeq->xev->xany.serial; 333 tm_context->keysym = keysym_return; 334 tm_context->modifiers = (Modifiers)i; 335 return TRUE; 336 } 337 } 338 } 339 break; 340 } /* switch (num_modbits) */ 341 } 342 return FALSE; 343} 344 345void XtConvertCase( 346 Display *dpy, 347 KeySym keysym, 348 KeySym *lower_return, 349 KeySym *upper_return) 350{ 351 XtPerDisplay pd; 352 CaseConverterPtr ptr; 353 DPY_TO_APPCON(dpy); 354 355 LOCK_APP(app); 356 pd = _XtGetPerDisplay(dpy); 357 358 *lower_return = *upper_return = keysym; 359 for (ptr=pd->case_cvt; ptr; ptr = ptr->next) 360 if (ptr->start <= keysym && keysym <= ptr->stop) { 361 (*ptr->proc)(dpy, keysym, lower_return, upper_return); 362 return; 363 } 364 XConvertCase(keysym, lower_return, upper_return); 365 UNLOCK_APP(app); 366} 367 368Boolean _XtMatchUsingStandardMods ( 369 TMTypeMatch typeMatch, 370 TMModifierMatch modMatch, 371 TMEventPtr eventSeq) 372{ 373 Modifiers modifiers_return; 374 KeySym keysym_return; 375 Modifiers computed= 0; 376 Modifiers computedMask = 0; 377 Boolean resolved = TRUE; 378 Display *dpy = eventSeq->xev->xany.display; 379 XtPerDisplay pd = _XtGetPerDisplay(dpy); 380 TMKeyContext tm_context = pd->tm_context; 381 Modifiers translateModifiers; 382 383 /* To maximize cache utilization, we mask off nonstandard modifiers 384 before cache lookup. For a given key translator, standard modifiers 385 are constant per KeyCode. If a key translator uses no standard 386 modifiers this implementation will never reference the cache. 387 */ 388 389 modifiers_return = MOD_RETURN(tm_context, eventSeq->event.eventCode); 390 if (!modifiers_return) { 391 XtTranslateKeycode(dpy, (KeyCode)eventSeq->event.eventCode, 392 eventSeq->event.modifiers, &modifiers_return, 393 &keysym_return); 394 translateModifiers = eventSeq->event.modifiers & modifiers_return; 395 UPDATE_CACHE(tm_context, pd, eventSeq->event.eventCode, 396 translateModifiers, modifiers_return, keysym_return); 397 } else { 398 translateModifiers = eventSeq->event.modifiers & modifiers_return; 399 TRANSLATE(tm_context, pd, dpy, (KeyCode)eventSeq->event.eventCode, 400 translateModifiers, modifiers_return, keysym_return); 401 } 402 403 if ((typeMatch->eventCode & typeMatch->eventCodeMask) == 404 (keysym_return & typeMatch->eventCodeMask)) { 405 if (modMatch->lateModifiers != NULL) 406 resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 407 &computed, &computedMask); 408 if (!resolved) return FALSE; 409 computed |= modMatch->modifiers; 410 computedMask |= modMatch->modifierMask; 411 412 if ((computed & computedMask) == 413 (eventSeq->event.modifiers & ~modifiers_return & computedMask)) { 414 tm_context->event = eventSeq->xev; 415 tm_context->serial = eventSeq->xev->xany.serial; 416 tm_context->keysym = keysym_return; 417 tm_context->modifiers = translateModifiers; 418 return TRUE; 419 } 420 } 421 return FALSE; 422} 423 424 425void _XtBuildKeysymTables( 426 Display *dpy, 427 register XtPerDisplay pd) 428{ 429 ModToKeysymTable *table; 430 int maxCount,i,j,k,tempCount,idx; 431 KeySym keysym,tempKeysym; 432 XModifierKeymap* modKeymap; 433 KeyCode keycode; 434#define KeysymTableSize 16 435 436 FLUSHKEYCACHE(pd->tm_context); 437 if (pd->keysyms) 438 XFree( (char *)pd->keysyms ); 439 pd->keysyms_serial = NextRequest(dpy); 440 pd->keysyms = XGetKeyboardMapping(dpy, pd->min_keycode, 441 pd->max_keycode-pd->min_keycode+1, 442 &pd->keysyms_per_keycode); 443 if (pd->modKeysyms) 444 XtFree((char *)pd->modKeysyms); 445 if (pd->modsToKeysyms) 446 XtFree((char *)pd->modsToKeysyms); 447 pd->modKeysyms = (KeySym*)__XtMalloc((Cardinal)KeysymTableSize*sizeof(KeySym)); 448 maxCount = KeysymTableSize; 449 tempCount = 0; 450 451 table = (ModToKeysymTable*)__XtMalloc((Cardinal)8*sizeof(ModToKeysymTable)); 452 pd->modsToKeysyms = table; 453 454 table[0].mask = ShiftMask; 455 table[1].mask = LockMask; 456 table[2].mask = ControlMask; 457 table[3].mask = Mod1Mask; 458 table[4].mask = Mod2Mask; 459 table[5].mask = Mod3Mask; 460 table[6].mask = Mod4Mask; 461 table[7].mask = Mod5Mask; 462 tempKeysym = 0; 463 464 modKeymap = XGetModifierMapping(dpy); 465 for (i=0;i<32;i++) 466 pd->isModifier[i] = 0; 467 pd->mode_switch = 0; 468 pd->num_lock = 0; 469 for (i=0;i<8;i++) { 470 table[i].idx = tempCount; 471 table[i].count = 0; 472 for (j=0;j<modKeymap->max_keypermod;j++) { 473 keycode = modKeymap->modifiermap[i*modKeymap->max_keypermod+j]; 474 if (keycode != 0) { 475 pd->isModifier[keycode>>3] |= 1 << (keycode & 7); 476 for (k=0; k<pd->keysyms_per_keycode;k++) { 477 idx = ((keycode-pd->min_keycode)* 478 pd->keysyms_per_keycode)+k; 479 keysym = pd->keysyms[idx]; 480 if ((keysym == XK_Mode_switch) && (i > 2)) 481 pd->mode_switch |= 1 << i; 482 if ((keysym == XK_Num_Lock) && (i > 2)) 483 pd->num_lock |= 1 << i; 484 if (keysym != 0 && keysym != tempKeysym ){ 485 if (tempCount==maxCount) { 486 maxCount += KeysymTableSize; 487 pd->modKeysyms = (KeySym*)XtRealloc( 488 (char*)pd->modKeysyms, 489 (unsigned) (maxCount*sizeof(KeySym)) ); 490 } 491 pd->modKeysyms[tempCount++] = keysym; 492 table[i].count++; 493 tempKeysym = keysym; 494 } 495 } 496 } 497 } 498 } 499 pd->lock_meaning = NoSymbol; 500 for (i = 0; i < table[1].count; i++) { 501 keysym = pd->modKeysyms[table[1].idx + i]; 502 if (keysym == XK_Caps_Lock) { 503 pd->lock_meaning = XK_Caps_Lock; 504 break; 505 } else if (keysym == XK_Shift_Lock) { 506 pd->lock_meaning = XK_Shift_Lock; 507 } 508 } 509 XFreeModifiermap(modKeymap); 510} 511 512void XtTranslateKeycode ( 513 Display *dpy, 514 _XtKeyCode keycode, 515 Modifiers modifiers, 516 Modifiers *modifiers_return, 517 KeySym *keysym_return) 518{ 519 XtPerDisplay pd; 520 DPY_TO_APPCON(dpy); 521 522 LOCK_APP(app); 523 pd = _XtGetPerDisplay(dpy); 524 _InitializeKeysymTables(dpy, pd); 525 (*pd->defaultKeycodeTranslator)( 526 dpy,keycode,modifiers,modifiers_return,keysym_return); 527 UNLOCK_APP(app); 528} 529 530/* This code should match XTranslateKey (internal, sigh) in Xlib */ 531void XtTranslateKey( 532 register Display *dpy, 533 _XtKeyCode keycode, 534 Modifiers modifiers, 535 Modifiers *modifiers_return, 536 KeySym *keysym_return) 537{ 538#ifndef XKB 539 XtPerDisplay pd; 540 int per; 541 register KeySym *syms; 542 KeySym sym, lsym, usym; 543 DPY_TO_APPCON(dpy); 544 545 LOCK_APP(app); 546 pd = _XtGetPerDisplay(dpy); 547 *modifiers_return = (ShiftMask|LockMask) | pd->mode_switch | pd->num_lock; 548 if (((int)keycode < pd->min_keycode) || ((int)keycode > pd->max_keycode)) { 549 *keysym_return = NoSymbol; 550 UNLOCK_APP(app); 551 return; 552 } 553 per = pd->keysyms_per_keycode; 554 syms = &pd->keysyms[(keycode - pd->min_keycode) * per]; 555 while ((per > 2) && (syms[per - 1] == NoSymbol)) 556 per--; 557 if ((per > 2) && (modifiers & pd->mode_switch)) { 558 syms += 2; 559 per -= 2; 560 } 561 if ((modifiers & pd->num_lock) && 562 (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { 563 if ((modifiers & ShiftMask) || 564 ((modifiers & LockMask) && (pd->lock_meaning == XK_Shift_Lock))) 565 *keysym_return = syms[0]; 566 else 567 *keysym_return = syms[1]; 568 } else if (!(modifiers & ShiftMask) && 569 (!(modifiers & LockMask) || (pd->lock_meaning == NoSymbol))) { 570 if ((per == 1) || (syms[1] == NoSymbol)) 571 XtConvertCase(dpy, syms[0], keysym_return, &usym); 572 else 573 *keysym_return = syms[0]; 574 } else if (!(modifiers & LockMask) || 575 (pd->lock_meaning != XK_Caps_Lock)) { 576 if ((per == 1) || ((usym = syms[1]) == NoSymbol)) 577 XtConvertCase(dpy, syms[0], &lsym, &usym); 578 *keysym_return = usym; 579 } else { 580 if ((per == 1) || ((sym = syms[1]) == NoSymbol)) 581 sym = syms[0]; 582 XtConvertCase(dpy, sym, &lsym, &usym); 583 if (!(modifiers & ShiftMask) && (sym != syms[0]) && 584 ((sym != usym) || (lsym == usym))) 585 XtConvertCase(dpy, syms[0], &lsym, &usym); 586 *keysym_return = usym; 587 } 588 589 if (*keysym_return == XK_VoidSymbol) 590 *keysym_return = NoSymbol; 591 UNLOCK_APP(app); 592#else 593 XkbLookupKeySym(dpy, keycode, modifiers, modifiers_return, keysym_return); 594#endif 595} 596 597void XtSetKeyTranslator( 598 Display *dpy, 599 XtKeyProc translator) 600{ 601 XtPerDisplay pd; 602 DPY_TO_APPCON(dpy); 603 604 LOCK_APP(app); 605 pd = _XtGetPerDisplay(dpy); 606 607 pd->defaultKeycodeTranslator = translator; 608 FLUSHKEYCACHE(pd->tm_context); 609 /* XXX should now redo grabs */ 610 UNLOCK_APP(app); 611} 612 613void XtRegisterCaseConverter( 614 Display *dpy, 615 XtCaseProc proc, 616 KeySym start, 617 KeySym stop) 618{ 619 XtPerDisplay pd; 620 CaseConverterPtr ptr, prev; 621 DPY_TO_APPCON(dpy); 622 623 LOCK_APP(app); 624 pd = _XtGetPerDisplay(dpy); 625 626 ptr = (CaseConverterPtr) __XtMalloc(sizeof(CaseConverterRec)); 627 ptr->start = start; 628 ptr->stop = stop; 629 ptr->proc = proc; 630 ptr->next = pd->case_cvt; 631 pd->case_cvt = ptr; 632 633 /* Remove obsolete case converters from the list */ 634 prev = ptr; 635 for (ptr=ptr->next; ptr; ptr=prev->next) { 636 if (start <= ptr->start && stop >= ptr->stop) { 637 prev->next = ptr->next; 638 XtFree((char *)ptr); 639 } 640 else prev = ptr; 641 } 642 FLUSHKEYCACHE(pd->tm_context); 643 /* XXX should now redo grabs */ 644 UNLOCK_APP(app); 645} 646 647KeySym *XtGetKeysymTable( 648 Display *dpy, 649 KeyCode *min_keycode_return, 650 int *keysyms_per_keycode_return) 651{ 652 XtPerDisplay pd; 653 KeySym* retval; 654 DPY_TO_APPCON(dpy); 655 656 LOCK_APP(app); 657 pd = _XtGetPerDisplay(dpy); 658 _InitializeKeysymTables(dpy, pd); 659 *min_keycode_return = pd->min_keycode; /* %%% */ 660 *keysyms_per_keycode_return = pd->keysyms_per_keycode; 661 retval = pd->keysyms; 662 UNLOCK_APP(app); 663 return retval; 664} 665 666void XtKeysymToKeycodeList( 667 Display *dpy, 668 KeySym keysym, 669 KeyCode **keycodes_return, 670 Cardinal *keycount_return) 671{ 672 XtPerDisplay pd; 673 unsigned keycode; 674 int per, match; 675 register KeySym *syms; 676 register int i, j; 677 KeySym lsym, usym; 678 unsigned maxcodes = 0; 679 unsigned ncodes = 0; 680 KeyCode *keycodes, *codeP = NULL; 681 DPY_TO_APPCON(dpy); 682 683 LOCK_APP(app); 684 pd = _XtGetPerDisplay(dpy); 685 _InitializeKeysymTables(dpy, pd); 686 keycodes = NULL; 687 per = pd->keysyms_per_keycode; 688 for (syms = pd->keysyms, keycode = (unsigned) pd->min_keycode; 689 (int)keycode <= pd->max_keycode; 690 syms += per, keycode++) { 691 match = 0; 692 for (j = 0; j < per; j++) { 693 if (syms[j] == keysym) { 694 match = 1; 695 break; 696 } 697 } 698 if (!match) 699 for (i = 1; i < 5; i += 2) { 700 if ((per == i) || ((per > i) && (syms[i] == NoSymbol))) { 701 XtConvertCase(dpy, syms[i-1], &lsym, &usym); 702 if ((lsym == keysym) || (usym == keysym)) { 703 match = 1; 704 break; 705 } 706 } 707 } 708 if (match) { 709 if (ncodes == maxcodes) { 710 KeyCode *old = keycodes; 711 maxcodes += KEYCODE_ARRAY_SIZE; 712 keycodes = (KeyCode*)__XtMalloc(maxcodes*sizeof(KeyCode)); 713 if (ncodes) { 714 (void) memmove((char *)keycodes, (char *)old, 715 ncodes*sizeof(KeyCode) ); 716 XtFree((char *)old); 717 } 718 codeP = &keycodes[ncodes]; 719 } 720 *codeP++ = (KeyCode) keycode; 721 ncodes++; 722 } 723 } 724 *keycodes_return = keycodes; 725 *keycount_return = ncodes; 726 UNLOCK_APP(app); 727} 728