home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / xterm / part07 / Xlib / XKeyBind.c < prev   
Encoding:
C/C++ Source or Header  |  1987-04-21  |  9.5 KB  |  352 lines

  1. #include <X/mit-copyright.h>
  2.  
  3. /* $Header: XKeyBind.c,v 10.12 86/07/21 15:27:14 wesommer Rel $ */
  4. /* Copyright 1985, Massachusetts Institute of Technology */
  5.  
  6. #include "XlibInternal.h"
  7. #include <sys/file.h>
  8. #include <sys/stat.h>
  9. #include "Xkeymap.h"
  10. #include "Xkeyboard.h"
  11. #include <stdio.h>
  12. #include <strings.h>
  13. #ifdef KEYBD
  14. #include "Xdefault.h"
  15. #endif KEYBD
  16.  
  17. #define EMPTY_ENTRY LeftMask 
  18.    /* if the "metabits" field of a runtime table entry contains this,
  19.     it's an empty entry */
  20.  
  21. static KeyMapElt *keymap = NULL;
  22. static Bool inited = FALSE;
  23.  
  24. static ExtensionHeader *ext_begin, *ext_end;
  25.  
  26. /* Runtime table: contains multiple-byte character bindings defined
  27.   at runtime with XRebindCode */
  28.  
  29. typedef struct {
  30.     unsigned char keycode;
  31.     unsigned short metabits;
  32.     short length;
  33.     char *value;
  34.     } RuntimeTableEntry;
  35.  
  36. static RuntimeTableEntry
  37.    *rt_begin,  /* first entry of runtime table */
  38.    *rt_end,    /* this and all succeeding entries are empty */
  39.    *rt_buf_end;/* points beyond end of allocated storage for table */
  40.  
  41. #ifdef KEYBD
  42. char *keyboardtype = NULL;
  43. #endif KEYBD
  44.  
  45. #define RT_INITIAL_SIZE 100  /* initial size of runtime table */
  46. #define RT_INCREMENT 40  /* size to grow by if expanded */
  47.  
  48. XUseKeymap(filename) 
  49.     char *filename;
  50. {
  51.     int file = -1;
  52.     int filesize;
  53.     unsigned char magic;
  54.     struct stat filestat;
  55.     file = open (filename, O_RDONLY, 0);
  56.     if (file < 0) {
  57.         return(0);        /* no keymap file found */
  58.     }
  59.     fstat (file, &filestat);
  60.     filesize = filestat.st_size - 1; /* first byte is magic number */
  61.     if (filesize < 256*sizeof(KeyMapElt)) {
  62.     fprintf (stderr, "Keymap file %s is too small\n", filename);
  63.     close (file);
  64.     return(0);
  65.     }
  66.     read (file, &magic, 1);
  67.     if (magic != X_KEYMAP_MAGIC) {
  68.     fprintf (stderr, 
  69.       "Keymap file %s doesn't begin with the proper magic number\n",
  70.       filename);
  71.         close (file);
  72.           return(0);
  73.     }
  74.     keymap = (KeyMapElt *) malloc (filesize);
  75.     if (!keymap) {
  76.     close (file);
  77.           return(0);  /* couldn't malloc; just act like there isn't a keymap */
  78.     }
  79.     read (file, (char *) keymap, filesize);
  80.     ext_begin = (ExtensionHeader *) (keymap + 256);
  81.     ext_end = (ExtensionHeader *) (((char *) keymap) + filesize);
  82.     rt_begin = (RuntimeTableEntry *) malloc (RT_INITIAL_SIZE*sizeof(RuntimeTableEntry));
  83.     if (!rt_begin)
  84.          _XIOError (_XlibCurrentDisplay);
  85.     rt_end = rt_begin;
  86.     rt_buf_end = rt_begin + RT_INITIAL_SIZE;
  87.     close (file);
  88.     inited = TRUE;
  89.     return(1);
  90. }
  91.  
  92. static Initialize() {
  93.     int file = -1;
  94.     int filesize;
  95.     unsigned char magic;
  96.     struct stat filestat;
  97.     char *getenv();
  98.     char *filename = NULL;
  99. #ifdef KEYBD
  100.     char *home;
  101.     char *kdefault = "default";
  102.     char *keybddir = KEYBDDIR;
  103. #else KEYBD
  104.     char *home = getenv ("HOME");
  105. #endif KEYBD
  106.  
  107.     inited = TRUE;
  108. #ifdef KEYBD
  109.     if(keyboardtype && *keyboardtype) {    /* Use keyboard type keymap */
  110.     filename = malloc(strlen(keybddir) + strlen(keyboardtype) + 1);
  111.     strcpy(filename, keybddir);
  112.     strcat(filename, keyboardtype);
  113.     if((file = open (filename, O_RDONLY, 0)) < 0) {
  114.         free (filename);
  115.         filename = NULL;
  116.     }
  117.     }
  118.     if(file < 0 && (home = getenv ("HOME")))
  119. #else KEYBD
  120.     if (home)
  121. #endif KEYBD
  122.      {
  123.     int homelen = strlen (home);
  124.     char *keymapstr = "/.Xkeymap";
  125.     int keymapstrlen = strlen (keymapstr);
  126.     filename = malloc (homelen + keymapstrlen + 1);
  127.     strncpy (filename, home, homelen+1);
  128.     strncat (filename, keymapstr, keymapstrlen);
  129.     file = open (filename, O_RDONLY, 0);
  130.     }
  131. #ifdef KEYBD
  132.     if (file < 0) {    /* Try system default keymap */
  133.     if(filename)
  134.         free(filename);
  135.     filename = malloc(strlen(keybddir) + strlen(kdefault) + 1);
  136.     strcpy(filename, keybddir);
  137.     strcat(filename, kdefault);
  138.     file = open (filename, O_RDONLY, 0);
  139.     }
  140. #endif KEYBD
  141.     if (file < 0) {
  142.     if(filename)
  143.         free(filename);
  144.     return; /* no keymap file found */
  145.     }
  146.     fstat (file, &filestat);
  147.     filesize = filestat.st_size - 1; /* first byte is magic number */
  148.     if (filesize < 256*sizeof(KeyMapElt)) {
  149.     fprintf (stderr, "Keymap file %s is too small\n", filename);
  150.     close (file);
  151.     free (filename);
  152.     return;
  153.     }
  154.     read (file, &magic, 1);
  155.     if (magic != X_KEYMAP_MAGIC) {
  156.     fprintf (stderr, 
  157.       "Keymap file %s doesn't begin with the proper magic number\n",
  158.       filename);
  159.         close (file);
  160.     free (filename);
  161.           return;
  162.     }
  163.     keymap = (KeyMapElt *) malloc (filesize);
  164.     if (!keymap) {
  165.     close (file);
  166.     free (filename);
  167.           return;  /* couldn't malloc; just act like there isn't a keymap */
  168.     }
  169.     read (file, (char *) keymap, filesize);
  170.     ext_begin = (ExtensionHeader *) (keymap + 256);
  171.     ext_end = (ExtensionHeader *) (((char *) keymap) + filesize);
  172.     rt_begin = (RuntimeTableEntry *) malloc (RT_INITIAL_SIZE*sizeof(RuntimeTableEntry));
  173.     if (!rt_begin)
  174.          _XIOError (_XlibCurrentDisplay);
  175.     rt_end = rt_begin;
  176.     rt_buf_end = rt_begin + RT_INITIAL_SIZE;
  177.     free (filename);
  178.     close (file);
  179.     }
  180.  
  181. /* this routine is used when initialization failed to find a
  182.    valid keymap file */
  183. static char *BackstopLookupMapping (event, nbytes)
  184.     XKeyPressedEvent *event;
  185.     int *nbytes;
  186.     {
  187.     int detail = event->detail;
  188.     register int keycode = detail & ValueMask;
  189.     extern KeyMapEntry StdMap[];
  190.     static char c;
  191.     short s;  /* needed to distinguish a real character (e.g. \0377) from -1 */
  192.     s = StdMap [keycode] [KeyState(detail)];
  193.     c = s;
  194.     if ((detail & ShiftLockMask) && (c >= 'a') && (c <= 'z'))
  195.         c += ('A' - 'a');
  196.     if (IsTypewriterKey(keycode)
  197.       || keycode == KC_ESC || keycode == KC_BS || keycode == KC_LF)
  198.     *nbytes = (s == -1 ? 0 : 1);
  199.     else
  200.         *nbytes = 0;
  201.     return (&c);
  202.     }
  203.  
  204. char *XLookupMapping (event, nbytes)
  205.     XKeyPressedEvent *event;
  206.     int *nbytes;
  207.     {
  208.     int detail = event->detail;
  209.     unsigned int metabits = FullKeyState (detail);
  210.     unsigned int key = detail & ValueMask;
  211.     register unsigned char *the_char;
  212.  
  213.     if (!inited)
  214.           Initialize();
  215.     if (!keymap)
  216.         return (BackstopLookupMapping (event, nbytes));
  217.  
  218.     the_char = &keymap [key] [metabits];
  219.  
  220.     switch (*the_char) {
  221.  
  222.           case UNBOUND: {
  223.         *nbytes = 0;
  224.         return (NULL);
  225.         }
  226.  
  227.           case EXTENSION_BOUND: {
  228.         register ExtensionHeader *this;
  229.         for (this = ext_begin; this < ext_end; NextExtension(this))
  230.             if ((key == this->keycode)
  231.             && ((metabits == this->metabits) || (this->metabits == DontCareMetaBits))) {
  232.                 *nbytes = this->length;
  233.                 return ((char *)this + ExtensionHeaderSize);
  234.                 }
  235.         /* if we get here, no match was found in the table extension */
  236.         *nbytes = 0;
  237.         return (NULL);
  238.         }
  239.  
  240.         case RUNTIME_TABLE_BOUND: {
  241.         register RuntimeTableEntry *entry;
  242.         for (entry = rt_begin; entry < rt_end; entry++)
  243.             if ((key == entry->keycode)
  244.             && ((metabits == entry->metabits) || (entry->metabits == DontCareMetaBits))) {
  245.             *nbytes = entry->length;
  246.             return (entry->value);
  247.             }
  248.  
  249.         /* if we get here, no match was found in the runtime table */
  250.         *nbytes = 0;
  251.         return (NULL);
  252.         }
  253.  
  254.     default: {
  255.         *nbytes = 1;
  256.         return ((char *)the_char);
  257.         }
  258.           }
  259.  
  260.     }
  261.  
  262.  
  263. XRebindCode (keycode, metabits, str, nbytes)
  264.     unsigned int keycode, metabits;
  265.     char *str;
  266.     int nbytes;
  267.     {
  268.     unsigned char *table_char;
  269.     metabits = FullKeyState (metabits);  /* shift meta bits to rightmost four bits */
  270.     if (!inited)
  271.         Initialize();
  272.     if (!keymap)
  273.         return;  /* no keymap file; what else can I do? */
  274.     table_char = &keymap [keycode] [metabits];
  275.     if (nbytes == 0) {
  276.     if (*table_char == RUNTIME_TABLE_BOUND)
  277.         Unbind (keycode, metabits);
  278.     *table_char = UNBOUND;
  279.     return;
  280.     }
  281.     if ((nbytes == 1) && SingleCharBound (*str)) {
  282.         if (*table_char == RUNTIME_TABLE_BOUND)
  283.         Unbind (keycode, metabits);
  284.     *table_char = *str;
  285.     return;
  286.     }
  287.     
  288.     /* the new binding is either multi-character, or one of the
  289.        three reserved special characters */
  290.  
  291.     if (*table_char == RUNTIME_TABLE_BOUND) {
  292.     /* entry is already in table; just change its binding */
  293.     register RuntimeTableEntry *entry;
  294.     for (entry = rt_begin; entry < rt_end; entry++)
  295.         if (keycode == entry->keycode && metabits == entry->metabits) {
  296.         entry->value = str;
  297.         entry->length = nbytes;
  298.         return;
  299.         }
  300.     /* if we get here, entry wasn't found in table; shouldn't
  301.      * ever happen!  Not much to do but fall through to 
  302.      * the following code.  */
  303.         }
  304.  
  305.     /* new binding must go in a new entry in the table */
  306.     *table_char = RUNTIME_TABLE_BOUND;
  307.     if (rt_end < rt_buf_end) {
  308.     rt_end->keycode = keycode;
  309.     rt_end->metabits = metabits;
  310.     rt_end->value = str;
  311.     rt_end++->length = nbytes;
  312.     return;
  313.     }
  314.  
  315.     /* no room at end of table; look for holes in middle */
  316.     {
  317.     register RuntimeTableEntry *entry;
  318.     for (entry = rt_begin; entry < rt_end; entry++)
  319.         if (entry->metabits == EMPTY_ENTRY) {
  320.         entry->keycode = keycode;
  321.         entry->metabits = metabits;
  322.         entry->value = str;
  323.         entry->length = nbytes;
  324.         return;
  325.         }
  326.     }
  327.  
  328.     /* no room in table at all.  Must expand it. */
  329.     {
  330.     int rt_length = rt_end - rt_begin;
  331.     rt_begin = (RuntimeTableEntry *) realloc ((char *)rt_begin, (rt_length+RT_INCREMENT)*sizeof (RuntimeTableEntry));
  332.     rt_end = rt_begin + rt_length;
  333.     rt_buf_end = rt_end + RT_INCREMENT;
  334.     rt_end->keycode = keycode;
  335.     rt_end->metabits = metabits;
  336.     rt_end->value = str;
  337.     rt_end++->length = nbytes;
  338.     }
  339.     }
  340.     
  341.  
  342. static Unbind (keycode, metabits)
  343.     unsigned int keycode, metabits;
  344.     {
  345.     register RuntimeTableEntry *entry;
  346.     for (entry = rt_begin; entry < rt_end; entry++)
  347.         if (keycode == entry->keycode && metabits == entry->metabits) {
  348.         entry->metabits = EMPTY_ENTRY;
  349.         return;
  350.         }
  351.     }
  352.