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