Work on status: Add \s[]\ \r[]\ sequences for text & rectangle

This commit is contained in:
Martin Duquesnoy 2012-01-09 19:35:57 +01:00
parent 2a47c21c01
commit f6c0bc8a6c
4 changed files with 232 additions and 10 deletions

View File

@ -8,21 +8,216 @@
#include "infobar.h"
#include "util.h"
#include <string.h>
/* Parse arg;between;semicolon */
#define STATUS_GET_ARGS(i, inc, p, arg, n) \
do { \
for(i = 0, p += inc, arg[0] = p; *p && *p != ']' && i < n; ++p) \
if(*p == ';') \
{ \
*p = '\0'; \
arg[++i] = ++p; \
} \
*p = '\0'; \
} while(/* CONSTCOND */ 0);
#define STATUS_CHECK_END(str, end, p) \
if(!(end = strstr(p, "]\\"))) \
{ \
str = end + 2; \
continue; \
}
#define STATUS_CHECK_ARGS(i, n1, n2, str, end) \
if(i != n1 && i != n2) \
{ \
str = end + 2; \
continue; \
}
/* Alloc & fill status_sq struct with universal options: align/position and type */
#define STATUS_FILL_SQ(sq, t, shift, arg) \
do { \
sq = xcalloc(1, sizeof(struct status_seq)); \
sq->type = t; \
\
if(!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); \
/** Check text blocks in str and list it
* --> \s[left/right;#color;text]\ OR \s[x;y;#color;text]\
*\param ib Infobar pointer
*\param str String
*/
static void
status_text(struct infobar *ib, char *str)
{
struct status_seq *sq;
int i;
char *dstr = xstrdup(str), *sauv = dstr;
char *p, *end;
while((p = strstr(dstr, "\\s[")))
{
char *arg[5] = { NULL };
int shift = 0;
STATUS_CHECK_END(dstr, end, p);
STATUS_GET_ARGS(i, 3, p, arg, 4);
STATUS_CHECK_ARGS(i, 2, 3, dstr, end);
STATUS_FILL_SQ(sq, 's', shift, arg);
/* string sequence options */
sq->color = color_atoh(arg[1 + shift]);
sq->str = xstrdup(arg[2 + shift]);
SLIST_INSERT_HEAD(&ib->statushead, sq, next);
dstr = end + 2;
}
free(sauv);
}
/** Check rectangle blocks in str and list it
* --> \s[left/right;width;height;#color]\ OR \s[x;y;width;height;#color]\
*\param ib Infobar pointer
*\param str String
*/
static void
status_rect(struct infobar *ib, char *str)
{
struct status_seq *sq;
int i;
char *dstr = xstrdup(str), *sauv = dstr;
char *p, *end;
while((p = strstr(dstr, "\r[")))
{
char *arg[6] = { NULL };
int shift = 0;
STATUS_CHECK_END(dstr, end, p);
STATUS_GET_ARGS(i, 2, p, arg, 5);
STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
STATUS_FILL_SQ(sq, 'r', shift, arg);
/* rectangle sequence options */
sq->geo.w = ATOI(arg[1 + shift]);
sq->geo.h = ATOI(arg[2 + shift]);
sq->color = color_atoh(arg[3 + shift]);
SLIST_INSERT_HEAD(&ib->statushead, sq, next);
dstr = end + 2;
}
free(sauv);
}
static void
status_apply_list(struct element *e)
{
struct status_seq *sq;
struct barwin *b = SLIST_FIRST(&e->bars);
int left = 0, right = 0;
int l;
SLIST_FOREACH(sq, &e->infobar->statushead, next)
{
switch(sq->type)
{
/* Text */
case 's':
if(sq->align == NoAlign)
draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
else if(sq->align == Left)
{
draw_text(b->dr, e->infobar->theme, left, TEXTY(e->infobar->theme, e->geo.h), sq->color, sq->str);
left += draw_textw(e->infobar->theme, sq->str);
}
else if(sq->align == Right)
{
l = draw_textw(e->infobar->theme, sq->str);
draw_text(b->dr, e->infobar->theme, e->geo.w - right - l,
TEXTY(e->infobar->theme, e->geo.h), sq->color, sq->str);
right += l;
}
break;
/* Rectangle */
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;
}
draw_rect(b->dr, sq->geo, sq->color);
break;
}
}
}
void
status_manage(struct element *e)
{
struct status_seq *sq;
struct barwin *b = SLIST_FIRST(&e->bars);
int l;
SLIST_INIT(&e->infobar->statushead);
/* Flush previous linked list of status sequences */
while(!SLIST_EMPTY(&e->infobar->statushead))
{
sq = SLIST_FIRST(&e->infobar->statushead);
SLIST_REMOVE_HEAD(&e->infobar->statushead, next);
free(sq->str);
free(sq);
}
if(!e->infobar->status)
return;
barwin_refresh_color(b);
if(e->infobar->status)
{
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);
barwin_refresh(b);
}
status_text(e->infobar, e->infobar->status);
status_rect(e->infobar, e->infobar->status);
/* DEBUG
SLIST_FOREACH(sq, &e->infobar->statushead, next)
printf("-> %c (%d;%d)x(%d;%d) (%d) (#%x) (%s)\n",
sq->type, sq->geo.x, sq->geo.y, sq->geo.w, sq->geo.h, sq->align, sq->color, sq->str);
*/
status_apply_list(e);
/*
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);
*/
barwin_refresh(b);
}
/* Syntax: "<infobar name> <status string>" */

View File

@ -76,8 +76,8 @@ xstrdup(const char *str)
{
char *ret;
if (str == NULL || (ret = strdup(str)) == NULL)
err(EXIT_FAILURE, "strdup(%s)", str);
if(str == NULL || (ret = strdup(str)) == NULL)
warnx("strdup(%s)", str);
return ret;
}

View File

@ -8,6 +8,8 @@
#include "wmfs.h"
#include <string.h>
/* Todo FREE_LIST(type, head, function_remove) */
#define FREE_LIST(type, head) \
do { \
@ -54,6 +56,19 @@ swap_ptr(void **x, void **y)
*y = t;
}
static inline enum position
str_to_position(char *str)
{
enum position i;
static const char index[PositionLast][8] = { "right", "left", "top", "bottom", "center" };
for(i = 0; i < PositionLast; ++i)
if(!strcmp(index[i], str))
return i;
return Right;
}
void *xmalloc(size_t nmemb, size_t size);
void *xcalloc(size_t nmemb, size_t size);
int xasprintf(char **strp, const char *fmt, ...);

View File

@ -46,6 +46,7 @@ enum position
Top,
Bottom,
Center,
NoAlign,
PositionLast
};
@ -92,6 +93,16 @@ struct barwin
SLIST_ENTRY(barwin) enext; /* element barwin */
};
struct status_seq
{
struct geo geo;
enum position align;
char type;
char *str;
Color color;
SLIST_ENTRY(status_seq) next;
};
struct element
{
struct geo geo;
@ -115,6 +126,7 @@ struct infobar
char *name;
char *status;
TAILQ_HEAD(esub, element) elements;
SLIST_HEAD(, status_seq) statushead;
SLIST_ENTRY(infobar) next;
};