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

Defined functions

BackstopLookupMapping defined in line 100; used 1 times
Initialize defined in line 41; used 2 times
Unbind defined in line 259; used 2 times
XRebindCode defined in line 180; never used

Defined variables

inited defined in line 19; used 3 times
keymap defined in line 18; used 9 times

Defined macros

EMPTY_ENTRY defined in line 14; used 2 times
RT_INCREMENT defined in line 39; used 2 times
RT_INITIAL_SIZE defined in line 38; used 2 times
Last modified: 1986-02-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1433
Valid CSS Valid XHTML 1.0 Strict