diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h index af9cd456..5a07f200 100644 --- a/cmd/wmii/dat.h +++ b/cmd/wmii/dat.h @@ -106,6 +106,7 @@ typedef struct Group Group; typedef struct Key Key; typedef struct Rule Rule; typedef struct Ruleset Ruleset; +typedef struct Ruleval Ruleval; typedef struct Strut Strut; typedef struct View View; typedef struct WMScreen WMScreen; @@ -223,10 +224,10 @@ struct Key { }; struct Rule { - Rule* next; - Reprog* regex; - char value[256]; - + Rule* next; + Reprog* regex; + char* value; + Ruleval* values; }; struct Ruleset { @@ -235,6 +236,12 @@ struct Ruleset { uint size; }; +struct Ruleval { + Ruleval* next; + char* key; + char* value; +} + struct Strut { Rectangle left; Rectangle right; @@ -271,8 +278,9 @@ EXTERN struct { Font* font; char* keys; uint keyssz; - Ruleset tagrules; Ruleset colrules; + Ruleset tagrules; + Ruleset rules; char grabmod[5]; ulong mod; uint border; diff --git a/cmd/wmii/fs.c b/cmd/wmii/fs.c index a4ef1066..4752131c 100644 --- a/cmd/wmii/fs.c +++ b/cmd/wmii/fs.c @@ -44,6 +44,7 @@ enum { /* Dirs */ FsFEvent, FsFKeys, FsFRctl, + FsFRules, FsFTagRules, FsFTctl, FsFTindex, @@ -90,6 +91,7 @@ dirtab_root[]= {{".", QTDIR, FsRoot, 0500|DMDIR }, {"colrules", QTFILE, FsFColRules, 0600 }, {"event", QTFILE, FsFEvent, 0600 }, {"keys", QTFILE, FsFKeys, 0600 }, + {"rules", QTFILE, FsFRules, 0600 }, {"tagrules", QTFILE, FsFTagRules, 0600 }, {nil}}, dirtab_clients[]={{".", QTDIR, FsDClients, 0500|DMDIR }, @@ -336,6 +338,9 @@ lookup_file(IxpFileId *parent, char *name) case FsFColRules: file->p.rule = &def.colrules; break; + case FsFRules: + file->p.rule = &def.tagrules; + break; case FsFTagRules: file->p.rule = &def.tagrules; break; @@ -379,6 +384,7 @@ fs_size(IxpFileId *f) { default: return 0; case FsFColRules: + case FsFRules: case FsFTagRules: return f->p.rule->size; case FsFKeys: @@ -447,6 +453,7 @@ fs_read(Ixp9Req *r) { respond(r, nil); return; case FsFColRules: + case FsFRules: case FsFTagRules: ixp_srv_readbuf(r, f->p.rule->string, f->p.rule->size); respond(r, nil); @@ -515,6 +522,7 @@ fs_write(Ixp9Req *r) { switch(f->tab.type) { case FsFColRules: + case FsFRules: case FsFTagRules: ixp_srv_writebuf(r, &f->p.rule->string, &f->p.rule->size, 0); respond(r, nil); @@ -681,16 +689,18 @@ fs_clunk(Ixp9Req *r) { switch(f->tab.type) { case FsFColRules: - update_rules(&f->p.rule->rule, f->p.rule->string); - break; + case FsFRules: case FsFTagRules: update_rules(&f->p.rule->rule, f->p.rule->string); + break; /* + case FsFTagRules: + update_rules(&f->p.rule->rule, f->p.rule->string); for(c=client; c; c=c->next) apply_rules(c); view_update_all(); - */ break; + */ case FsFKeys: update_keys(); break; diff --git a/cmd/wmii/rule.c b/cmd/wmii/rule.c index 28f68f45..b060b280 100644 --- a/cmd/wmii/rule.c +++ b/cmd/wmii/rule.c @@ -22,33 +22,59 @@ trim(char *str, const char *chars) { *q = '\0'; } +void +update_rules(Rule **rule, const char *data) { +#define putc(m, c) BLOCK(if(m.pos < m.end) *m.pos++ = c) +#define getc(m) (m.pos < m.end ? *m.pos++ : 0) +#define ungetc(m) BLOCK(if(m.pos > m.data) --m.pos) + IxpMsg buf, outbuf, rebuf; + char regex[256]; + char c; + + buf = ixp_message(data, strlen(data), MsgUnpack); +} + /* XXX: I hate this. --KM */ void update_rules(Rule **rule, const char *data) { - /* basic rule matching language /regex/ -> value - * regex might contain POSIX regex syntax defined in regex(3) */ enum { + COMMENT, IGNORE, REGEX, VALUE, - COMMENT, + WAIT, }; - int state; + int state, old_state; + IxpMsg m; + Ruleval **rvp; + Ruleval *rv; Rule *rul; - char regex[256], value[256]; + char regex[256]; char *regex_end = regex + sizeof(regex) - 1; - char *value_end = value + sizeof(value) - 1; + char *value_end = buffer + sizeof(buffer) - 1; char *r, *v; const char *p; char c; + int len; + +#define NEXT(next) BLOCK( \ + old_state = state \ + state = next; \ + continue; \ + ) SET(r); SET(v); + SET(old_state); if(!data || !strlen(data)) return; while((rul = *rule)) { *rule = rul->next; + while((rv = rul->values)) { + rul->values = rv->next; + free(rv); + } free(rul->regex); free(rul); } @@ -57,11 +83,11 @@ update_rules(Rule **rule, const char *data) { switch(state) { case COMMENT: if(c == '\n') - state = IGNORE; + state = old_state; break; case IGNORE: if(c == '#') - state = COMMENT; + goto comment; else if(c == '/') { r = regex; state = REGEX; @@ -75,6 +101,10 @@ update_rules(Rule **rule, const char *data) { case REGEX: if(c == '\\' && p[1] == '/') p++; + else if(c == '\\' && p[1] == '\\' && p[2] == '/') + p++; + else if(c == '\\' && r < regex_end) + *r++ = *p++; else if(c == '/') { *r = 0; state = IGNORE; @@ -84,24 +114,49 @@ update_rules(Rule **rule, const char *data) { *r++ = c; break; case VALUE: - if(c == '\n' || c == '#' || c == 0) { - *v = 0; - trim(value, " \t"); - *rule = emallocz(sizeof **rule); - (*rule)->regex = regcomp(regex); - if((*rule)->regex) { - utflcpy((*rule)->value, value, sizeof rul->value); - rule = &(*rule)->next; - }else - free(*rule); - state = IGNORE; - if(c == '#') - state = COMMENT; - } - else if(v < value_end) + if(c == '#') + NEXT(COMMENT); + if(c == '\n') + NEXT(WAIT); + if(v < value_end) *v++ = c; break; + case WAIT: + if(c == '#') + NEXT(COMMENT); + if(c == '/') { + state = + break; default: /* can't happen */ die("invalid state"); + accept: + + *v = 0; + *rule = emallocz(sizeof **rule); + (*rule)->regex = regcomp(regex); + if((*rule)->regex) { + (*rule)->value = strdup(buffer); + trim((*rule)->value, " \t"); + + rvp = &(*rule)->values; + m = ixp_message(buffer, v - buffer, MsgUnpack); + while((r = msg_getword(&m))) + if((v = strchr(r, '='))) { + len = strlen(r) + 1; + *rvp = rv = emalloc(sizeof *rv + len); + rvp = &rv->next; + + memcpy(&rv[1], r, len); + tokenize(&rv->key, 2, (char*)&rv[1], '='); + } + + + rule = &(*rule)->next; + }else + free(*rule); + + r = regex; + + break; } } diff --git a/lib/libstuff/printevent.c b/lib/libstuff/printevent.c index b0b09322..adae25e0 100644 --- a/lib/libstuff/printevent.c +++ b/lib/libstuff/printevent.c @@ -558,7 +558,7 @@ VerbButton(Fmt *fmt, XEvent *e) { TInt, _(x), TInt, _(y), TInt, _(x_root), TInt, _(y_root), TModState, _(state), - TModState, _(button), + TInt, _(button), TBool, _(same_screen), TEnd );