|
|
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.