home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / X / XKeyBind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  15.7 KB  |  581 lines

  1. /* $XConsortium: XKeyBind.c,v 11.67 92/05/19 11:23:14 converse Exp $ */
  2. /* Copyright 1985, 1987, Massachusetts Institute of Technology */
  3.  
  4. /*
  5. Permission to use, copy, modify, distribute, and sell this software and its
  6. documentation for any purpose is hereby granted without fee, provided that
  7. the above copyright notice appear in all copies and that both that
  8. copyright notice and this permission notice appear in supporting
  9. documentation, and that the name of M.I.T. not be used in advertising or
  10. publicity pertaining to distribution of the software without specific,
  11. written prior permission.  M.I.T. makes no representations about the
  12. suitability of this software for any purpose.  It is provided "as is"
  13. without express or implied warranty.
  14. */
  15.  
  16. /* Beware, here be monsters (still under construction... - JG */
  17.  
  18. #define NEED_EVENTS
  19. #include <X11/Xlibint.h>
  20. #include <X11/Xutil.h>
  21. #define XK_MISCELLANY
  22. #define XK_LATIN1
  23. #define XK_LATIN2
  24. #define XK_LATIN3
  25. #define XK_LATIN4
  26. #include <X11/keysymdef.h>
  27. #include <stdio.h>
  28.  
  29. #define AllMods (ShiftMask|LockMask|ControlMask| \
  30.          Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
  31.  
  32. static ComputeMaskFromKeytrans();
  33. static int Initialize();
  34. static void XConvertCase();
  35.  
  36. struct _XKeytrans {
  37.     struct _XKeytrans *next;/* next on list */
  38.     char *string;        /* string to return when the time comes */
  39.     int len;        /* length of string (since NULL is legit)*/
  40.     KeySym key;        /* keysym rebound */
  41.     unsigned int state;    /* modifier state */
  42.     KeySym *modifiers;    /* modifier keysyms you want */
  43.     int mlen;        /* length of modifier list */
  44. };
  45.  
  46. static KeySym
  47. KeyCodetoKeySym(dpy, keycode, col)
  48.     register Display *dpy;
  49.     KeyCode keycode;
  50.     int col;
  51. {
  52.     register int per = dpy->keysyms_per_keycode;
  53.     register KeySym *syms;
  54.     KeySym lsym, usym;
  55.  
  56.     if ((col < 0) || ((col >= per) && (col > 3)) ||
  57.     ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
  58.       return NoSymbol;
  59.  
  60.     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
  61.     if (col < 4) {
  62.     if (col > 1) {
  63.         while ((per > 2) && (syms[per - 1] == NoSymbol))
  64.         per--;
  65.         if (per < 3)
  66.         col -= 2;
  67.     }
  68.     if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
  69.         XConvertCase(dpy, syms[col&~1], &lsym, &usym);
  70.         if (!(col & 1))
  71.         return lsym;
  72.         else if (usym == lsym)
  73.         return NoSymbol;
  74.         else
  75.         return usym;
  76.     }
  77.     }
  78.     return syms[col];
  79. }
  80.  
  81. #if NeedFunctionPrototypes
  82. KeySym
  83. XKeycodeToKeysym(Display *dpy,
  84. #if NeedWidePrototypes
  85.          unsigned int kc,
  86. #else
  87.          KeyCode kc,
  88. #endif
  89.          int col)
  90. #else
  91. KeySym
  92. XKeycodeToKeysym(dpy, kc, col)
  93.     Display *dpy;
  94.     KeyCode kc;
  95.     int col;
  96. #endif
  97. {
  98.     if ((! dpy->keysyms) && (! Initialize(dpy)))
  99.     return NoSymbol;
  100.     return KeyCodetoKeySym(dpy, kc, col);
  101. }
  102.  
  103. KeyCode
  104. XKeysymToKeycode(dpy, ks)
  105.     Display *dpy;
  106.     KeySym ks;
  107. {
  108.     register int i, j;
  109.  
  110.     if ((! dpy->keysyms) && (! Initialize(dpy)))
  111.     return (KeyCode) 0;
  112.     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
  113.     for (i = dpy->min_keycode; i <= dpy->max_keycode; i++) {
  114.         if (KeyCodetoKeySym(dpy, (KeyCode) i, j) == ks)
  115.         return i;
  116.     }
  117.     }
  118.     return 0;
  119. }
  120.  
  121. KeySym
  122. XLookupKeysym(event, col)
  123.     register XKeyEvent *event;
  124.     int col;
  125. {
  126.     if ((! event->display->keysyms) && (! Initialize(event->display)))
  127.     return NoSymbol;
  128.     return KeyCodetoKeySym(event->display, event->keycode, col);
  129. }
  130.  
  131. static int
  132. InitModMap(dpy)
  133.     Display *dpy;
  134. {
  135.     register XModifierKeymap *map;
  136.     register int i, j, n;
  137.     KeySym sym;
  138.     register struct _XKeytrans *p;
  139.  
  140.     if (! (dpy->modifiermap = map = XGetModifierMapping(dpy)))
  141.     return 0;
  142.     dpy->free_funcs->modifiermap = XFreeModifiermap;
  143.     if ((! dpy->keysyms) && (! Initialize(dpy)))
  144.     return 0;
  145.     LockDisplay(dpy);
  146.     /* If any Lock key contains Caps_Lock, then interpret as Caps_Lock,
  147.      * else if any contains Shift_Lock, then interpret as Shift_Lock,
  148.      * else ignore Lock altogether.
  149.      */
  150.     dpy->lock_meaning = NoSymbol;
  151.     /* Lock modifiers are in the second row of the matrix */
  152.     n = 2 * map->max_keypermod;
  153.     for (i = map->max_keypermod; i < n; i++) {
  154.     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
  155.         sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
  156.         if (sym == XK_Caps_Lock) {
  157.         dpy->lock_meaning = XK_Caps_Lock;
  158.         break;
  159.         } else if (sym == XK_Shift_Lock) {
  160.         dpy->lock_meaning = XK_Shift_Lock;
  161.         }
  162.     }
  163.     }
  164.     /* Now find any Mod<n> modifier acting as the Group modifier */
  165.     dpy->mode_switch = 0;
  166.     n *= 4;
  167.     for (i = 3*map->max_keypermod; i < n; i++) {
  168.     for (j = 0; j < dpy->keysyms_per_keycode; j++) {
  169.         sym = KeyCodetoKeySym(dpy, map->modifiermap[i], j);
  170.         if (sym == XK_Mode_switch)
  171.         dpy->mode_switch |= 1 << (i / map->max_keypermod);
  172.     }
  173.     }
  174.     for (p = dpy->key_bindings; p; p = p->next)
  175.     ComputeMaskFromKeytrans(dpy, p);
  176.     UnlockDisplay(dpy);
  177.     return 1;
  178. }
  179.  
  180. XRefreshKeyboardMapping(event)
  181.     register XMappingEvent *event;
  182. {
  183.  
  184.     if(event->request == MappingKeyboard) {
  185.     /* XXX should really only refresh what is necessary
  186.      * for now, make initialize test fail
  187.      */
  188.     LockDisplay(event->display);
  189.     if (event->display->keysyms) {
  190.          Xfree ((char *)event->display->keysyms);
  191.          event->display->keysyms = NULL;
  192.     }
  193.     UnlockDisplay(event->display);
  194.     }
  195.     if(event->request == MappingModifier) {
  196.     LockDisplay(event->display);
  197.     if (event->display->modifiermap) {
  198.         XFreeModifiermap(event->display->modifiermap);
  199.         event->display->modifiermap = NULL;
  200.     }
  201.     UnlockDisplay(event->display);
  202.     /* go ahead and get it now, since initialize test may not fail */
  203.     (void) InitModMap(event->display);
  204.     }
  205. }
  206.  
  207. static int
  208. Initialize(dpy)
  209.     Display *dpy;
  210. {
  211.     int per, n;
  212.     KeySym *keysyms;
  213.  
  214.     /* 
  215.      * lets go get the keysyms from the server.
  216.      */
  217.     if (!dpy->keysyms) {
  218.     n = dpy->max_keycode - dpy->min_keycode + 1;
  219.     keysyms = XGetKeyboardMapping (dpy, (KeyCode) dpy->min_keycode,
  220.                        n, &per);
  221.     /* keysyms may be NULL */
  222.     if (! keysyms) return 0;
  223.  
  224.     LockDisplay(dpy);
  225.     dpy->keysyms = keysyms;
  226.     dpy->keysyms_per_keycode = per;
  227.     UnlockDisplay(dpy);
  228.     }
  229.     if (!dpy->modifiermap)
  230.         return InitModMap(dpy);
  231.     return 1;
  232. }
  233.  
  234. /*ARGSUSED*/
  235. static void
  236. XConvertCase(dpy, sym, lower, upper)
  237.     Display *dpy;
  238.     register KeySym sym;
  239.     KeySym *lower;
  240.     KeySym *upper;
  241. {
  242.     *lower = sym;
  243.     *upper = sym;
  244.     switch(sym >> 8) {
  245.     case 0:
  246.     if ((sym >= XK_A) && (sym <= XK_Z))
  247.         *lower += (XK_a - XK_A);
  248.     else if ((sym >= XK_a) && (sym <= XK_z))
  249.         *upper -= (XK_a - XK_A);
  250.     else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
  251.         *lower += (XK_agrave - XK_Agrave);
  252.     else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
  253.         *upper -= (XK_agrave - XK_Agrave);
  254.     else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
  255.         *lower += (XK_oslash - XK_Ooblique);
  256.     else if ((sym >= XK_oslash) && (sym <= XK_thorn))
  257.         *upper -= (XK_oslash - XK_Ooblique);
  258.     break;
  259. #ifdef XK_LATIN2
  260.     case 1:
  261.     /* Assume the KeySym is a legal value (ignore discontinuities) */
  262.     if (sym == XK_Aogonek)
  263.         *lower = XK_aogonek;
  264.     else if (sym >= XK_Lstroke && sym <= XK_Sacute)
  265.         *lower += (XK_lstroke - XK_Lstroke);
  266.     else if (sym >= XK_Scaron && sym <= XK_Zacute)
  267.         *lower += (XK_scaron - XK_Scaron);
  268.     else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
  269.         *lower += (XK_zcaron - XK_Zcaron);
  270.     else if (sym == XK_aogonek)
  271.         *upper = XK_Aogonek;
  272.     else if (sym >= XK_lstroke && sym <= XK_sacute)
  273.         *upper -= (XK_lstroke - XK_Lstroke);
  274.     else if (sym >= XK_scaron && sym <= XK_zacute)
  275.         *upper -= (XK_scaron - XK_Scaron);
  276.     else if (sym >= XK_zcaron && sym <= XK_zabovedot)
  277.         *upper -= (XK_zcaron - XK_Zcaron);
  278.     else if (sym >= XK_Racute && sym <= XK_Tcedilla)
  279.         *lower += (XK_racute - XK_Racute);
  280.     else if (sym >= XK_racute && sym <= XK_tcedilla)
  281.         *upper -= (XK_racute - XK_Racute);
  282.     break;
  283. #endif
  284. #ifdef XK_LATIN3
  285.     case 2:
  286.     /* Assume the KeySym is a legal value (ignore discontinuities) */
  287.     if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
  288.         *lower += (XK_hstroke - XK_Hstroke);
  289.     else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
  290.         *lower += (XK_gbreve - XK_Gbreve);
  291.     else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
  292.         *upper -= (XK_hstroke - XK_Hstroke);
  293.     else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
  294.         *upper -= (XK_gbreve - XK_Gbreve);
  295.     else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
  296.         *lower += (XK_cabovedot - XK_Cabovedot);
  297.     else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
  298.         *upper -= (XK_cabovedot - XK_Cabovedot);
  299.     break;
  300. #endif
  301. #ifdef XK_LATIN4
  302.     case 3:
  303.     /* Assume the KeySym is a legal value (ignore discontinuities) */
  304.     if (sym >= XK_Rcedilla && sym <= XK_Tslash)
  305.         *lower += (XK_rcedilla - XK_Rcedilla);
  306.     else if (sym >= XK_rcedilla && sym <= XK_tslash)
  307.         *upper -= (XK_rcedilla - XK_Rcedilla);
  308.     else if (sym == XK_ENG)
  309.         *lower = XK_eng;
  310.     else if (sym == XK_eng)
  311.         *upper = XK_ENG;
  312.     else if (sym >= XK_Amacron && sym <= XK_Umacron)
  313.         *lower += (XK_amacron - XK_Amacron);
  314.     else if (sym >= XK_amacron && sym <= XK_umacron)
  315.         *upper -= (XK_amacron - XK_Amacron);
  316.     break;
  317. #endif
  318.     }
  319. }
  320.  
  321. static int
  322. XTranslateKey(dpy, keycode, modifiers, modifiers_return, keysym_return)
  323.     register Display *dpy;
  324.     KeyCode keycode;
  325.     register unsigned int modifiers;
  326.     unsigned int *modifiers_return;
  327.     KeySym *keysym_return;
  328. {
  329.     int per;
  330.     register KeySym *syms;
  331.     KeySym sym, lsym, usym;
  332.  
  333.     if ((! dpy->keysyms) && (! Initialize(dpy)))
  334.     return 0;
  335.     *modifiers_return = (ShiftMask|LockMask) | dpy->mode_switch;
  336.     if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
  337.     {
  338.     *keysym_return = NoSymbol;
  339.     return 1;
  340.     }
  341.     per = dpy->keysyms_per_keycode;
  342.     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
  343.     while ((per > 2) && (syms[per - 1] == NoSymbol))
  344.     per--;
  345.     if ((per > 2) && (modifiers & dpy->mode_switch)) {
  346.     syms += 2;
  347.     per -= 2;
  348.     }
  349.     if (!(modifiers & ShiftMask) &&
  350.     (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
  351.     if ((per == 1) || (syms[1] == NoSymbol))
  352.         XConvertCase(dpy, syms[0], keysym_return, &usym);
  353.     else
  354.         *keysym_return = syms[0];
  355.     } else if (!(modifiers & LockMask) ||
  356.            (dpy->lock_meaning != XK_Caps_Lock)) {
  357.     if ((per == 1) || ((usym = syms[1]) == NoSymbol))
  358.         XConvertCase(dpy, syms[0], &lsym, &usym);
  359.     *keysym_return = usym;
  360.     } else {
  361.     if ((per == 1) || ((sym = syms[1]) == NoSymbol))
  362.         sym = syms[0];
  363.     XConvertCase(dpy, sym, &lsym, &usym);
  364.     if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
  365.         ((sym != usym) || (lsym == usym)))
  366.         XConvertCase(dpy, syms[0], &lsym, &usym);
  367.     *keysym_return = usym;
  368.     }
  369.     if (*keysym_return == XK_VoidSymbol)
  370.     *keysym_return = NoSymbol;
  371.     return 1;
  372. }
  373.  
  374. static int
  375. XTranslateKeySym(dpy, symbol, modifiers, buffer, nbytes)
  376.     Display *dpy;
  377.     register KeySym symbol;
  378.     unsigned int modifiers;
  379.     char *buffer;
  380.     int nbytes;
  381. {
  382.     register struct _XKeytrans *p; 
  383.     int length;
  384.     unsigned long hiBytes;
  385.     register unsigned char c;
  386.  
  387.     if (!symbol)
  388.     return 0;
  389.     /* see if symbol rebound, if so, return that string. */
  390.     for (p = dpy->key_bindings; p; p = p->next) {
  391.     if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
  392.         length = p->len;
  393.         if (length > nbytes) length = nbytes;
  394.         bcopy (p->string, buffer, length);
  395.         return length;
  396.     }
  397.     }
  398.     /* try to convert to Latin-1, handling control */
  399.     hiBytes = symbol >> 8;
  400.     if (!(nbytes &&
  401.       ((hiBytes == 0) ||
  402.        ((hiBytes == 0xFF) &&
  403.         (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
  404.          (symbol == XK_Return) ||
  405.          (symbol == XK_Escape) ||
  406.          (symbol == XK_KP_Space) ||
  407.          (symbol == XK_KP_Tab) ||
  408.          (symbol == XK_KP_Enter) ||
  409.          ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
  410.          (symbol == XK_KP_Equal) ||
  411.          (symbol == XK_Delete))))))
  412.     return 0;
  413.  
  414.     /* if X keysym, convert to ascii by grabbing low 7 bits */
  415.     if (symbol == XK_KP_Space)
  416.     c = XK_space & 0x7F; /* patch encoding botch */
  417.     else if (symbol == XK_hyphen)
  418.     c = XK_minus & 0xFF; /* map to equiv character */
  419.     else if (hiBytes == 0xFF)
  420.     c = symbol & 0x7F;
  421.     else
  422.     c = symbol & 0xFF;
  423.     /* only apply Control key if it makes sense, else ignore it */
  424.     if (modifiers & ControlMask) {
  425.     if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
  426.     else if (c == '2') c = '\000';
  427.     else if (c >= '3' && c <= '7') c -= ('3' - '\033');
  428.     else if (c == '8') c = '\177';
  429.     else if (c == '/') c = '_' & 0x1F;
  430.     }
  431.     buffer[0] = c;
  432.     return 1;
  433. }
  434.   
  435. /*ARGSUSED*/
  436. int
  437. XLookupString (event, buffer, nbytes, keysym, status)
  438.     register XKeyEvent *event;
  439.     char *buffer;    /* buffer */
  440.     int nbytes;    /* space in buffer for characters */
  441.     KeySym *keysym;
  442.     XComposeStatus *status;    /* not implemented */
  443. {
  444.     unsigned int modifiers;
  445.     KeySym symbol;
  446.  
  447.     if (! XTranslateKey(event->display, event->keycode, event->state,
  448.           &modifiers, &symbol))
  449.     return 0;
  450.  
  451.     if (keysym)
  452.     *keysym = symbol;
  453.     /* arguable whether to use (event->state & ~modifiers) here */
  454.     return XTranslateKeySym(event->display, symbol, event->state,
  455.                 buffer, nbytes);
  456. }
  457.  
  458. static void
  459. _XFreeKeyBindings (dpy)
  460.     Display *dpy;
  461. {
  462.     register struct _XKeytrans *p, *np;
  463.  
  464.     for (p = dpy->key_bindings; p; p = np) {
  465.     np = p->next;
  466.     Xfree(p->string);
  467.     Xfree((char *)p->modifiers);
  468.     Xfree((char *)p);
  469.     }   
  470. }
  471.  
  472. #if NeedFunctionPrototypes
  473. XRebindKeysym (
  474.     Display *dpy,
  475.     KeySym keysym,
  476.     KeySym *mlist,
  477.     int nm,        /* number of modifiers in mlist */
  478.     _Xconst unsigned char *str,
  479.     int nbytes)
  480. #else
  481. XRebindKeysym (dpy, keysym, mlist, nm, str, nbytes)
  482.     Display *dpy;
  483.     KeySym keysym;
  484.     KeySym *mlist;
  485.     int nm;        /* number of modifiers in mlist */
  486.     unsigned char *str;
  487.     int nbytes;
  488. #endif
  489. {
  490.     register struct _XKeytrans *tmp, *p;
  491.     int nb;
  492.  
  493.     if ((! dpy->keysyms) && (! Initialize(dpy)))
  494.     return;
  495.     LockDisplay(dpy);
  496.     tmp = dpy->key_bindings;
  497.     nb = sizeof(KeySym) * nm;
  498.  
  499.     if ((! (p = (struct _XKeytrans *) Xmalloc( sizeof(struct _XKeytrans)))) ||
  500.     ((! (p->string = (char *) Xmalloc( (unsigned) nbytes))) && 
  501.      (nbytes > 0)) ||
  502.     ((! (p->modifiers = (KeySym *) Xmalloc( (unsigned) nb))) &&
  503.      (nb > 0))) {
  504.     if (p) {
  505.         if (p->string) Xfree(p->string);
  506.         if (p->modifiers) Xfree((char *) p->modifiers);
  507.         Xfree((char *) p);
  508.     }
  509.     UnlockDisplay(dpy);
  510.     return;
  511.     }
  512.  
  513.     dpy->key_bindings = p;
  514.     dpy->free_funcs->key_bindings = _XFreeKeyBindings;
  515.     p->next = tmp;    /* chain onto list */
  516.     bcopy ((char *) str, p->string, nbytes);
  517.     p->len = nbytes;
  518.     bcopy ((char *) mlist, (char *) p->modifiers, nb);
  519.     p->key = keysym;
  520.     p->mlen = nm;
  521.     ComputeMaskFromKeytrans(dpy, p);
  522.     UnlockDisplay(dpy);
  523.     return;
  524. }
  525.  
  526. /*
  527.  * given a KeySym, returns the first keycode containing it, if any.
  528.  */
  529. static CARD8
  530. FindKeyCode(dpy, code)
  531.     register Display *dpy;
  532.     register KeySym code;
  533. {
  534.  
  535.     register KeySym *kmax = dpy->keysyms + 
  536.     (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
  537.     register KeySym *k = dpy->keysyms;
  538.     while (k < kmax) {
  539.     if (*k == code)
  540.         return (((k - dpy->keysyms) / dpy->keysyms_per_keycode) +
  541.             dpy->min_keycode);
  542.     k += 1;
  543.     }
  544.     return 0;
  545. }
  546.  
  547.     
  548. /*
  549.  * given a list of modifiers, computes the mask necessary for later matching.
  550.  * This routine must lookup the key in the Keymap and then search to see
  551.  * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
  552.  * can't map some keysym to a modifier.
  553.  */
  554. static
  555. ComputeMaskFromKeytrans(dpy, p)
  556.     Display *dpy;
  557.     register struct _XKeytrans *p;
  558. {
  559.     register int i;
  560.     register CARD8 code;
  561.     register XModifierKeymap *m = dpy->modifiermap;
  562.  
  563.     p->state = AnyModifier;
  564.     for (i = 0; i < p->mlen; i++) {
  565.     /* if not found, then not on current keyboard */
  566.     if ((code = FindKeyCode(dpy, p->modifiers[i])) == 0)
  567.         return;
  568.     /* code is now the keycode for the modifier you want */
  569.     {
  570.         register int j = m->max_keypermod<<3;
  571.  
  572.         while ((--j >= 0) && (code != m->modifiermap[j]))
  573.         ;
  574.         if (j < 0)
  575.         return;
  576.         p->state |= (1<<(j/m->max_keypermod));
  577.     }
  578.     }
  579.     p->state &= AllMods;
  580. }
  581.