diff --git a/src/infobar.c b/src/infobar.c index b90ccf4..68f9408 100644 --- a/src/infobar.c +++ b/src/infobar.c @@ -268,6 +268,8 @@ infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos, /* struct elements */ infobar_elem_init(i); + SLIST_INIT(&i->statushead); + /* Render, only if pos is Top or Bottom */ if(!map) return i; diff --git a/src/status.c b/src/status.c index 23b1283..2f7b2d9 100644 --- a/src/status.c +++ b/src/status.c @@ -10,43 +10,28 @@ #include "util.h" #include -#include -/* Parse arg;between;semicolon */ -#define STATUS_GET_ARGS(i, p, arg, n) \ - do { \ - for(i = 0, p += 2, arg[0] = p; *p && *p != ']' && i < n; ++p) \ - if(*p == ';') \ - { \ - *p = '\0'; \ - arg[++i] = ++p; \ - } \ - *p = '\0'; \ - } while(/* CONSTCOND */ 0); +static struct status_seq* +status_new_seq(char type, int narg, int minarg, char *args[], int *shift) +{ + struct status_seq *sq = xcalloc(1, sizeof(struct status_seq)); -#define STATUS_CHECK_ARGS(i, n1, n2, str, end) \ - if(i != n1 && i != n2) \ - { \ - str = end + 2; \ - continue; \ + SLIST_INIT(&sq->mousebinds); + sq->type = type; + *shift = 0; + + if(narg == minarg || !strcmp(args[0], "right") || !strcmp(args[0], "left")) + sq->align = str_to_position(args[0]); + else + { + sq->align = NoAlign; + sq->geo.x = ATOI(args[0]); + sq->geo.y = ATOI(args[1]); + *shift = 1; } -/* Alloc & fill status_sq struct with universal options: align/position and type */ -#define STATUS_FILL_SQ(sq, t, ma, shift, arg) \ - do { \ - sq = xcalloc(1, sizeof(struct status_seq)); \ - sq->type = t; \ - \ - if(i == ma || !strcmp(arg[0], "right") || !strcmp(arg[0], "left")) \ - sq->align = str_to_position(arg[0]); \ - else \ - { \ - sq->align = NoAlign; \ - sq->geo.x = ATOI(arg[0]); \ - sq->geo.y = ATOI(arg[1]); \ - shift = 1; \ - } \ - } while(/* CONSTCOND */ 0); \ + return sq; +} /* Parse mousebind sequence next normal sequence: \[](button;func;cmd) */ static char* @@ -54,19 +39,13 @@ status_parse_mouse(struct status_seq *sq, struct element *e, char *str) { struct mousebind *m; struct barwin *b = SLIST_FIRST(&e->bars); - char *arg[3] = { NULL }; + char *end, *arg[3] = { NULL }; int i; - if(*str != '(' || !strchr(str, ')')) + if(*str != '(' || !(end = strchr(str, ')'))) return str + 1; - for(i = 0, ++str, arg[0] = str; *str && *str != ')' && i < 3; ++str) - if(*str == ';') - { - *str = '\0'; - arg[++i] = ++str; - } - *str = '\0'; + i = parse_args(++str, ';', ')', 3, arg); m = xcalloc(1, sizeof(struct mousebind)); @@ -75,13 +54,18 @@ status_parse_mouse(struct status_seq *sq, struct element *e, char *str) m->func = uicb_name_func(arg[1]); m->cmd = (i > 1 ? xstrdup(arg[2]) : NULL); - sq->mousebind = m; - SLIST_INSERT_HEAD(&b->mousebinds, m, next); + SLIST_INSERT_HEAD(&sq->mousebinds, m, snext); - return str + 1; + return end + 1; } +#define STATUS_CHECK_ARGS(i, n1, n2, str, end) \ + if(i != n1 && i != n2) \ + { \ + str = end + 2; \ + continue; \ + } static void status_parse(struct element *e) { @@ -102,15 +86,15 @@ status_parse(struct element *e) continue; /* Then parse & list it */ - switch((type = tolower(*p))) + switch((type = *p) ) { /* * Text sequence: \s[left/right;#color;text] OR \s[x;y;#color;text] */ case 's': - STATUS_GET_ARGS(i, p, arg, 4); + i = parse_args(p + 2, ';', ']', 4, arg); STATUS_CHECK_ARGS(i, 2, 3, dstr, end); - STATUS_FILL_SQ(sq, type, 2, shift, arg); + sq = status_new_seq(type, i, 2, arg, &shift); sq->color = color_atoh(arg[1 + shift]); sq->str = xstrdup(arg[2 + shift]); @@ -120,10 +104,10 @@ status_parse(struct element *e) /* * Rectangle sequence: \R[left/right;w;h;#color] OR \R[x;y;w;h;#color] */ - case 'r': - STATUS_GET_ARGS(i, p, arg, 5); + case 'R': + i = parse_args(p + 2, ';', ']', 5, arg); STATUS_CHECK_ARGS(i, 3, 4, dstr, end); - STATUS_FILL_SQ(sq, type, 3, shift, arg); + sq = status_new_seq(type, i, 3, arg, &shift); sq->geo.w = ATOI(arg[1 + shift]); sq->geo.h = ATOI(arg[2 + shift]); @@ -134,22 +118,36 @@ status_parse(struct element *e) SLIST_INSERT_TAIL(&e->infobar->statushead, sq, next, prev); - dstr = status_parse_mouse(sq, e, end + 1); + /* + * Optional mousebind sequence(s) \[](button;func;cmd) + * Parse it while there is a mousebind sequence. + */ + dstr = ++end; + while((*(dstr = status_parse_mouse(sq, e, dstr)) == '(')); - printf(":%s\n", dstr); - - shift = 0; prev = sq; } free(sauv); } +#define STATUS_ALIGN(align) \ + if(align == Left) \ + { \ + sq->geo.x = left; \ + left += sq->geo.w; \ + } \ + else if(align == Right) \ + { \ + sq->geo.x = e->geo.w - right - sq->geo.w; \ + right += sq->geo.w; \ + } static void status_apply_list(struct element *e) { struct status_seq *sq; struct barwin *b = SLIST_FIRST(&e->bars); + struct mousebind *m; int left = 0, right = 0; SLIST_FOREACH(sq, &e->infobar->statushead, next) @@ -164,48 +162,31 @@ status_apply_list(struct element *e) if(sq->align != NoAlign) sq->geo.y = TEXTY(e->infobar->theme, e->geo.h); - if(sq->align == Left) - { - sq->geo.x = left; - left += sq->geo.w; - } - else if(sq->align == Right) - { - sq->geo.x = e->geo.w - right - sq->geo.w; - right += sq->geo.w; - } + STATUS_ALIGN(sq->align); draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str); - if(sq->mousebind) - { - sq->mousebind->area = sq->geo; - sq->mousebind->area.y -= sq->geo.h; - } + if(!SLIST_EMPTY(&sq->mousebinds)) + SLIST_FOREACH(m, &sq->mousebinds, snext) + { + m->area = sq->geo; + m->area.y -= sq->geo.h; + } break; /* Rectangle */ - case 'r': + case 'R': if(sq->align != NoAlign) sq->geo.y = (e->geo.h >> 1) - (sq->geo.h >> 1); - if(sq->align == Left) - { - sq->geo.x = left; - left += sq->geo.w; - } - else if(sq->align == Right) - { - sq->geo.x = e->geo.w - right - sq->geo.w; - right += sq->geo.w; - } - + STATUS_ALIGN(sq->align); draw_rect(b->dr, sq->geo, sq->color); - if(sq->mousebind) - sq->mousebind->area = sq->geo; + if(!SLIST_EMPTY(&sq->mousebinds)) + SLIST_FOREACH(m, &sq->mousebinds, snext) + m->area = sq->geo; break; } @@ -244,8 +225,6 @@ status_manage(struct element *e) struct mousebind *m; struct barwin *b = SLIST_FIRST(&e->bars); - SLIST_INIT(&e->infobar->statushead); - /* * Flush previous linked list of status sequences * and mousebind of status barwin diff --git a/src/util.c b/src/util.c index f8f779f..67e8328 100644 --- a/src/util.c +++ b/src/util.c @@ -121,6 +121,23 @@ spawn(const char *format, ...) return pid; } +int +parse_args(char *str, char delim, char end, int narg, char *args[]) +{ + int i = 0; + + for(args[0] = str; *str && *str != end && i < narg; ++str) + if(*str == delim) + { + *str = '\0'; + args[++i] = ++str; + } + + *str = '\0'; + + return i; +} + void uicb_spawn(Uicb cmd) { diff --git a/src/util.h b/src/util.h index 7b3c64c..efc13e7 100644 --- a/src/util.h +++ b/src/util.h @@ -81,6 +81,7 @@ void *xcalloc(size_t nmemb, size_t size); int xasprintf(char **strp, const char *fmt, ...); char *xstrdup(const char *str); pid_t spawn(const char *format, ...); +int parse_args(char *str, char delim, char end, int narg, char *args[]); void uicb_spawn(Uicb cmd); #endif /* UTIL_H */ diff --git a/src/wmfs.h b/src/wmfs.h index 490c318..e979652 100644 --- a/src/wmfs.h +++ b/src/wmfs.h @@ -96,11 +96,11 @@ struct barwin struct status_seq { struct geo geo; - struct mousebind *mousebind; enum position align; char type; char *str; Color color; + SLIST_HEAD(, mousebind) mousebinds; SLIST_ENTRY(status_seq) next; }; @@ -212,6 +212,7 @@ struct mousebind void (*func)(Uicb); Uicb cmd; SLIST_ENTRY(mousebind) next; + SLIST_ENTRY(mousebind) snext; }; struct theme