1 #include "dat.h"
2 #include <ctype.h>
3 #include <strings.h>
4 #include <unistd.h>
5 #include "fns.h"
6
7 typedef struct Key Key;
8
9 struct Key {
10 Key* next;
11 long mask;
12 char* key;
13 char** action;
14 };
15
16 static Key* bindings;
17
18 static void
init_numlock(void)19 init_numlock(void) {
20 static int masks[] = {
21 ShiftMask, LockMask, ControlMask, Mod1Mask,
22 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
23 };
24 XModifierKeymap *modmap;
25 KeyCode kcode;
26 int i, max;
27
28 modmap = XGetModifierMapping(display);
29 kcode = keycode("Num_Lock");
30 if(kcode)
31 if(modmap && modmap->max_keypermod > 0) {
32 max = nelem(masks) * modmap->max_keypermod;
33 for(i = 0; i < max; i++)
34 if(modmap->modifiermap[i] == kcode)
35 numlock = masks[i / modmap->max_keypermod];
36 }
37 XFreeModifiermap(modmap);
38 }
39
40 /*
41 * To do: Find my red black tree implementation.
42 */
43 void
parse_keys(char * spec)44 parse_keys(char *spec) {
45 static char *lines[1024];
46 static char *words[16];
47 Key *k;
48 char *p, *line;
49 int mask;
50 int i, nlines, nwords;
51
52 if(!numlock)
53 init_numlock();
54
55 nlines = tokenize(lines, nelem(lines), spec, '\n');
56 for(i=0; i < nlines; i++) {
57 line = lines[i];
58 p = strchr(line, '#');
59 if(p)
60 *p = '\0';
61
62 nwords = stokenize(words, nelem(words) - 1, line, " \t");
63 words[nwords] = nil;
64 if(!words[0])
65 continue;
66 if(parsekey(words[0], &mask, &p)) {
67 k = emallocz(sizeof *k);
68 k->key = p;
69 k->mask = mask;
70 k->action = strlistdup(words + 1);
71 k->next = bindings;
72 bindings = k;
73 }
74 }
75 }
76
77 char**
find_key(char * key,long mask)78 find_key(char *key, long mask) {
79 Key *k;
80
81 /* Horrible hack. */
82 if(!strcmp(key, "ISO_Left_Tab"))
83 key = "Tab";
84
85 mask &= ~(numlock | LockMask) & ((1<<8) - 1);
86 for(k=bindings; k; k=k->next)
87 if(!strcasecmp(k->key, key) && k->mask == mask)
88 return k->action;
89 return nil;
90 }
91
92 /* sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */
93 /* awk '{$1=""; print}' keys.txt | perl -e '$_=lc join "", <>; print join "\n", m/(\w+)/g;' | sort -u | sed 's:.*: "&",:' */
94 char *symtab[] = {
95 "accept",
96 "backward",
97 "char",
98 "complete",
99 "first",
100 "forward",
101 "history",
102 "kill",
103 "last",
104 "line",
105 "literal",
106 "next",
107 "nextpage",
108 "prev",
109 "prevpage",
110 "reject",
111 "word",
112 };
113
114 static int
_bsearch(char * s,char ** tab,int ntab)115 _bsearch(char *s, char **tab, int ntab) {
116 int i, n, m, cmp;
117
118 if(s == nil)
119 return -1;
120
121 n = ntab;
122 i = 0;
123 while(n) {
124 m = n/2;
125 cmp = strcasecmp(s, tab[i+m]);
126 if(cmp == 0)
127 return i+m;
128 if(cmp < 0 || m == 0)
129 n = m;
130 else {
131 i += m;
132 n = n-m;
133 }
134 }
135 return -1;
136 }
137
138 int
getsym(char * s)139 getsym(char *s) {
140 return _bsearch(s, symtab, nelem(symtab));
141 }
142
143