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