|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.