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