TMkey.c revision 444c061a
1444c061aSmrg/* $Xorg: TMkey.c,v 1.4 2001/02/09 02:03:58 xorgcvs Exp $ */ 2444c061aSmrg/*LINTLIBRARY*/ 3444c061aSmrg 4444c061aSmrg/*********************************************************** 5444c061aSmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, 6444c061aSmrgCopyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 7444c061aSmrg 8444c061aSmrg All Rights Reserved 9444c061aSmrg 10444c061aSmrgPermission to use, copy, modify, and distribute this software and its 11444c061aSmrgdocumentation for any purpose and without fee is hereby granted, 12444c061aSmrgprovided that the above copyright notice appear in all copies and that 13444c061aSmrgboth that copyright notice and this permission notice appear in 14444c061aSmrgsupporting documentation, and that the names of Digital or Sun not be 15444c061aSmrgused in advertising or publicity pertaining to distribution of the 16444c061aSmrgsoftware without specific, written prior permission. 17444c061aSmrg 18444c061aSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 19444c061aSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 20444c061aSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 21444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22444c061aSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 23444c061aSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 24444c061aSmrgSOFTWARE. 25444c061aSmrg 26444c061aSmrgSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 27444c061aSmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 28444c061aSmrgNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 29444c061aSmrgABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 30444c061aSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 31444c061aSmrgPROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 32444c061aSmrgOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 33444c061aSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 34444c061aSmrg 35444c061aSmrg******************************************************************/ 36444c061aSmrg 37444c061aSmrg/* 38444c061aSmrg 39444c061aSmrgCopyright 1987, 1988, 1994, 1998 The Open Group 40444c061aSmrg 41444c061aSmrgPermission to use, copy, modify, distribute, and sell this software and its 42444c061aSmrgdocumentation for any purpose is hereby granted without fee, provided that 43444c061aSmrgthe above copyright notice appear in all copies and that both that 44444c061aSmrgcopyright notice and this permission notice appear in supporting 45444c061aSmrgdocumentation. 46444c061aSmrg 47444c061aSmrgThe above copyright notice and this permission notice shall be included in 48444c061aSmrgall copies or substantial portions of the Software. 49444c061aSmrg 50444c061aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51444c061aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52444c061aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53444c061aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 54444c061aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 55444c061aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56444c061aSmrg 57444c061aSmrgExcept as contained in this notice, the name of The Open Group shall not be 58444c061aSmrgused in advertising or otherwise to promote the sale, use or other dealings 59444c061aSmrgin this Software without prior written authorization from The Open Group. 60444c061aSmrg 61444c061aSmrg*/ 62444c061aSmrg/* $XFree86: xc/lib/Xt/TMkey.c,v 3.10 2001/12/14 19:56:30 dawes Exp $ */ 63444c061aSmrg 64444c061aSmrg#define XK_MISCELLANY 65444c061aSmrg#define XK_LATIN1 66444c061aSmrg#define XK_LATIN2 67444c061aSmrg#define XK_LATIN3 68444c061aSmrg#define XK_LATIN4 69444c061aSmrg 70444c061aSmrg#ifdef HAVE_CONFIG_H 71444c061aSmrg#include <config.h> 72444c061aSmrg#endif 73444c061aSmrg#include "IntrinsicI.h" 74444c061aSmrg#include <X11/keysymdef.h> 75444c061aSmrg#ifdef XKB 76444c061aSmrg#include <X11/XKBlib.h> 77444c061aSmrg#endif 78444c061aSmrg 79444c061aSmrg#define FLUSHKEYCACHE(ctx) \ 80444c061aSmrg bzero((char *)&ctx->keycache, sizeof(TMKeyCache)) 81444c061aSmrg 82444c061aSmrg/* 83444c061aSmrg * The following array reorders the modifier bits so that the most common ones 84444c061aSmrg * (used by a translator) are in the top-most bits with respect to the size of 85444c061aSmrg * the keycache. The array currently just reverses the bits as a good guess. 86444c061aSmrg * This might be more trouble than it is worth, but it seems to help. 87444c061aSmrg */ 88444c061aSmrg 89444c061aSmrg#define FM(i) i >> (8 - TMKEYCACHELOG2) 90444c061aSmrgstatic const unsigned char modmix[256] = { 91444c061aSmrgFM(0x0f), FM(0x8f), FM(0x4f), FM(0xcf), FM(0x2f), FM(0xaf), FM(0x6f), FM(0xef), 92444c061aSmrgFM(0x1f), FM(0x9f), FM(0x5f), FM(0xdf), FM(0x3f), FM(0xbf), FM(0x7f), FM(0xff), 93444c061aSmrgFM(0x07), FM(0x87), FM(0x47), FM(0xc7), FM(0x27), FM(0xa7), FM(0x67), FM(0xe7), 94444c061aSmrgFM(0x17), FM(0x97), FM(0x57), FM(0xd7), FM(0x37), FM(0xb7), FM(0x77), FM(0xf7), 95444c061aSmrgFM(0x0b), FM(0x8b), FM(0x4b), FM(0xcb), FM(0x2b), FM(0xab), FM(0x6b), FM(0xeb), 96444c061aSmrgFM(0x1b), FM(0x9b), FM(0x5b), FM(0xdb), FM(0x3b), FM(0xbb), FM(0x7b), FM(0xfb), 97444c061aSmrgFM(0x03), FM(0x83), FM(0x43), FM(0xc3), FM(0x23), FM(0xa3), FM(0x63), FM(0xe3), 98444c061aSmrgFM(0x13), FM(0x93), FM(0x53), FM(0xd3), FM(0x33), FM(0xb3), FM(0x73), FM(0xf3), 99444c061aSmrgFM(0x0d), FM(0x8d), FM(0x4d), FM(0xcd), FM(0x2d), FM(0xad), FM(0x6d), FM(0xed), 100444c061aSmrgFM(0x1d), FM(0x9d), FM(0x5d), FM(0xdd), FM(0x3d), FM(0xbd), FM(0x7d), FM(0xfd), 101444c061aSmrgFM(0x05), FM(0x85), FM(0x45), FM(0xc5), FM(0x25), FM(0xa5), FM(0x65), FM(0xe5), 102444c061aSmrgFM(0x15), FM(0x95), FM(0x55), FM(0xd5), FM(0x35), FM(0xb5), FM(0x75), FM(0xf5), 103444c061aSmrgFM(0x09), FM(0x89), FM(0x49), FM(0xc9), FM(0x29), FM(0xa9), FM(0x69), FM(0xe9), 104444c061aSmrgFM(0x19), FM(0x99), FM(0x59), FM(0xd9), FM(0x39), FM(0xb9), FM(0x79), FM(0xf9), 105444c061aSmrgFM(0x01), FM(0x81), FM(0x41), FM(0xc1), FM(0x21), FM(0xa1), FM(0x61), FM(0xe1), 106444c061aSmrgFM(0x11), FM(0x91), FM(0x51), FM(0xd1), FM(0x31), FM(0xb1), FM(0x71), FM(0xf1), 107444c061aSmrgFM(0x00), FM(0x8e), FM(0x4e), FM(0xce), FM(0x2e), FM(0xae), FM(0x6e), FM(0xee), 108444c061aSmrgFM(0x1e), FM(0x9e), FM(0x5e), FM(0xde), FM(0x3e), FM(0xbe), FM(0x7e), FM(0xfe), 109444c061aSmrgFM(0x08), FM(0x88), FM(0x48), FM(0xc8), FM(0x28), FM(0xa8), FM(0x68), FM(0xe8), 110444c061aSmrgFM(0x18), FM(0x98), FM(0x58), FM(0xd8), FM(0x38), FM(0xb8), FM(0x78), FM(0xf8), 111444c061aSmrgFM(0x04), FM(0x84), FM(0x44), FM(0xc4), FM(0x24), FM(0xa4), FM(0x64), FM(0xe4), 112444c061aSmrgFM(0x14), FM(0x94), FM(0x54), FM(0xd4), FM(0x34), FM(0xb4), FM(0x74), FM(0xf4), 113444c061aSmrgFM(0x0c), FM(0x8c), FM(0x4c), FM(0xcc), FM(0x2c), FM(0xac), FM(0x6c), FM(0xec), 114444c061aSmrgFM(0x1c), FM(0x9c), FM(0x5c), FM(0xdc), FM(0x3c), FM(0xbc), FM(0x7c), FM(0xfc), 115444c061aSmrgFM(0x02), FM(0x82), FM(0x42), FM(0xc2), FM(0x22), FM(0xa2), FM(0x62), FM(0xe2), 116444c061aSmrgFM(0x12), FM(0x92), FM(0x52), FM(0xd2), FM(0x32), FM(0xb2), FM(0x72), FM(0xf2), 117444c061aSmrgFM(0x0a), FM(0x8a), FM(0x4a), FM(0xca), FM(0x2a), FM(0xaa), FM(0x6a), FM(0xea), 118444c061aSmrgFM(0x1a), FM(0x9a), FM(0x5a), FM(0xda), FM(0x3a), FM(0xba), FM(0x7a), FM(0xfa), 119444c061aSmrgFM(0x06), FM(0x86), FM(0x46), FM(0xc6), FM(0x26), FM(0xa6), FM(0x66), FM(0xe6), 120444c061aSmrgFM(0x16), FM(0x96), FM(0x56), FM(0xd6), FM(0x36), FM(0xb6), FM(0x76), FM(0xf6), 121444c061aSmrgFM(0x0e), FM(0x8e), FM(0x4e), FM(0xce), FM(0x2e), FM(0xae), FM(0x6e), FM(0xee), 122444c061aSmrgFM(0x1e), FM(0x9e), FM(0x5e), FM(0xde), FM(0x3e), FM(0xbe), FM(0x7e), FM(0xfe) 123444c061aSmrg}; 124444c061aSmrg#undef FM 125444c061aSmrg 126444c061aSmrg#define MOD_RETURN(ctx, key) (ctx)->keycache.modifiers_return[key] 127444c061aSmrg 128444c061aSmrg#define TRANSLATE(ctx,pd,dpy,key,mod,mod_ret,sym_ret) \ 129444c061aSmrg{ \ 130444c061aSmrg int _i_ = (((key) - (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 131444c061aSmrg (TMKEYCACHESIZE-1)); \ 132444c061aSmrg if ((key) != 0 && /* Xlib XIM composed input */ \ 133444c061aSmrg (ctx)->keycache.keycode[_i_] == (key) && \ 134444c061aSmrg (ctx)->keycache.modifiers[_i_] == (mod)) { \ 135444c061aSmrg mod_ret = MOD_RETURN(ctx, key); \ 136444c061aSmrg sym_ret = (ctx)->keycache.keysym[_i_]; \ 137444c061aSmrg } else { \ 138444c061aSmrg XtTranslateKeycode(dpy, key, mod, &mod_ret, &sym_ret); \ 139444c061aSmrg (ctx)->keycache.keycode[_i_] = key; \ 140444c061aSmrg (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 141444c061aSmrg (ctx)->keycache.keysym[_i_] = sym_ret; \ 142444c061aSmrg MOD_RETURN(ctx, key) = (unsigned char)mod_ret; \ 143444c061aSmrg } \ 144444c061aSmrg} 145444c061aSmrg 146444c061aSmrg#define UPDATE_CACHE(ctx, pd, key, mod, mod_ret, sym_ret) \ 147444c061aSmrg{ \ 148444c061aSmrg int _i_ = (((key) - (pd)->min_keycode + modmix[(mod) & 0xff]) & \ 149444c061aSmrg (TMKEYCACHESIZE-1)); \ 150444c061aSmrg (ctx)->keycache.keycode[_i_] = key; \ 151444c061aSmrg (ctx)->keycache.modifiers[_i_] = (unsigned char)(mod); \ 152444c061aSmrg (ctx)->keycache.keysym[_i_] = sym_ret; \ 153444c061aSmrg MOD_RETURN(ctx, key) = (unsigned char)mod_ret; \ 154444c061aSmrg} 155444c061aSmrg 156444c061aSmrg/* usual number of expected keycodes in XtKeysymToKeycodeList */ 157444c061aSmrg#define KEYCODE_ARRAY_SIZE 10 158444c061aSmrg 159444c061aSmrgBoolean _XtComputeLateBindings( 160444c061aSmrg Display *dpy, 161444c061aSmrg LateBindingsPtr lateModifiers, 162444c061aSmrg Modifiers *computed, 163444c061aSmrg Modifiers *computedMask) 164444c061aSmrg{ 165444c061aSmrg int i,j,ref; 166444c061aSmrg ModToKeysymTable* temp; 167444c061aSmrg XtPerDisplay perDisplay; 168444c061aSmrg Boolean found; 169444c061aSmrg KeySym tempKeysym = NoSymbol; 170444c061aSmrg 171444c061aSmrg perDisplay = _XtGetPerDisplay(dpy); 172444c061aSmrg if (perDisplay == NULL) { 173444c061aSmrg XtAppWarningMsg(XtDisplayToApplicationContext(dpy), 174444c061aSmrg "displayError","invalidDisplay",XtCXtToolkitError, 175444c061aSmrg "Can't find display structure", 176444c061aSmrg (String *)NULL, (Cardinal *)NULL); 177444c061aSmrg return FALSE; 178444c061aSmrg } 179444c061aSmrg _InitializeKeysymTables(dpy, perDisplay); 180444c061aSmrg for (ref=0; lateModifiers[ref].keysym; ref++) { 181444c061aSmrg found = FALSE; 182444c061aSmrg for (i=0;i<8;i++) { 183444c061aSmrg temp = &(perDisplay->modsToKeysyms[i]); 184444c061aSmrg for (j=0;j<temp->count;j++){ 185444c061aSmrg if (perDisplay->modKeysyms[temp->idx+j] == 186444c061aSmrg lateModifiers[ref].keysym) { 187444c061aSmrg *computedMask = *computedMask | temp->mask; 188444c061aSmrg if (!lateModifiers[ref].knot) 189444c061aSmrg *computed |= temp->mask; 190444c061aSmrg tempKeysym = lateModifiers[ref].keysym; 191444c061aSmrg found = TRUE; break; 192444c061aSmrg } 193444c061aSmrg } 194444c061aSmrg if (found) break; 195444c061aSmrg } 196444c061aSmrg if (!found && !lateModifiers[ref].knot) 197444c061aSmrg if (!lateModifiers[ref].pair && (tempKeysym == NoSymbol)) 198444c061aSmrg return FALSE; 199444c061aSmrg /* if you didn't find the modifier and the modifier must be 200444c061aSmrg asserted then return FALSE. If you didn't find the modifier 201444c061aSmrg and the modifier must be off, then it is OK . Don't 202444c061aSmrg return FALSE if this is the first member of a pair or if 203444c061aSmrg it is the second member of a pair when the first member 204444c061aSmrg was bound to a modifier */ 205444c061aSmrg if (!lateModifiers[ref].pair) tempKeysym = NoSymbol; 206444c061aSmrg } 207444c061aSmrg return TRUE; 208444c061aSmrg} 209444c061aSmrg 210444c061aSmrgvoid _XtAllocTMContext( 211444c061aSmrg XtPerDisplay pd) 212444c061aSmrg{ 213444c061aSmrg TMKeyContext ctx; 214444c061aSmrg ctx = (TMKeyContext)_XtHeapAlloc(&pd->heap, 215444c061aSmrg sizeof(TMKeyContextRec)); 216444c061aSmrg ctx->event = NULL; 217444c061aSmrg ctx->serial = 0; 218444c061aSmrg ctx->keysym = NoSymbol; 219444c061aSmrg ctx->modifiers = 0; 220444c061aSmrg FLUSHKEYCACHE(ctx); 221444c061aSmrg pd->tm_context = ctx; 222444c061aSmrg} 223444c061aSmrg 224444c061aSmrgstatic unsigned int num_bits(unsigned long mask) 225444c061aSmrg{ 226444c061aSmrg register unsigned long y; 227444c061aSmrg 228444c061aSmrg y = (mask >> 1) &033333333333; 229444c061aSmrg y = mask - y - ((y >>1) & 033333333333); 230444c061aSmrg return ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077)); 231444c061aSmrg} 232444c061aSmrg 233444c061aSmrgBoolean _XtMatchUsingDontCareMods( 234444c061aSmrg TMTypeMatch typeMatch, 235444c061aSmrg TMModifierMatch modMatch, 236444c061aSmrg TMEventPtr eventSeq) 237444c061aSmrg{ 238444c061aSmrg Modifiers modifiers_return; 239444c061aSmrg KeySym keysym_return; 240444c061aSmrg Modifiers useful_mods; 241444c061aSmrg int i, num_modbits; 242444c061aSmrg Modifiers computed = 0; 243444c061aSmrg Modifiers computedMask = 0; 244444c061aSmrg Boolean resolved = TRUE; 245444c061aSmrg Display *dpy = eventSeq->xev->xany.display; 246444c061aSmrg XtPerDisplay pd; 247444c061aSmrg TMKeyContext tm_context; 248444c061aSmrg 249444c061aSmrg if (modMatch->lateModifiers != NULL) 250444c061aSmrg resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 251444c061aSmrg &computed, &computedMask); 252444c061aSmrg if (!resolved) return FALSE; 253444c061aSmrg computed |= modMatch->modifiers; 254444c061aSmrg computedMask |= modMatch->modifierMask; /* gives do-care mask */ 255444c061aSmrg 256444c061aSmrg if ( (computed & computedMask) == 257444c061aSmrg (eventSeq->event.modifiers & computedMask) ) { 258444c061aSmrg 259444c061aSmrg pd = _XtGetPerDisplay(dpy); 260444c061aSmrg tm_context = pd->tm_context; 261444c061aSmrg TRANSLATE(tm_context, pd, dpy, (KeyCode)eventSeq->event.eventCode, 262444c061aSmrg (unsigned)0, modifiers_return, keysym_return); 263444c061aSmrg 264444c061aSmrg if ((keysym_return & typeMatch->eventCodeMask) == typeMatch->eventCode ) { 265444c061aSmrg tm_context->event = eventSeq->xev; 266444c061aSmrg tm_context->serial = eventSeq->xev->xany.serial; 267444c061aSmrg tm_context->keysym = keysym_return; 268444c061aSmrg tm_context->modifiers = (Modifiers)0; 269444c061aSmrg return TRUE; 270444c061aSmrg } 271444c061aSmrg useful_mods = ~computedMask & modifiers_return; 272444c061aSmrg if (useful_mods == 0) return FALSE; 273444c061aSmrg 274444c061aSmrg switch (num_modbits = num_bits(useful_mods)) { 275444c061aSmrg case 1: 276444c061aSmrg case 8: 277444c061aSmrg /* 278444c061aSmrg * one modbit should never happen, in fact the implementation 279444c061aSmrg * of XtTranslateKey and XmTranslateKey guarantee that it 280444c061aSmrg * won't, so don't care if the loop is set up for the case 281444c061aSmrg * when one modbit is set. 282444c061aSmrg * The performance implications of all eight modbits being 283444c061aSmrg * set is horrendous. This isn't a problem with Xt/Xaw based 284444c061aSmrg * applications. We can only hope that Motif's virtual 285444c061aSmrg * modifiers won't result in all eight modbits being set. 286444c061aSmrg */ 287444c061aSmrg for (i = useful_mods; i > 0; i--) { 288444c061aSmrg TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 289444c061aSmrg (Modifiers)i, modifiers_return, keysym_return); 290444c061aSmrg if (keysym_return == 291444c061aSmrg (typeMatch->eventCode & typeMatch->eventCodeMask)) { 292444c061aSmrg tm_context->event = eventSeq->xev; 293444c061aSmrg tm_context->serial = eventSeq->xev->xany.serial; 294444c061aSmrg tm_context->keysym = keysym_return; 295444c061aSmrg tm_context->modifiers = (Modifiers)i; 296444c061aSmrg return TRUE; 297444c061aSmrg } 298444c061aSmrg } 299444c061aSmrg break; 300444c061aSmrg default: /* (2..7) */ 301444c061aSmrg { 302444c061aSmrg /* 303444c061aSmrg * Only translate using combinations of the useful modifiers. 304444c061aSmrg * to minimize the chance of invalidating the cache. 305444c061aSmrg */ 306444c061aSmrg static char pows[] = { 0, 1, 3, 7, 15, 31, 63, 127 }; 307444c061aSmrg Modifiers tmod, mod_masks[8]; 308444c061aSmrg int j; 309444c061aSmrg for (tmod = 1, i = 0; tmod <= (Mod5Mask<<1); tmod <<= 1) 310444c061aSmrg if (tmod & useful_mods) mod_masks[i++] = tmod; 311444c061aSmrg for (j = (int) pows[num_modbits]; j > 0; j--) { 312444c061aSmrg tmod = 0; 313444c061aSmrg for (i = 0; i < num_modbits; i++) 314444c061aSmrg if (j & (1<<i)) tmod |= mod_masks[i]; 315444c061aSmrg TRANSLATE(tm_context, pd, dpy, eventSeq->event.eventCode, 316444c061aSmrg tmod, modifiers_return, keysym_return); 317444c061aSmrg if (keysym_return == 318444c061aSmrg (typeMatch->eventCode & typeMatch->eventCodeMask)) { 319444c061aSmrg tm_context->event = eventSeq->xev; 320444c061aSmrg tm_context->serial = eventSeq->xev->xany.serial; 321444c061aSmrg tm_context->keysym = keysym_return; 322444c061aSmrg tm_context->modifiers = (Modifiers)i; 323444c061aSmrg return TRUE; 324444c061aSmrg } 325444c061aSmrg } 326444c061aSmrg } 327444c061aSmrg break; 328444c061aSmrg } /* switch (num_modbits) */ 329444c061aSmrg } 330444c061aSmrg return FALSE; 331444c061aSmrg} 332444c061aSmrg 333444c061aSmrgvoid XtConvertCase( 334444c061aSmrg Display *dpy, 335444c061aSmrg KeySym keysym, 336444c061aSmrg KeySym *lower_return, 337444c061aSmrg KeySym *upper_return) 338444c061aSmrg{ 339444c061aSmrg XtPerDisplay pd; 340444c061aSmrg CaseConverterPtr ptr; 341444c061aSmrg DPY_TO_APPCON(dpy); 342444c061aSmrg 343444c061aSmrg LOCK_APP(app); 344444c061aSmrg pd = _XtGetPerDisplay(dpy); 345444c061aSmrg 346444c061aSmrg *lower_return = *upper_return = keysym; 347444c061aSmrg for (ptr=pd->case_cvt; ptr; ptr = ptr->next) 348444c061aSmrg if (ptr->start <= keysym && keysym <= ptr->stop) { 349444c061aSmrg (*ptr->proc)(dpy, keysym, lower_return, upper_return); 350444c061aSmrg return; 351444c061aSmrg } 352444c061aSmrg XConvertCase(keysym, lower_return, upper_return); 353444c061aSmrg UNLOCK_APP(app); 354444c061aSmrg} 355444c061aSmrg 356444c061aSmrgBoolean _XtMatchUsingStandardMods ( 357444c061aSmrg TMTypeMatch typeMatch, 358444c061aSmrg TMModifierMatch modMatch, 359444c061aSmrg TMEventPtr eventSeq) 360444c061aSmrg{ 361444c061aSmrg Modifiers modifiers_return; 362444c061aSmrg KeySym keysym_return; 363444c061aSmrg Modifiers computed= 0; 364444c061aSmrg Modifiers computedMask = 0; 365444c061aSmrg Boolean resolved = TRUE; 366444c061aSmrg Display *dpy = eventSeq->xev->xany.display; 367444c061aSmrg XtPerDisplay pd = _XtGetPerDisplay(dpy); 368444c061aSmrg TMKeyContext tm_context = pd->tm_context; 369444c061aSmrg Modifiers translateModifiers; 370444c061aSmrg 371444c061aSmrg /* To maximize cache utilization, we mask off nonstandard modifiers 372444c061aSmrg before cache lookup. For a given key translator, standard modifiers 373444c061aSmrg are constant per KeyCode. If a key translator uses no standard 374444c061aSmrg modifiers this implementation will never reference the cache. 375444c061aSmrg */ 376444c061aSmrg 377444c061aSmrg modifiers_return = MOD_RETURN(tm_context, eventSeq->event.eventCode); 378444c061aSmrg if (!modifiers_return) { 379444c061aSmrg XtTranslateKeycode(dpy, (KeyCode)eventSeq->event.eventCode, 380444c061aSmrg eventSeq->event.modifiers, &modifiers_return, 381444c061aSmrg &keysym_return); 382444c061aSmrg translateModifiers = eventSeq->event.modifiers & modifiers_return; 383444c061aSmrg UPDATE_CACHE(tm_context, pd, eventSeq->event.eventCode, 384444c061aSmrg translateModifiers, modifiers_return, keysym_return); 385444c061aSmrg } else { 386444c061aSmrg translateModifiers = eventSeq->event.modifiers & modifiers_return; 387444c061aSmrg TRANSLATE(tm_context, pd, dpy, (KeyCode)eventSeq->event.eventCode, 388444c061aSmrg translateModifiers, modifiers_return, keysym_return); 389444c061aSmrg } 390444c061aSmrg 391444c061aSmrg if ((typeMatch->eventCode & typeMatch->eventCodeMask) == 392444c061aSmrg (keysym_return & typeMatch->eventCodeMask)) { 393444c061aSmrg if (modMatch->lateModifiers != NULL) 394444c061aSmrg resolved = _XtComputeLateBindings(dpy, modMatch->lateModifiers, 395444c061aSmrg &computed, &computedMask); 396444c061aSmrg if (!resolved) return FALSE; 397444c061aSmrg computed |= modMatch->modifiers; 398444c061aSmrg computedMask |= modMatch->modifierMask; 399444c061aSmrg 400444c061aSmrg if ((computed & computedMask) == 401444c061aSmrg (eventSeq->event.modifiers & ~modifiers_return & computedMask)) { 402444c061aSmrg tm_context->event = eventSeq->xev; 403444c061aSmrg tm_context->serial = eventSeq->xev->xany.serial; 404444c061aSmrg tm_context->keysym = keysym_return; 405444c061aSmrg tm_context->modifiers = translateModifiers; 406444c061aSmrg return TRUE; 407444c061aSmrg } 408444c061aSmrg } 409444c061aSmrg return FALSE; 410444c061aSmrg} 411444c061aSmrg 412444c061aSmrg 413444c061aSmrgvoid _XtBuildKeysymTables( 414444c061aSmrg Display *dpy, 415444c061aSmrg register XtPerDisplay pd) 416444c061aSmrg{ 417444c061aSmrg ModToKeysymTable *table; 418444c061aSmrg int maxCount,i,j,k,tempCount,idx; 419444c061aSmrg KeySym keysym,tempKeysym; 420444c061aSmrg XModifierKeymap* modKeymap; 421444c061aSmrg KeyCode keycode; 422444c061aSmrg#define KeysymTableSize 16 423444c061aSmrg 424444c061aSmrg FLUSHKEYCACHE(pd->tm_context); 425444c061aSmrg if (pd->keysyms) 426444c061aSmrg XFree( (char *)pd->keysyms ); 427444c061aSmrg pd->keysyms_serial = NextRequest(dpy); 428444c061aSmrg pd->keysyms = XGetKeyboardMapping(dpy, pd->min_keycode, 429444c061aSmrg pd->max_keycode-pd->min_keycode+1, 430444c061aSmrg &pd->keysyms_per_keycode); 431444c061aSmrg if (pd->modKeysyms) 432444c061aSmrg XtFree((char *)pd->modKeysyms); 433444c061aSmrg if (pd->modsToKeysyms) 434444c061aSmrg XtFree((char *)pd->modsToKeysyms); 435444c061aSmrg pd->modKeysyms = (KeySym*)__XtMalloc((Cardinal)KeysymTableSize*sizeof(KeySym)); 436444c061aSmrg maxCount = KeysymTableSize; 437444c061aSmrg tempCount = 0; 438444c061aSmrg 439444c061aSmrg table = (ModToKeysymTable*)__XtMalloc((Cardinal)8*sizeof(ModToKeysymTable)); 440444c061aSmrg pd->modsToKeysyms = table; 441444c061aSmrg 442444c061aSmrg table[0].mask = ShiftMask; 443444c061aSmrg table[1].mask = LockMask; 444444c061aSmrg table[2].mask = ControlMask; 445444c061aSmrg table[3].mask = Mod1Mask; 446444c061aSmrg table[4].mask = Mod2Mask; 447444c061aSmrg table[5].mask = Mod3Mask; 448444c061aSmrg table[6].mask = Mod4Mask; 449444c061aSmrg table[7].mask = Mod5Mask; 450444c061aSmrg tempKeysym = 0; 451444c061aSmrg 452444c061aSmrg modKeymap = XGetModifierMapping(dpy); 453444c061aSmrg for (i=0;i<32;i++) 454444c061aSmrg pd->isModifier[i] = 0; 455444c061aSmrg pd->mode_switch = 0; 456444c061aSmrg pd->num_lock = 0; 457444c061aSmrg for (i=0;i<8;i++) { 458444c061aSmrg table[i].idx = tempCount; 459444c061aSmrg table[i].count = 0; 460444c061aSmrg for (j=0;j<modKeymap->max_keypermod;j++) { 461444c061aSmrg keycode = modKeymap->modifiermap[i*modKeymap->max_keypermod+j]; 462444c061aSmrg if (keycode != 0) { 463444c061aSmrg pd->isModifier[keycode>>3] |= 1 << (keycode & 7); 464444c061aSmrg for (k=0; k<pd->keysyms_per_keycode;k++) { 465444c061aSmrg idx = ((keycode-pd->min_keycode)* 466444c061aSmrg pd->keysyms_per_keycode)+k; 467444c061aSmrg keysym = pd->keysyms[idx]; 468444c061aSmrg if ((keysym == XK_Mode_switch) && (i > 2)) 469444c061aSmrg pd->mode_switch |= 1 << i; 470444c061aSmrg if ((keysym == XK_Num_Lock) && (i > 2)) 471444c061aSmrg pd->num_lock |= 1 << i; 472444c061aSmrg if (keysym != 0 && keysym != tempKeysym ){ 473444c061aSmrg if (tempCount==maxCount) { 474444c061aSmrg maxCount += KeysymTableSize; 475444c061aSmrg pd->modKeysyms = (KeySym*)XtRealloc( 476444c061aSmrg (char*)pd->modKeysyms, 477444c061aSmrg (unsigned) (maxCount*sizeof(KeySym)) ); 478444c061aSmrg } 479444c061aSmrg pd->modKeysyms[tempCount++] = keysym; 480444c061aSmrg table[i].count++; 481444c061aSmrg tempKeysym = keysym; 482444c061aSmrg } 483444c061aSmrg } 484444c061aSmrg } 485444c061aSmrg } 486444c061aSmrg } 487444c061aSmrg pd->lock_meaning = NoSymbol; 488444c061aSmrg for (i = 0; i < table[1].count; i++) { 489444c061aSmrg keysym = pd->modKeysyms[table[1].idx + i]; 490444c061aSmrg if (keysym == XK_Caps_Lock) { 491444c061aSmrg pd->lock_meaning = XK_Caps_Lock; 492444c061aSmrg break; 493444c061aSmrg } else if (keysym == XK_Shift_Lock) { 494444c061aSmrg pd->lock_meaning = XK_Shift_Lock; 495444c061aSmrg } 496444c061aSmrg } 497444c061aSmrg XFreeModifiermap(modKeymap); 498444c061aSmrg} 499444c061aSmrg 500444c061aSmrgvoid XtTranslateKeycode ( 501444c061aSmrg Display *dpy, 502444c061aSmrg _XtKeyCode keycode, 503444c061aSmrg Modifiers modifiers, 504444c061aSmrg Modifiers *modifiers_return, 505444c061aSmrg KeySym *keysym_return) 506444c061aSmrg{ 507444c061aSmrg XtPerDisplay pd; 508444c061aSmrg DPY_TO_APPCON(dpy); 509444c061aSmrg 510444c061aSmrg LOCK_APP(app); 511444c061aSmrg pd = _XtGetPerDisplay(dpy); 512444c061aSmrg _InitializeKeysymTables(dpy, pd); 513444c061aSmrg (*pd->defaultKeycodeTranslator)( 514444c061aSmrg dpy,keycode,modifiers,modifiers_return,keysym_return); 515444c061aSmrg UNLOCK_APP(app); 516444c061aSmrg} 517444c061aSmrg 518444c061aSmrg/* This code should match XTranslateKey (internal, sigh) in Xlib */ 519444c061aSmrgvoid XtTranslateKey( 520444c061aSmrg register Display *dpy, 521444c061aSmrg _XtKeyCode keycode, 522444c061aSmrg Modifiers modifiers, 523444c061aSmrg Modifiers *modifiers_return, 524444c061aSmrg KeySym *keysym_return) 525444c061aSmrg{ 526444c061aSmrg#ifndef XKB 527444c061aSmrg XtPerDisplay pd; 528444c061aSmrg int per; 529444c061aSmrg register KeySym *syms; 530444c061aSmrg KeySym sym, lsym, usym; 531444c061aSmrg DPY_TO_APPCON(dpy); 532444c061aSmrg 533444c061aSmrg LOCK_APP(app); 534444c061aSmrg pd = _XtGetPerDisplay(dpy); 535444c061aSmrg *modifiers_return = (ShiftMask|LockMask) | pd->mode_switch | pd->num_lock; 536444c061aSmrg if (((int)keycode < pd->min_keycode) || ((int)keycode > pd->max_keycode)) { 537444c061aSmrg *keysym_return = NoSymbol; 538444c061aSmrg UNLOCK_APP(app); 539444c061aSmrg return; 540444c061aSmrg } 541444c061aSmrg per = pd->keysyms_per_keycode; 542444c061aSmrg syms = &pd->keysyms[(keycode - pd->min_keycode) * per]; 543444c061aSmrg while ((per > 2) && (syms[per - 1] == NoSymbol)) 544444c061aSmrg per--; 545444c061aSmrg if ((per > 2) && (modifiers & pd->mode_switch)) { 546444c061aSmrg syms += 2; 547444c061aSmrg per -= 2; 548444c061aSmrg } 549444c061aSmrg if ((modifiers & pd->num_lock) && 550444c061aSmrg (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { 551444c061aSmrg if ((modifiers & ShiftMask) || 552444c061aSmrg ((modifiers & LockMask) && (pd->lock_meaning == XK_Shift_Lock))) 553444c061aSmrg *keysym_return = syms[0]; 554444c061aSmrg else 555444c061aSmrg *keysym_return = syms[1]; 556444c061aSmrg } else if (!(modifiers & ShiftMask) && 557444c061aSmrg (!(modifiers & LockMask) || (pd->lock_meaning == NoSymbol))) { 558444c061aSmrg if ((per == 1) || (syms[1] == NoSymbol)) 559444c061aSmrg XtConvertCase(dpy, syms[0], keysym_return, &usym); 560444c061aSmrg else 561444c061aSmrg *keysym_return = syms[0]; 562444c061aSmrg } else if (!(modifiers & LockMask) || 563444c061aSmrg (pd->lock_meaning != XK_Caps_Lock)) { 564444c061aSmrg if ((per == 1) || ((usym = syms[1]) == NoSymbol)) 565444c061aSmrg XtConvertCase(dpy, syms[0], &lsym, &usym); 566444c061aSmrg *keysym_return = usym; 567444c061aSmrg } else { 568444c061aSmrg if ((per == 1) || ((sym = syms[1]) == NoSymbol)) 569444c061aSmrg sym = syms[0]; 570444c061aSmrg XtConvertCase(dpy, sym, &lsym, &usym); 571444c061aSmrg if (!(modifiers & ShiftMask) && (sym != syms[0]) && 572444c061aSmrg ((sym != usym) || (lsym == usym))) 573444c061aSmrg XtConvertCase(dpy, syms[0], &lsym, &usym); 574444c061aSmrg *keysym_return = usym; 575444c061aSmrg } 576444c061aSmrg 577444c061aSmrg if (*keysym_return == XK_VoidSymbol) 578444c061aSmrg *keysym_return = NoSymbol; 579444c061aSmrg UNLOCK_APP(app); 580444c061aSmrg#else 581444c061aSmrg XkbLookupKeySym(dpy, keycode, modifiers, modifiers_return, keysym_return); 582444c061aSmrg#endif 583444c061aSmrg} 584444c061aSmrg 585444c061aSmrgvoid XtSetKeyTranslator( 586444c061aSmrg Display *dpy, 587444c061aSmrg XtKeyProc translator) 588444c061aSmrg{ 589444c061aSmrg XtPerDisplay pd; 590444c061aSmrg DPY_TO_APPCON(dpy); 591444c061aSmrg 592444c061aSmrg LOCK_APP(app); 593444c061aSmrg pd = _XtGetPerDisplay(dpy); 594444c061aSmrg 595444c061aSmrg pd->defaultKeycodeTranslator = translator; 596444c061aSmrg FLUSHKEYCACHE(pd->tm_context); 597444c061aSmrg /* XXX should now redo grabs */ 598444c061aSmrg UNLOCK_APP(app); 599444c061aSmrg} 600444c061aSmrg 601444c061aSmrgvoid XtRegisterCaseConverter( 602444c061aSmrg Display *dpy, 603444c061aSmrg XtCaseProc proc, 604444c061aSmrg KeySym start, 605444c061aSmrg KeySym stop) 606444c061aSmrg{ 607444c061aSmrg XtPerDisplay pd; 608444c061aSmrg CaseConverterPtr ptr, prev; 609444c061aSmrg DPY_TO_APPCON(dpy); 610444c061aSmrg 611444c061aSmrg LOCK_APP(app); 612444c061aSmrg pd = _XtGetPerDisplay(dpy); 613444c061aSmrg 614444c061aSmrg ptr = (CaseConverterPtr) __XtMalloc(sizeof(CaseConverterRec)); 615444c061aSmrg ptr->start = start; 616444c061aSmrg ptr->stop = stop; 617444c061aSmrg ptr->proc = proc; 618444c061aSmrg ptr->next = pd->case_cvt; 619444c061aSmrg pd->case_cvt = ptr; 620444c061aSmrg 621444c061aSmrg /* Remove obsolete case converters from the list */ 622444c061aSmrg prev = ptr; 623444c061aSmrg for (ptr=ptr->next; ptr; ptr=prev->next) { 624444c061aSmrg if (start <= ptr->start && stop >= ptr->stop) { 625444c061aSmrg prev->next = ptr->next; 626444c061aSmrg XtFree((char *)ptr); 627444c061aSmrg } 628444c061aSmrg else prev = ptr; 629444c061aSmrg } 630444c061aSmrg FLUSHKEYCACHE(pd->tm_context); 631444c061aSmrg /* XXX should now redo grabs */ 632444c061aSmrg UNLOCK_APP(app); 633444c061aSmrg} 634444c061aSmrg 635444c061aSmrgKeySym *XtGetKeysymTable( 636444c061aSmrg Display *dpy, 637444c061aSmrg KeyCode *min_keycode_return, 638444c061aSmrg int *keysyms_per_keycode_return) 639444c061aSmrg{ 640444c061aSmrg XtPerDisplay pd; 641444c061aSmrg KeySym* retval; 642444c061aSmrg DPY_TO_APPCON(dpy); 643444c061aSmrg 644444c061aSmrg LOCK_APP(app); 645444c061aSmrg pd = _XtGetPerDisplay(dpy); 646444c061aSmrg _InitializeKeysymTables(dpy, pd); 647444c061aSmrg *min_keycode_return = pd->min_keycode; /* %%% */ 648444c061aSmrg *keysyms_per_keycode_return = pd->keysyms_per_keycode; 649444c061aSmrg retval = pd->keysyms; 650444c061aSmrg UNLOCK_APP(app); 651444c061aSmrg return retval; 652444c061aSmrg} 653444c061aSmrg 654444c061aSmrgvoid XtKeysymToKeycodeList( 655444c061aSmrg Display *dpy, 656444c061aSmrg KeySym keysym, 657444c061aSmrg KeyCode **keycodes_return, 658444c061aSmrg Cardinal *keycount_return) 659444c061aSmrg{ 660444c061aSmrg XtPerDisplay pd; 661444c061aSmrg unsigned keycode; 662444c061aSmrg int per, match; 663444c061aSmrg register KeySym *syms; 664444c061aSmrg register int i, j; 665444c061aSmrg KeySym lsym, usym; 666444c061aSmrg unsigned maxcodes = 0; 667444c061aSmrg unsigned ncodes = 0; 668444c061aSmrg KeyCode *keycodes, *codeP = NULL; 669444c061aSmrg DPY_TO_APPCON(dpy); 670444c061aSmrg 671444c061aSmrg LOCK_APP(app); 672444c061aSmrg pd = _XtGetPerDisplay(dpy); 673444c061aSmrg _InitializeKeysymTables(dpy, pd); 674444c061aSmrg keycodes = NULL; 675444c061aSmrg per = pd->keysyms_per_keycode; 676444c061aSmrg for (syms = pd->keysyms, keycode = (unsigned) pd->min_keycode; 677444c061aSmrg (int)keycode <= pd->max_keycode; 678444c061aSmrg syms += per, keycode++) { 679444c061aSmrg match = 0; 680444c061aSmrg for (j = 0; j < per; j++) { 681444c061aSmrg if (syms[j] == keysym) { 682444c061aSmrg match = 1; 683444c061aSmrg break; 684444c061aSmrg } 685444c061aSmrg } 686444c061aSmrg if (!match) 687444c061aSmrg for (i = 1; i < 5; i += 2) { 688444c061aSmrg if ((per == i) || ((per > i) && (syms[i] == NoSymbol))) { 689444c061aSmrg XtConvertCase(dpy, syms[i-1], &lsym, &usym); 690444c061aSmrg if ((lsym == keysym) || (usym == keysym)) { 691444c061aSmrg match = 1; 692444c061aSmrg break; 693444c061aSmrg } 694444c061aSmrg } 695444c061aSmrg } 696444c061aSmrg if (match) { 697444c061aSmrg if (ncodes == maxcodes) { 698444c061aSmrg KeyCode *old = keycodes; 699444c061aSmrg maxcodes += KEYCODE_ARRAY_SIZE; 700444c061aSmrg keycodes = (KeyCode*)__XtMalloc(maxcodes*sizeof(KeyCode)); 701444c061aSmrg if (ncodes) { 702444c061aSmrg (void) memmove((char *)keycodes, (char *)old, 703444c061aSmrg ncodes*sizeof(KeyCode) ); 704444c061aSmrg XtFree((char *)old); 705444c061aSmrg } 706444c061aSmrg codeP = &keycodes[ncodes]; 707444c061aSmrg } 708444c061aSmrg *codeP++ = (KeyCode) keycode; 709444c061aSmrg ncodes++; 710444c061aSmrg } 711444c061aSmrg } 712444c061aSmrg *keycodes_return = keycodes; 713444c061aSmrg *keycount_return = ncodes; 714444c061aSmrg UNLOCK_APP(app); 715444c061aSmrg} 716