diff --git a/cmd/wmii/bar.c b/cmd/wmii/bar.c index 09e23111..77e4b1a9 100644 --- a/cmd/wmii/bar.c +++ b/cmd/wmii/bar.c @@ -95,9 +95,9 @@ bar_create(Bar **bp, const char *name) { utflcpy(b->name, name, sizeof b->name); b->col = def.normcolor; - strlcat(b->buf, b->col.colstr, sizeof(b->buf)); - strlcat(b->buf, " ", sizeof(b->buf)); - strlcat(b->buf, b->text, sizeof(b->buf)); + strlcat(b->buf, b->col.colstr, sizeof b->buf); + strlcat(b->buf, " ", sizeof b->buf); + strlcat(b->buf, b->text, sizeof b->buf); SET(i); for(sp=screens; (s = *sp); sp++) { diff --git a/cmd/wmii/client.c b/cmd/wmii/client.c index ba2f3a08..0f022cc3 100644 --- a/cmd/wmii/client.c +++ b/cmd/wmii/client.c @@ -197,7 +197,21 @@ client_create(XWindow w, XWindowAttributes *wa) { static bool apply_rules(Client *c) { + IxpMsg m; Rule *r; + Ruleval *rv; + + if(def.rules.string) + for(r=def.rules.rule; r; r=r->next) + if(regexec(r->regex, c->props, nil, 0)) { + for(rv=r->values; rv; rv=rv->next) { + bufclear(); + bufprint("%s %s", rv->key, rv->value); + m = ixp_message(buffer, sizeof buffer, MsgPack); + message_client(c, &m); + } + return true; + } if(def.tagrules.string) for(r=def.tagrules.rule; r; r=r->next) @@ -1116,10 +1130,10 @@ client_applytags(Client *c, const char *tags) { found = false; j = 0; - while(buf[n] && n < sizeof(buf) && j < 32) { + while(buf[n] && n < sizeof buf && j < 32) { /* Check for regex. */ if(buf[n] == '/') { - for(i=n+1; i < sizeof(buf) - 1; i++) + for(i=n+1; i < sizeof buf - 1; i++) if(buf[i] == '/') break; if(buf[i] == '/') { i++; @@ -1140,7 +1154,7 @@ client_applytags(Client *c, const char *tags) { } } - for(i = n; i < sizeof(buf) - 1; i++) + for(i = n; i < sizeof buf - 1; i++) if(buf[i] == '+' || buf[i] == '-' || buf[i] == '\0') diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h index 5a07f200..5027ccdd 100644 --- a/cmd/wmii/dat.h +++ b/cmd/wmii/dat.h @@ -59,11 +59,14 @@ enum { extern char* modes[]; +#define toggle(val, x) \ + ((x) == On ? true : \ + (x) == Off ? false : \ + (x) == Toggle ? !(val) : (val)) #define TOGGLE(x) \ - (x == On ? "on" : \ - x == Off ? "off" : \ - x == Toggle ? "toggle" : \ - "") + ((x) == On ? "on" : \ + (x) == Off ? "off" : \ + (x) == Toggle ? "toggle" : "") enum { Off, On, @@ -240,7 +243,7 @@ struct Ruleval { Ruleval* next; char* key; char* value; -} +}; struct Strut { Rectangle left; diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h index 1d8ca86b..75f82363 100644 --- a/cmd/wmii/fns.h +++ b/cmd/wmii/fns.h @@ -208,6 +208,7 @@ char* message_client(Client*, IxpMsg*); char* message_root(void*, IxpMsg*); char* message_view(View*, IxpMsg*); char* msg_debug(IxpMsg*); +void msg_eatrunes(IxpMsg*, int (*)(Rune), int); char* msg_getword(IxpMsg*); char* msg_parsecolors(IxpMsg*, CTuple*); char* msg_selectarea(Area*, IxpMsg*); @@ -249,7 +250,7 @@ int ownerscreen(Rectangle); /* rule.c */ void trim(char *str, const char *chars); -void update_rules(Rule**, const char*); +void update_rules(Rule**, char*); /* view.c */ void view_arrange(View*); diff --git a/cmd/wmii/fs.c b/cmd/wmii/fs.c index 4752131c..bb7919f4 100644 --- a/cmd/wmii/fs.c +++ b/cmd/wmii/fs.c @@ -339,7 +339,7 @@ lookup_file(IxpFileId *parent, char *name) file->p.rule = &def.colrules; break; case FsFRules: - file->p.rule = &def.tagrules; + file->p.rule = &def.rules; break; case FsFTagRules: file->p.rule = &def.tagrules; @@ -534,7 +534,7 @@ fs_write(Ixp9Req *r) { case FsFClabel: ixp_srv_data2cstring(r); utfecpy(f->p.client->name, - f->p.client->name+sizeof(client->name), + f->p.client->name + sizeof client->name, r->ifcall.io.data); frame_draw(f->p.client->sel); update_class(f->p.client); diff --git a/cmd/wmii/message.c b/cmd/wmii/message.c index 838ae07c..416b2a30 100644 --- a/cmd/wmii/message.c +++ b/cmd/wmii/message.c @@ -24,8 +24,6 @@ static char /* Edit |sort Edit |sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */ enum { - LFULLSCREEN, - LURGENT, LBAR, LBORDER, LCLIENT, @@ -33,9 +31,11 @@ enum { LDEBUG, LDOWN, LEXEC, + LFLOATING, LFOCUSCOLORS, LFONT, LFONTPAD, + LFULLSCREEN, LGRABMOD, LGROW, LINCMODE, @@ -53,14 +53,14 @@ enum { LSLAY, LSPAWN, LSWAP, + LTAGS, LTOGGLE, LUP, + LURGENT, LVIEW, LTILDE, }; char *symtab[] = { - "Fullscreen", - "Urgent", "bar", "border", "client", @@ -68,9 +68,11 @@ char *symtab[] = { "debug", "down", "exec", + "floating", "focuscolors", "font", "fontpad", + "fullscreen", "grabmod", "grow", "incmode", @@ -88,8 +90,10 @@ char *symtab[] = { "slay", "spawn", "swap", + "tags", "toggle", "up", + "urgent", "view", "~", }; @@ -113,11 +117,13 @@ static char* incmodetab[] = { "show", "squeeze", }; +#ifdef notdef static char* toggletab[] = { "off", "on", "toggle", }; +#endif /* Edit ,y/^[a-zA-Z].*\n.* {\n/d * Edit s/^([a-zA-Z].*)\n(.*) {\n/\1 \2;\n/ @@ -125,17 +131,30 @@ static char* toggletab[] = { */ static int -_bsearch(char *s, char **tab, int ntab) { +_bsearch(char *from, char **tab, int ntab) { int i, n, m, cmp; + char *to, *end; + Rune r; - if(s == nil) + if(from == nil) return -1; + end = buffer + sizeof buffer - UTFmax - 1; + for(to=buffer; *from && to < end;) { + from += chartorune(&r, from); + if(r != 0x80) { + r = tolowerrune(r); + to += runetochar(to, &r); + } + } + *to = '\0'; + to = buffer; + n = ntab; i = 0; while(n) { m = n/2; - cmp = strcmp(s, tab[i+m]); + cmp = strcmp(to, tab[i+m]); if(cmp == 0) return i+m; if(cmp < 0 || m == 0) @@ -189,8 +208,8 @@ getdirection(IxpMsg *m) { } } -static void -eatrunes(IxpMsg *m, int (*p)(Rune), int val) { +void +msg_eatrunes(IxpMsg *m, int (*p)(Rune), int val) { Rune r; int n; @@ -210,13 +229,13 @@ msg_getword(IxpMsg *m) { Rune r; int n; - eatrunes(m, isspacerune, true); + msg_eatrunes(m, isspacerune, true); ret = m->pos; - eatrunes(m, isspacerune, false); + msg_eatrunes(m, isspacerune, false); n = chartorune(&r, m->pos); *m->pos = '\0'; m->pos += n; - eatrunes(m, isspacerune, true); + msg_eatrunes(m, isspacerune, true); /* Filter out comments. */ if(*ret == '#') { @@ -339,11 +358,13 @@ char* readctl_client(Client *c) { bufclear(); bufprint("%#C\n", c); + bufprint("floating %s\n", TOGGLE(c->floating)); if(c->fullscreen >= 0) - bufprint("Fullscreen %d\n", c->fullscreen); + bufprint("fullscreen %d\n", c->fullscreen); else - bufprint("Fullscreen off\n"); - bufprint("Urgent %s\n", toggletab[(int)c->urgent]); + bufprint("fullscreen off\n"); + bufprint("tags %s\n", c->tags); + bufprint("urgent %s\n", TOGGLE(c->urgent)); return buffer; } @@ -360,13 +381,18 @@ message_client(Client *c, IxpMsg *m) { * | off * | toggle * | - * Fullscreen - * Urgent + * floating + * fullscreen * kill * slay + * tags + * urgent */ switch(getsym(s)) { + case LFLOATING: + c->floating = toggle(c->floating, gettoggle(m->pos)); + break; case LFULLSCREEN: s = msg_getword(m); if(getlong(s, &l)) @@ -384,6 +410,9 @@ message_client(Client *c, IxpMsg *m) { case LSLAY: client_kill(c, false); break; + case LTAGS: + client_applytags(c, m->pos); + break; case LURGENT: i = gettoggle(msg_getword(m)); if(i == -1) @@ -812,7 +841,7 @@ msg_parsecolors(IxpMsg *m, CTuple *col) { *p = c; m->pos = p; - eatrunes(m, isspacerune, true); + msg_eatrunes(m, isspacerune, true); return nil; } diff --git a/cmd/wmii/rule.c b/cmd/wmii/rule.c index b060b280..c7270aa6 100644 --- a/cmd/wmii/rule.c +++ b/cmd/wmii/rule.c @@ -23,140 +23,103 @@ trim(char *str, const char *chars) { } 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; +update_rules(Rule **rule, 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) - buf = ixp_message(data, strlen(data), MsgUnpack); -} - -/* XXX: I hate this. --KM */ -void -update_rules(Rule **rule, const char *data) { - enum { - COMMENT, - IGNORE, - REGEX, - VALUE, - WAIT, - }; - int state, old_state; - IxpMsg m; + IxpMsg buf, valuebuf, rebuf; + Reprog *re; + Rule *r; Ruleval **rvp; Ruleval *rv; - Rule *rul; - char regex[256]; - char *regex_end = regex + sizeof(regex) - 1; - char *value_end = buffer + sizeof(buffer) - 1; - char *r, *v; - const char *p; + char *w; + char regexp[256]; 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; + while((r = *rule)) { + *rule = r->next; + while((rv = r->values)) { + r->values = rv->next; free(rv); } - free(rul->regex); - free(rul); + free(r->regex); + free(r->value); + free(r); } - state = IGNORE; - for(p = data; (c = *p); p++) - switch(state) { - case COMMENT: - if(c == '\n') - state = old_state; - break; - case IGNORE: - if(c == '#') - goto comment; - else if(c == '/') { - r = regex; - state = REGEX; - } - else if(c == '>') { - value[0] = 0; - v = value; - state = VALUE; - } - break; - 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; + + if(!data || !data[0]) + return; + + buf = ixp_message(data, strlen(data), MsgUnpack); + +begin: + msg_eatrunes(&buf, isspacerune, true); + if(getc(&buf) == '/') + goto regexp; + /* Regexp not at begining of the line. Rest of the line is junk. */ + while((c = getc(&buf))) + if(c == '\n') + goto begin; + goto done; + +regexp: + rebuf = ixp_message(regexp, sizeof regexp - 1, MsgPack); + while((c = getc(&buf))) + if(c == '/') + goto value; + else if(c != '\\') + putc(&rebuf, c); + else if(buf.pos[1] == '/' || buf.pos[1] == '\\' && buf.pos[2] == '/') + putc(&rebuf, getc(&buf)); + else { + putc(&rebuf, c); + putc(&rebuf, getc(&buf)); + } + goto done; + +value: + valuebuf = ixp_message(buffer, sizeof buffer - 1, MsgPack); + while((c = getc(&buf))) { + if(c == '\n') { + putc(&valuebuf, ' '); + msg_eatrunes(&buf, isspacerune, true); + if((c = getc(&buf)) == '/') { + ungetc(&buf); break; } - if(r < regex_end) - *r++ = c; - break; - case VALUE: - 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; } + putc(&valuebuf, c); + } + + putc(&rebuf, '\0'); + re = regcomp(regexp); + if(!re) + goto begin; + r = emallocz(sizeof *r); + *rule = r; + rule = &r->next; + r->regex = re; + + valuebuf.end = valuebuf.pos; + valuebuf.pos = valuebuf.data; + rvp = &r->values; + while((w = msg_getword(&valuebuf))) { + free(r->value); + r->value = estrdup(w); + if(strchr(w, '=')) { + len = strlen(w) + 1; + *rvp = rv = emallocz(sizeof *rv + len); + rvp = &rv->next; + + memcpy(&rv[1], w, len); + tokenize(&rv->key, 2, (char*)&rv[1], '='); + } + } + goto begin; + +done: + return; } +