[draw] Use g_markup API to parse bg elements
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
dd9cb9810b
commit
a3b1b3be0b
159
common/draw.c
159
common/draw.c
|
@ -211,58 +211,96 @@ draw_font_delete(font_t **font)
|
||||||
p_delete(font);
|
p_delete(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
typedef struct
|
||||||
draw_text_markup_expand(xcb_connection_t *conn,
|
|
||||||
int phys_screen,
|
|
||||||
const char *str, ssize_t slen,
|
|
||||||
xcolor_t **bg_color)
|
|
||||||
{
|
{
|
||||||
const char *ps;
|
xcb_connection_t *connection;
|
||||||
char *bg, *bg_end, *bg_str, *color, *col_end, *col_str, *new;
|
int phys_screen;
|
||||||
ssize_t len;
|
char *text;
|
||||||
|
bool has_bg_color;
|
||||||
|
xcolor_t bg_color;
|
||||||
|
} draw_parser_data_t;
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_text_markup_parse_start_element(GMarkupParseContext *context __attribute__ ((unused)),
|
||||||
|
const gchar *element_name,
|
||||||
|
const gchar **attribute_names,
|
||||||
|
const gchar **attribute_values,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
draw_parser_data_t *p = (draw_parser_data_t *) user_data;
|
||||||
|
const char **tmp;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if((bg = strstr(str, "<bg "))
|
if(!a_strcmp(element_name, "bg"))
|
||||||
&& ((bg_end = strstr(bg, "/>"))))
|
for(tmp = attribute_names; *tmp; tmp++, i++)
|
||||||
{
|
if(!p->has_bg_color && !a_strcmp(*tmp, "color"))
|
||||||
len = bg_end - bg + 1;
|
p->has_bg_color = draw_color_new(p->connection, p->phys_screen,
|
||||||
bg_str = p_new(char, len);
|
attribute_values[i], &p->bg_color);
|
||||||
/* strncpy(bg_str, len, bg + len of '<bg ', everything * exclude >) */
|
}
|
||||||
a_strncpy(bg_str, len, bg + 4, len - 5);
|
|
||||||
|
|
||||||
if(bg_color && (color = strstr(bg_str, "color=")))
|
static void
|
||||||
{
|
draw_text_markup_parse_text(GMarkupParseContext *context __attribute__ ((unused)),
|
||||||
color += 6;
|
const gchar *text,
|
||||||
if(color[0] == '"')
|
gsize text_len,
|
||||||
color++;
|
gpointer user_data,
|
||||||
for(col_end = color; *col_end && (*col_end == '#' || isalnum(*col_end)); col_end++);
|
GError **error __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
draw_parser_data_t *p = (draw_parser_data_t *) user_data;
|
||||||
|
ssize_t len, rlen;
|
||||||
|
|
||||||
col_str = a_strndup(color, col_end - color);
|
len = a_strlen(p->text);
|
||||||
|
rlen = len + 1 + text_len;
|
||||||
if((len = a_strlen(col_str)))
|
p_realloc(&p->text, rlen);
|
||||||
{
|
if(len)
|
||||||
if(col_str[len - 1] == '"')
|
a_strncat(p->text, rlen, text, len);
|
||||||
col_str[--len] = '\0';
|
|
||||||
*bg_color = p_new(xcolor_t, 1);
|
|
||||||
if(!draw_color_new(conn, phys_screen, col_str, *bg_color))
|
|
||||||
p_delete(bg_color);
|
|
||||||
}
|
|
||||||
p_delete(&col_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copy string without <bg> */
|
|
||||||
new = p_new(char, slen - (bg_end - bg));
|
|
||||||
for(ps = str; *ps; ps++)
|
|
||||||
/* if before <bg and after /> */
|
|
||||||
if(ps < bg || ps > (bg_end + 1))
|
|
||||||
new[i++] = *ps;
|
|
||||||
|
|
||||||
p_delete(&bg_str);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
new = a_strdup(str);
|
a_strncpy(p->text, rlen, text, text_len);
|
||||||
|
}
|
||||||
|
|
||||||
return new;
|
static bool
|
||||||
|
draw_text_markup_expand(draw_parser_data_t *data,
|
||||||
|
const char *str, ssize_t slen)
|
||||||
|
{
|
||||||
|
GMarkupParseContext *mkp_ctx;
|
||||||
|
GMarkupParser parser =
|
||||||
|
{
|
||||||
|
/* start_element */
|
||||||
|
draw_text_markup_parse_start_element,
|
||||||
|
/* end_element */
|
||||||
|
NULL,
|
||||||
|
/* text */
|
||||||
|
draw_text_markup_parse_text,
|
||||||
|
/* passthrough */
|
||||||
|
NULL,
|
||||||
|
/* error */
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
GError *error = NULL;
|
||||||
|
char *text;
|
||||||
|
ssize_t len = 18 + slen;
|
||||||
|
|
||||||
|
/* parsed text must begin with an element */
|
||||||
|
text = p_new(char, len);
|
||||||
|
a_strcpy(text, len, "<markup>");
|
||||||
|
a_strcat(text, len, str);
|
||||||
|
a_strcat(text, len, "</markup>");
|
||||||
|
|
||||||
|
mkp_ctx = g_markup_parse_context_new(&parser, 0, data, NULL);
|
||||||
|
|
||||||
|
if(!g_markup_parse_context_parse(mkp_ctx, text, len - 1, &error))
|
||||||
|
{
|
||||||
|
warn("unable to parse text: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_markup_parse_context_end_parse(mkp_ctx, &error);
|
||||||
|
|
||||||
|
g_markup_parse_context_free(mkp_ctx);
|
||||||
|
p_delete(&text);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Draw text into a draw context
|
/** Draw text into a draw context
|
||||||
|
@ -290,6 +328,7 @@ draw_text(DrawCtx *ctx,
|
||||||
char *buf = NULL, *utf8 = NULL;
|
char *buf = NULL, *utf8 = NULL;
|
||||||
xcolor_t *bg_color = NULL;
|
xcolor_t *bg_color = NULL;
|
||||||
PangoRectangle ext;
|
PangoRectangle ext;
|
||||||
|
draw_parser_data_t parser_data;
|
||||||
|
|
||||||
if(!(len = a_strlen(text)))
|
if(!(len = a_strlen(text)))
|
||||||
return;
|
return;
|
||||||
|
@ -300,15 +339,22 @@ draw_text(DrawCtx *ctx,
|
||||||
else
|
else
|
||||||
utf8 = a_strdup(text);
|
utf8 = a_strdup(text);
|
||||||
|
|
||||||
buf = draw_text_markup_expand(ctx->connection, ctx->phys_screen,
|
bzero(&parser_data, sizeof(parser_data));
|
||||||
utf8, len, &bg_color);
|
parser_data.connection = ctx->connection;
|
||||||
p_delete(&utf8);
|
parser_data.phys_screen = ctx->phys_screen;
|
||||||
|
if(draw_text_markup_expand(&parser_data, utf8, len))
|
||||||
|
{
|
||||||
|
buf = parser_data.text;
|
||||||
|
p_delete(&utf8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf = utf8;
|
||||||
|
|
||||||
len = olen = a_strlen(buf);
|
len = olen = a_strlen(buf);
|
||||||
|
|
||||||
if(bg_color)
|
if(parser_data.has_bg_color)
|
||||||
{
|
{
|
||||||
draw_rectangle(ctx, area, 1.0, true, *bg_color);
|
draw_rectangle(ctx, area, 1.0, true, parser_data.bg_color);
|
||||||
p_delete(&bg_color);
|
p_delete(&bg_color);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -923,6 +969,7 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
|
||||||
area_t geom = { 0, 0, 0, 0, NULL, NULL };
|
area_t geom = { 0, 0, 0, 0, NULL, NULL };
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
char *buf, *utf8;
|
char *buf, *utf8;
|
||||||
|
draw_parser_data_t parser_data;
|
||||||
|
|
||||||
if(!(len = a_strlen(text)))
|
if(!(len = a_strlen(text)))
|
||||||
return geom;
|
return geom;
|
||||||
|
@ -933,8 +980,16 @@ draw_text_extents(xcb_connection_t *conn, int default_screen, font_t *font, cons
|
||||||
else
|
else
|
||||||
utf8 = a_strdup(text);
|
utf8 = a_strdup(text);
|
||||||
|
|
||||||
buf = draw_text_markup_expand(conn, default_screen, utf8, len, NULL);
|
bzero(&parser_data, sizeof(parser_data));
|
||||||
p_delete(&utf8);
|
parser_data.connection = conn;
|
||||||
|
parser_data.phys_screen = default_screen;
|
||||||
|
if(draw_text_markup_expand(&parser_data, utf8, len))
|
||||||
|
{
|
||||||
|
buf = parser_data.text;
|
||||||
|
p_delete(&utf8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
buf = utf8;
|
||||||
|
|
||||||
len = a_strlen(buf);
|
len = a_strlen(buf);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue