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