123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
- * For license, see COPYING.
- */
- #include "status.h"
- #include "barwin.h"
- #include "config.h"
- #include "infobar.h"
- #include "util.h"
- #include "draw.h"
- #include <string.h>
- 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));
- 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;
- }
- return sq;
- }
- /* Parse mousebind sequence next normal sequence: \<seq>[](button;func;cmd) */
- static char*
- status_parse_mouse(struct status_seq *sq, struct element *e, char *str)
- {
- struct mousebind *m;
- struct barwin *b = SLIST_FIRST(&e->bars);
- char *end, *arg[3] = { NULL };
- int i;
- if(*str != '(' || !(end = strchr(str, ')')))
- return str + 1;
- i = parse_args(++str, ';', ')', 3, arg);
- m = xcalloc(1, sizeof(struct mousebind));
- m->use_area = true;
- m->button = ATOI(arg[0]);
- m->func = uicb_name_func(arg[1]);
- m->cmd = (i > 1 ? xstrdup(arg[2]) : NULL);
- SLIST_INSERT_HEAD(&b->mousebinds, m, next);
- SLIST_INSERT_HEAD(&sq->mousebinds, m, snext);
- 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)
- {
- struct status_seq *sq, *prev = NULL;
- int i, shift = 0;
- char *dstr = xstrdup(e->infobar->status), *sauv = dstr;
- char type, *p, *end, *arg[6] = { NULL };
- for(; *dstr; ++dstr)
- {
- /* Check if this is a sequence */
- if(*dstr != '\\')
- continue;
- p = ++dstr;
- if(!(strchr("sRi", *p)) || !(end = strchr(p, ']')))
- continue;
- /* Then parse & list it */
- switch((type = *p))
- {
- /*
- * Text sequence: \s[left/right;#color;text] OR \s[x;y;#color;text]
- */
- case 's':
- i = parse_args(p + 2, ';', ']', 4, arg);
- STATUS_CHECK_ARGS(i, 2, 3, dstr, end);
- sq = status_new_seq(type, i, 2, arg, &shift);
- sq->color = color_atoh(arg[1 + shift]);
- sq->str = xstrdup(arg[2 + shift]);
- break;
- /*
- * Rectangle sequence: \R[left/right;w;h;#color] OR \R[x;y;w;h;#color]
- */
- case 'R':
- i = parse_args(p + 2, ';', ']', 5, arg);
- STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
- sq = status_new_seq(type, i, 3, arg, &shift);
- sq->geo.w = ATOI(arg[1 + shift]);
- sq->geo.h = ATOI(arg[2 + shift]);
- sq->color = color_atoh(arg[3 + shift]);
- break;
- /*
- * Image sequence: \i[left/right;w;h;/path/img] OR \i[x;y;w;h;/path/img]
- */
- #ifdef HAVE_IMLIB2
- case 'i':
- i = parse_args(p + 2, ';', ']', 5, arg);
- STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
- sq = status_new_seq(type, i, 3, arg, &shift);
- sq->geo.w = ATOI(arg[1 + shift]);
- sq->geo.h = ATOI(arg[2 + shift]);
- sq->str = xstrdup(arg[3 + shift]);
- break;
- #endif /* HAVE_IMLIB2 */
- }
- SLIST_INSERT_TAIL(&e->infobar->statushead, sq, next, prev);
- /*
- * Optional mousebind sequence(s) \<seq>[](button;func;cmd)
- * Parse it while there is a mousebind sequence.
- */
- dstr = ++end;
- while((*(dstr = status_parse_mouse(sq, e, dstr)) == '('));
- 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, w, h;
- SLIST_FOREACH(sq, &e->infobar->statushead, next)
- {
- switch(sq->type)
- {
- /* Text */
- case 's':
- sq->geo.w = draw_textw(e->infobar->theme, sq->str);
- sq->geo.h = e->infobar->theme->font.height;
- if(sq->align != NoAlign)
- sq->geo.y = TEXTY(e->infobar->theme, e->geo.h);
- STATUS_ALIGN(sq->align);
- draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
- 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':
- if(sq->align != NoAlign)
- sq->geo.y = (e->geo.h >> 1) - (sq->geo.h >> 1);
- STATUS_ALIGN(sq->align);
- draw_rect(b->dr, &sq->geo, sq->color);
- if(!SLIST_EMPTY(&sq->mousebinds))
- SLIST_FOREACH(m, &sq->mousebinds, snext)
- m->area = sq->geo;
- break;
- /* Image */
- #ifdef HAVE_IMLIB2
- case 'i':
- draw_image_get_size(sq->str, &w, &h);
- if(sq->geo.w <= 0)
- sq->geo.w = w;
- if(sq->geo.h <= 0)
- sq->geo.h = h;
- if(sq->align != NoAlign)
- sq->geo.y = (e->geo.h >> 1) - (sq->geo.h >> 1);
- STATUS_ALIGN(sq->align);
- draw_image(b->dr, &sq->geo, sq->str);
- if(!SLIST_EMPTY(&sq->mousebinds))
- SLIST_FOREACH(m, &sq->mousebinds, snext)
- m->area = sq->geo;
- break;
- #endif /* HAVE_IMLIB2 */
- }
- }
- }
- /* Render current statustext of an element */
- void
- status_render(struct element *e)
- {
- struct barwin *b = SLIST_FIRST(&e->bars);
- if(!e->infobar->status)
- return;
- barwin_refresh_color(b);
- /* Use simple text instead sequence if no sequence found */
- if(SLIST_EMPTY(&e->infobar->statushead))
- {
- int l = draw_textw(e->infobar->theme, e->infobar->status);
- draw_text(b->dr, e->infobar->theme, e->geo.w - l,
- TEXTY(e->infobar->theme, e->geo.h), b->fg, e->infobar->status);
- }
- else
- status_apply_list(e);
- barwin_refresh(b);
- }
- /* Parse and render statustext */
- void
- status_manage(struct element *e)
- {
- struct status_seq *sq;
- struct mousebind *m;
- struct barwin *b = SLIST_FIRST(&e->bars);
- /*
- * Flush previous linked list of status sequences
- * and mousebind of status barwin
- */
- while(!SLIST_EMPTY(&e->infobar->statushead))
- {
- sq = SLIST_FIRST(&e->infobar->statushead);
- SLIST_REMOVE_HEAD(&e->infobar->statushead, next);
- free(sq->str);
- free(sq);
- }
- while(!SLIST_EMPTY(&b->mousebinds))
- {
- m = SLIST_FIRST(&b->mousebinds);
- SLIST_REMOVE_HEAD(&b->mousebinds, next);
- free((void*)m->cmd);
- free(m);
- }
- status_parse(e);
- status_render(e);
- }
- /* Syntax: "<infobar name> <status string>" */
- void
- uicb_status(Uicb cmd)
- {
- struct infobar *ib;
- struct screen *s;
- char *p;
- if(!cmd || !(p = strchr(cmd, ' ')))
- return;
- /* Get infobar name & status */
- *p = '\0';
- ++p;
- SLIST_FOREACH(s, &W->h.screen, next)
- {
- SLIST_FOREACH(ib, &s->infobars, next)
- if(!strcmp(cmd, ib->name))
- {
- free(ib->status);
- ib->status = xstrdup(p);
- infobar_elem_screen_update(s, ElemStatus);
- }
- }
- }
|