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