wmii/cmd/menu/keys.c
2009-05-16 11:14:33 -04:00

143 lines
2.4 KiB
C

#include "dat.h"
#include <ctype.h>
#include <strings.h>
#include <unistd.h>
#include "fns.h"
typedef struct Key Key;
struct Key {
Key* next;
long mask;
char* key;
char** action;
};
static Key* bindings;
static void
init_numlock(void) {
static int masks[] = {
ShiftMask, LockMask, ControlMask, Mod1Mask,
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
};
XModifierKeymap *modmap;
KeyCode kcode;
int i, max;
modmap = XGetModifierMapping(display);
kcode = keycode("Num_Lock");
if(kcode)
if(modmap && modmap->max_keypermod > 0) {
max = nelem(masks) * modmap->max_keypermod;
for(i = 0; i < max; i++)
if(modmap->modifiermap[i] == kcode)
numlock = masks[i / modmap->max_keypermod];
}
XFreeModifiermap(modmap);
}
/*
* To do: Find my red black tree implementation.
*/
void
parse_keys(char *spec) {
static char *lines[1024];
static char *words[16];
Key *k;
char *p, *line;
int mask;
int i, nlines, nwords;
if(!numlock)
init_numlock();
nlines = tokenize(lines, nelem(lines), spec, '\n');
for(i=0; i < nlines; i++) {
line = lines[i];
p = strchr(line, '#');
if(p)
*p = '\0';
nwords = stokenize(words, nelem(words) - 1, line, " \t");
words[nwords] = nil;
if(!words[0])
continue;
if(parsekey(words[0], &mask, &p)) {
k = emallocz(sizeof *k);
k->key = p;
k->mask = mask;
k->action = strlistdup(words + 1);
k->next = bindings;
bindings = k;
}
}
}
char**
find_key(char *key, long mask) {
Key *k;
/* Horrible hack. */
if(!strcmp(key, "ISO_Left_Tab"))
key = "Tab";
mask &= ~(numlock | LockMask);
for(k=bindings; k; k=k->next)
if(!strcasecmp(k->key, key) && k->mask == mask)
return k->action;
return nil;
}
/* sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */
/* awk '{$1=""; print}' keys.txt | perl -e '$_=lc join "", <>; print join "\n", m/(\w+)/g;' | sort -u | sed 's:.*: "&",:' */
char *symtab[] = {
"accept",
"backward",
"char",
"complete",
"first",
"forward",
"history",
"kill",
"last",
"line",
"literal",
"next",
"nextpage",
"prev",
"prevpage",
"reject",
"word",
};
static int
_bsearch(char *s, char **tab, int ntab) {
int i, n, m, cmp;
if(s == nil)
return -1;
n = ntab;
i = 0;
while(n) {
m = n/2;
cmp = strcasecmp(s, tab[i+m]);
if(cmp == 0)
return i+m;
if(cmp < 0 || m == 0)
n = m;
else {
i += m;
n = n-m;
}
}
return -1;
}
int
getsym(char *s) {
return _bsearch(s, symtab, nelem(symtab));
}