tkMacKeyboard.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkMacKeyboard.c --
  3.  *
  4.  * Routines to support keyboard events on the Macintosh.
  5.  *
  6.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * RCS: @(#) $Id: tkMacKeyboard.c,v 1.8 2002/02/08 02:57:11 dgp Exp $
  12.  */
  13. #include "tkInt.h"
  14. #include "Xlib.h"
  15. #include "keysym.h"
  16. #include <Events.h>
  17. #include <Script.h>
  18. typedef struct {
  19.     short keycode; /* Macintosh keycode */
  20.     KeySym keysym; /* X windows Keysym */
  21. } KeyInfo;
  22. static KeyInfo keyArray[] = {
  23.     {0x4C, XK_Return},
  24.     {0x24, XK_Return},
  25.     {0x33, XK_BackSpace},
  26.     {0x75, XK_Delete},
  27.     {0x30, XK_Tab},
  28.     {0x74, XK_Page_Up},
  29.     {0x79, XK_Page_Down},
  30.     {0x73, XK_Home},
  31.     {0x77, XK_End},
  32.     {0x7B, XK_Left},
  33.     {0x7C, XK_Right},
  34.     {0x7E, XK_Up},
  35.     {0x7D, XK_Down},
  36.     {0x72, XK_Help},
  37.     {0x35, XK_Escape},
  38.     {0x47, XK_Clear},
  39.     {0, 0}
  40. };
  41. static KeyInfo vituralkeyArray[] = {
  42.     {122, XK_F1},
  43.     {120, XK_F2},
  44.     {99, XK_F3},
  45.     {118, XK_F4},
  46.     {96, XK_F5},
  47.     {97, XK_F6},
  48.     {98, XK_F7},
  49.     {100, XK_F8},
  50.     {101, XK_F9},
  51.     {109, XK_F10},
  52.     {103, XK_F11},
  53.     {111, XK_F12},
  54.     {105, XK_F13},
  55.     {107, XK_F14},
  56.     {113, XK_F15},
  57.     {0, 0}
  58. };
  59. static int initialized = 0;
  60. static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */
  61. static Tcl_HashTable vkeyTable; /* vituralkeyArray hashed by virtual
  62.    keycode value. */
  63. static Ptr KCHRPtr; /* Pointer to 'KCHR' resource. */
  64. /*
  65.  * Prototypes for static functions used in this file.
  66.  */
  67. static void InitKeyMaps _ANSI_ARGS_((void));
  68. /*
  69.  *----------------------------------------------------------------------
  70.  *
  71.  * InitKeyMaps --
  72.  *
  73.  * Creates hash tables used by some of the functions in this file.
  74.  *
  75.  * Results:
  76.  * None.
  77.  *
  78.  * Side effects:
  79.  * Allocates memory & creates some hash tables.
  80.  *
  81.  *----------------------------------------------------------------------
  82.  */
  83. static void
  84. InitKeyMaps()
  85. {
  86.     register Tcl_HashEntry *hPtr;
  87.     register KeyInfo *kPtr;
  88.     int dummy;
  89.     Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
  90.     for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
  91. hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
  92. &dummy);
  93. Tcl_SetHashValue(hPtr, kPtr->keysym);
  94.     }
  95.     Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
  96.     for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) {
  97. hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
  98. &dummy);
  99. Tcl_SetHashValue(hPtr, kPtr->keysym);
  100.     }
  101.     KCHRPtr = (Ptr) GetScriptManagerVariable(smKCHRCache);
  102.     initialized = 1;
  103. }
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * XKeycodeToKeysym --
  108.  *
  109.  * Translate from a system-dependent keycode to a
  110.  * system-independent keysym.
  111.  *
  112.  * Results:
  113.  * Returns the translated keysym, or NoSymbol on failure.
  114.  *
  115.  * Side effects:
  116.  * None.
  117.  *
  118.  *----------------------------------------------------------------------
  119.  */
  120. KeySym 
  121. XKeycodeToKeysym(
  122.     Display* display,
  123.     KeyCode keycode,
  124.     int index)
  125. {
  126.     register Tcl_HashEntry *hPtr;
  127.     int c;
  128.     char virtualKey;
  129.     int newKeycode;
  130.     unsigned long dummy, newChar;
  131.     if (!initialized) {
  132. InitKeyMaps();
  133.     }
  134.     virtualKey = (char) (keycode >> 16);    
  135.     c = (keycode) & 0xffff;
  136.     if (c > 255) {
  137.         return NoSymbol;
  138.     }
  139.     /*
  140.      * When determining what keysym to produce we firt check to see if
  141.      * the key is a function key.  We then check to see if the character
  142.      * is another non-printing key.  Finally, we return the key syms
  143.      * for all ASCI chars.
  144.      */
  145.     if (c == 0x10) {
  146. hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
  147. if (hPtr != NULL) {
  148.     return (KeySym) Tcl_GetHashValue(hPtr);
  149. }
  150.     }
  151.     hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
  152.     if (hPtr != NULL) {
  153. return (KeySym) Tcl_GetHashValue(hPtr);
  154.     }
  155.     /* 
  156.      * Recompute the character based on the Shift key only.
  157.      * TODO: The index may also specify the NUM_LOCK.
  158.      */
  159.     newKeycode = virtualKey;
  160.     if (index & 0x01) {
  161. newKeycode += 0x0200;
  162.     }
  163.     dummy = 0;
  164.     newChar = KeyTranslate(KCHRPtr, (short) newKeycode, &dummy);
  165.     c = newChar & charCodeMask;
  166.     
  167.     if (c >= XK_space && c < XK_asciitilde) {
  168. return c;
  169.     }
  170.     return NoSymbol; 
  171. }
  172. /*
  173.  *----------------------------------------------------------------------
  174.  *
  175.  * TkpGetString --
  176.  *
  177.  * Retrieve the string equivalent for the given keyboard event.
  178.  *
  179.  * Results:
  180.  * Returns the UTF string.
  181.  *
  182.  * Side effects:
  183.  * None.
  184.  *
  185.  *----------------------------------------------------------------------
  186.  */
  187. char *
  188. TkpGetString(
  189.     TkWindow *winPtr, /* Window where event occurred:  needed to
  190.  * get input context. */
  191.     XEvent *eventPtr, /* X keyboard event. */
  192.     Tcl_DString *dsPtr) /* Uninitialized or empty string to hold
  193.  * result. */
  194. {
  195.     register Tcl_HashEntry *hPtr;
  196.     char string[3];
  197.     char virtualKey;
  198.     int c, len;
  199.     if (!initialized) {
  200. InitKeyMaps();
  201.     }
  202.     
  203.     Tcl_DStringInit(dsPtr);
  204.     
  205.     virtualKey = (char) (eventPtr->xkey.keycode >> 16);    
  206.     c = (eventPtr->xkey.keycode) & 0xffff;
  207.     
  208.     if (c < 256) {
  209.         string[0] = (char) c;
  210.         len = 1;
  211.     } else {
  212.         string[0] = (char) (c >> 8);
  213.         string[1] = (char) c;
  214.         len = 2;
  215.     }
  216.     
  217.     /*
  218.      * Just return NULL if the character is a function key or another
  219.      * non-printing key.
  220.      */
  221.     if (c == 0x10) {
  222. len = 0;
  223.     } else {
  224. hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
  225. if (hPtr != NULL) {
  226.     len = 0;
  227. }
  228.     }
  229.     return Tcl_ExternalToUtfDString(NULL, string, len, dsPtr);
  230. }
  231. /*
  232.  *----------------------------------------------------------------------
  233.  *
  234.  * XGetModifierMapping --
  235.  *
  236.  * Fetch the current keycodes used as modifiers.
  237.  *
  238.  * Results:
  239.  * Returns a new modifier map.
  240.  *
  241.  * Side effects:
  242.  * Allocates a new modifier map data structure.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246. XModifierKeymap * 
  247. XGetModifierMapping(
  248.     Display* display)
  249.     XModifierKeymap * modmap;
  250.     modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
  251.     modmap->max_keypermod = 0;
  252.     modmap->modifiermap = NULL;
  253.     return modmap;
  254. }
  255. /*
  256.  *----------------------------------------------------------------------
  257.  *
  258.  * XFreeModifiermap --
  259.  *
  260.  * Deallocate a modifier map that was created by
  261.  * XGetModifierMapping.
  262.  *
  263.  * Results:
  264.  * None.
  265.  *
  266.  * Side effects:
  267.  * Frees the datastructure referenced by modmap.
  268.  *
  269.  *----------------------------------------------------------------------
  270.  */
  271. void 
  272. XFreeModifiermap(
  273.     XModifierKeymap *modmap)
  274. {
  275.     if (modmap->modifiermap != NULL) {
  276. ckfree((char *) modmap->modifiermap);
  277.     }
  278.     ckfree((char *) modmap);
  279. }
  280. /*
  281.  *----------------------------------------------------------------------
  282.  *
  283.  * XKeysymToString, XStringToKeysym --
  284.  *
  285.  * These X window functions map Keysyms to strings & strings to 
  286.  *  keysyms.  However, Tk already does this for the most common keysyms.  
  287.  *   Therefor, these functions only need to support keysyms that will be 
  288.  *   specific to the Macintosh.  Currently, there are none.
  289.  *
  290.  * Results:
  291.  * None.
  292.  *
  293.  * Side effects:
  294.  * None.
  295.  *
  296.  *----------------------------------------------------------------------
  297.  */
  298. char * 
  299. XKeysymToString(
  300.     KeySym keysym)
  301. {
  302.     return NULL; 
  303. }
  304. KeySym 
  305. XStringToKeysym(
  306.     const char* string)
  307.     return NoSymbol;
  308. }
  309. /*
  310.  *----------------------------------------------------------------------
  311.  *
  312.  * XKeysymToKeycode --
  313.  *
  314.  * The function XKeysymToKeycode is only used by tkTest.c and
  315.  * currently only implementes the support for keys used in the
  316.  * Tk test suite.
  317.  *      FIXME - This is no longer true.  This function is now used in
  318.  *      "event generate" so we really should make it work.
  319.  *
  320.  * Results:
  321.  * None.
  322.  *
  323.  * Side effects:
  324.  * None.
  325.  *
  326.  *----------------------------------------------------------------------
  327.  */
  328. KeyCode
  329. XKeysymToKeycode(
  330.     Display* display,
  331.     KeySym keysym)
  332. {
  333.     KeyCode keycode = 0;
  334.     char virtualKeyCode = 0;
  335.     
  336.     if ((keysym >= XK_space) && (XK_asciitilde)) {
  337.         if (keysym == 'a') {
  338.             virtualKeyCode = 0x00;
  339.         } else if (keysym == 'b' || keysym == 'B') {
  340.             virtualKeyCode = 0x0B;
  341.         } else if (keysym == 'c') {
  342.             virtualKeyCode = 0x08;
  343.         } else if (keysym == 'x' || keysym == 'X') {
  344.             virtualKeyCode = 0x07;
  345.         } else if (keysym == 'z') {
  346.             virtualKeyCode = 0x06;
  347.         } else if (keysym == ' ') {
  348.             virtualKeyCode = 0x31;
  349.         } else if (keysym == XK_Return) {
  350.             virtualKeyCode = 0x24;
  351.             keysym = 'r';
  352.         }
  353. keycode = keysym + (virtualKeyCode <<16);
  354.     }
  355.     return keycode;
  356. }
  357. /*
  358.  * When mapping from a keysym to a keycode, need
  359.  * information about the modifier state that should be used
  360.  * so that when they call XKeycodeToKeysym taking into
  361.  * account the xkey.state, they will get back the original
  362.  * keysym.
  363.  */
  364. void
  365. TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
  366.     Tk_Window tkwin;
  367.     KeySym keySym;
  368.     XEvent *eventPtr;
  369. {
  370.     Display *display;
  371.     int state;
  372.     KeyCode keycode;
  373.     
  374.     display = Tk_Display(tkwin);
  375.     
  376.     if (keySym == NoSymbol) {
  377. keycode = 0;
  378.     } else {
  379. keycode = XKeysymToKeycode(display, keySym);
  380.     }
  381.     if (keycode != 0) {
  382. for (state = 0; state < 4; state++) {
  383.     if (XKeycodeToKeysym(display, keycode, state) == keySym) {
  384. if (state & 1) {
  385.     eventPtr->xkey.state |= ShiftMask;
  386. }
  387. if (state & 2) {
  388.     TkDisplay *dispPtr;
  389.     dispPtr = ((TkWindow *) tkwin)->dispPtr; 
  390.     eventPtr->xkey.state |= dispPtr->modeModMask;
  391. }
  392. break;
  393.     }
  394. }
  395.     }
  396.     eventPtr->xkey.keycode = keycode;
  397. }
  398. /*
  399.  *----------------------------------------------------------------------
  400.  *
  401.  * TkpGetKeySym --
  402.  *
  403.  * Given an X KeyPress or KeyRelease event, map the
  404.  * keycode in the event into a KeySym.
  405.  *
  406.  * Results:
  407.  * The return value is the KeySym corresponding to
  408.  * eventPtr, or NoSymbol if no matching Keysym could be
  409.  * found.
  410.  *
  411.  * Side effects:
  412.  * In the first call for a given display, keycode-to-
  413.  * KeySym maps get loaded.
  414.  *
  415.  *----------------------------------------------------------------------
  416.  */
  417. KeySym
  418. TkpGetKeySym(dispPtr, eventPtr)
  419.     TkDisplay *dispPtr; /* Display in which to
  420.  * map keycode. */
  421.     XEvent *eventPtr; /* Description of X event. */
  422. {
  423.     KeySym sym;
  424.     int index;
  425.     /*
  426.      * Refresh the mapping information if it's stale
  427.      */
  428.     if (dispPtr->bindInfoStale) {
  429. TkpInitKeymapInfo(dispPtr);
  430.     }
  431.     /*
  432.      * Figure out which of the four slots in the keymap vector to
  433.      * use for this key.  Refer to Xlib documentation for more info
  434.      * on how this computation works.
  435.      */
  436.     index = 0;
  437.     if (eventPtr->xkey.state & dispPtr->modeModMask) {
  438. index = 2;
  439.     }
  440.     if ((eventPtr->xkey.state & ShiftMask)
  441.     || ((dispPtr->lockUsage != LU_IGNORE)
  442.     && (eventPtr->xkey.state & LockMask))) {
  443. index += 1;
  444.     }
  445.     sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
  446.     /*
  447.      * Special handling:  if the key was shifted because of Lock, but
  448.      * lock is only caps lock, not shift lock, and the shifted keysym
  449.      * isn't upper-case alphabetic, then switch back to the unshifted
  450.      * keysym.
  451.      */
  452.     if ((index & 1) && !(eventPtr->xkey.state & ShiftMask)
  453.     && (dispPtr->lockUsage == LU_CAPS)) {
  454. if (!(((sym >= XK_A) && (sym <= XK_Z))
  455. || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
  456. || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
  457.     index &= ~1;
  458.     sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
  459.     index);
  460. }
  461.     }
  462.     /*
  463.      * Another bit of special handling:  if this is a shifted key and there
  464.      * is no keysym defined, then use the keysym for the unshifted key.
  465.      */
  466.     if ((index & 1) && (sym == NoSymbol)) {
  467. sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
  468. index & ~1);
  469.     }
  470.     return sym;
  471. }
  472. /*
  473.  *--------------------------------------------------------------
  474.  *
  475.  * TkpInitKeymapInfo --
  476.  *
  477.  * This procedure is invoked to scan keymap information
  478.  * to recompute stuff that's important for binding, such
  479.  * as the modifier key (if any) that corresponds to "mode
  480.  * switch".
  481.  *
  482.  * Results:
  483.  * None.
  484.  *
  485.  * Side effects:
  486.  * Keymap-related information in dispPtr is updated.
  487.  *
  488.  *--------------------------------------------------------------
  489.  */
  490. void
  491. TkpInitKeymapInfo(dispPtr)
  492.     TkDisplay *dispPtr; /* Display for which to recompute keymap
  493.  * information. */
  494. {
  495.     XModifierKeymap *modMapPtr;
  496.     KeyCode *codePtr;
  497.     KeySym keysym;
  498.     int count, i, j, max, arraySize;
  499. #define KEYCODE_ARRAY_SIZE 20
  500.     dispPtr->bindInfoStale = 0;
  501.     modMapPtr = XGetModifierMapping(dispPtr->display);
  502.     /*
  503.      * Check the keycodes associated with the Lock modifier.  If
  504.      * any of them is associated with the XK_Shift_Lock modifier,
  505.      * then Lock has to be interpreted as Shift Lock, not Caps Lock.
  506.      */
  507.     dispPtr->lockUsage = LU_IGNORE;
  508.     codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
  509.     for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
  510. if (*codePtr == 0) {
  511.     continue;
  512. }
  513. keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
  514. if (keysym == XK_Shift_Lock) {
  515.     dispPtr->lockUsage = LU_SHIFT;
  516.     break;
  517. }
  518. if (keysym == XK_Caps_Lock) {
  519.     dispPtr->lockUsage = LU_CAPS;
  520.     break;
  521. }
  522.     }
  523.     /*
  524.      * Look through the keycodes associated with modifiers to see if
  525.      * the the "mode switch", "meta", or "alt" keysyms are associated
  526.      * with any modifiers.  If so, remember their modifier mask bits.
  527.      */
  528.     dispPtr->modeModMask = 0;
  529.     dispPtr->metaModMask = 0;
  530.     dispPtr->altModMask = 0;
  531.     codePtr = modMapPtr->modifiermap;
  532.     max = 8*modMapPtr->max_keypermod;
  533.     for (i = 0; i < max; i++, codePtr++) {
  534. if (*codePtr == 0) {
  535.     continue;
  536. }
  537. keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
  538. if (keysym == XK_Mode_switch) {
  539.     dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
  540. }
  541. if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
  542.     dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
  543. }
  544. if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
  545.     dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
  546. }
  547.     }
  548.     /*
  549.      * Create an array of the keycodes for all modifier keys.
  550.      */
  551.     if (dispPtr->modKeyCodes != NULL) {
  552. ckfree((char *) dispPtr->modKeyCodes);
  553.     }
  554.     dispPtr->numModKeyCodes = 0;
  555.     arraySize = KEYCODE_ARRAY_SIZE;
  556.     dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
  557.     (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
  558.     for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
  559. if (*codePtr == 0) {
  560.     continue;
  561. }
  562. /*
  563.  * Make sure that the keycode isn't already in the array.
  564.  */
  565. for (j = 0; j < dispPtr->numModKeyCodes; j++) {
  566.     if (dispPtr->modKeyCodes[j] == *codePtr) {
  567. goto nextModCode;
  568.     }
  569. }
  570. if (dispPtr->numModKeyCodes >= arraySize) {
  571.     KeyCode *new;
  572.     /*
  573.      * Ran out of space in the array;  grow it.
  574.      */
  575.     arraySize *= 2;
  576.     new = (KeyCode *) ckalloc((unsigned)
  577.     (arraySize * sizeof(KeyCode)));
  578.     memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
  579.     (dispPtr->numModKeyCodes * sizeof(KeyCode)));
  580.     ckfree((char *) dispPtr->modKeyCodes);
  581.     dispPtr->modKeyCodes = new;
  582. }
  583. dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
  584. dispPtr->numModKeyCodes++;
  585. nextModCode: continue;
  586.     }
  587.     XFreeModifiermap(modMapPtr);
  588. }