aboutsummaryrefslogtreecommitdiff
path: root/dwlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwlb.c')
-rw-r--r--dwlb.c167
1 files changed, 119 insertions, 48 deletions
diff --git a/dwlb.c b/dwlb.c
index 3b3fb35..947db65 100644
--- a/dwlb.c
+++ b/dwlb.c
@@ -150,6 +150,73 @@ allocate_shm_file(size_t size)
return fd;
}
+/* Color parsing logic adapted from [sway] */
+static int
+parse_color(const char *str, pixman_color_t *clr)
+{
+ if (*str == '#')
+ str++;
+ int len = strlen(str);
+
+ // Disallows "0x" prefix that strtoul would ignore
+ if ((len != 6 && len != 8) || !isxdigit(str[0]) || !isxdigit(str[1]))
+ return -1;
+
+ char *ptr;
+ uint32_t parsed = strtoul(str, &ptr, 16);
+ if (*ptr)
+ return -1;
+
+ if (len == 8) {
+ clr->alpha = (parsed & 0xff) * 0x101;
+ parsed >>= 8;
+ } else {
+ clr->alpha = 0xffff;
+ }
+ clr->red = ((parsed >> 16) & 0xff) * 0x101;
+ clr->green = ((parsed >> 8) & 0xff) * 0x101;
+ clr->blue = ((parsed >> 0) & 0xff) * 0x101;
+ return 0;
+}
+
+static char *
+handle_cmd(char *cmd, pixman_color_t *fg, pixman_color_t *bg,
+ pixman_color_t *def_fg, pixman_color_t *def_bg)
+{
+ char *arg, *end;
+
+ if (!(arg = strchr(cmd, '(')) || !(end = strchr(arg + 1, ')')))
+ return cmd;
+
+ *arg++ = '\0';
+ *end = '\0';
+
+ if (!strcmp(cmd, "bg")) {
+ if (bg && def_bg) {
+ if (!*arg) {
+ *bg = *def_bg;
+ } else if (parse_color(arg, bg)) {
+ fprintf(stderr, "Bad color string \"%s\"\n", arg);
+ }
+ }
+ } else if (!strcmp(cmd, "fg")) {
+ if (fg && def_fg) {
+ if (!*arg) {
+ *fg = *def_fg;
+ } else if (parse_color(arg, fg)) {
+ fprintf(stderr, "Bad color string \"%s\"\n", arg);
+ }
+ }
+ } else {
+ fprintf(stderr, "Unrecognized command \"%s\"\n", cmd);
+ }
+
+ /* Restore string for later redraws */
+ *--arg = '(';
+ *end = ')';
+ return end;
+}
+
static uint32_t
draw_text(char *text,
uint32_t xpos,
@@ -158,26 +225,51 @@ draw_text(char *text,
pixman_image_t *background,
pixman_color_t *fgcolor,
pixman_color_t *bgcolor,
- uint32_t max_x,
+ uint32_t surface_width,
uint32_t height,
- uint32_t padding)
+ uint32_t padding,
+ bool commands)
{
uint32_t codepoint;
uint32_t state = UTF8_ACCEPT;
uint32_t ixpos = xpos;
uint32_t nxpos;
uint32_t lastcp = 0;
- pixman_image_t *fgfill = pixman_image_create_solid_fill(fgcolor);
-
- if (!*text)
- return xpos;
- if ((nxpos = xpos + padding) > max_x)
+ if (!*text || !surface_width || xpos >= surface_width)
return xpos;
+ if ((nxpos = xpos + padding) >= surface_width)
+ return xpos;
xpos = nxpos;
+ pixman_color_t cur_fgcolor = *fgcolor;
+ pixman_color_t cur_bgcolor;
+ if (background && bgcolor) {
+ cur_bgcolor = *bgcolor;
+ pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
+ &cur_bgcolor, 1, &(pixman_box32_t){
+ .x1 = ixpos,
+ .x2 = xpos,
+ .y1 = 0,
+ .y2 = height
+ });
+ }
+
+ pixman_image_t *fgfill = pixman_image_create_solid_fill(fgcolor);
+
for (char *p = text; *p; p++) {
+ /* Check for inline ^ commands */
+ if (commands && state == UTF8_ACCEPT && *p == '^') {
+ p++;
+ if (*p != '^') {
+ p = handle_cmd(p, &cur_fgcolor, &cur_bgcolor, fgcolor, bgcolor);
+ pixman_image_unref(fgfill);
+ fgfill = pixman_image_create_solid_fill(&cur_fgcolor);
+ continue;
+ }
+ }
+
/* Returns nonzero if more bytes are needed */
if (utf8decode(&state, &codepoint, *p))
continue;
@@ -192,13 +284,11 @@ draw_text(char *text,
long x_kern = 0;
if (lastcp)
fcft_kerning(font, lastcp, codepoint, &x_kern, NULL);
-
- if ((nxpos = xpos + x_kern + glyph->advance.x) > max_x) {
+ if ((nxpos = xpos + x_kern + glyph->advance.x) >= surface_width) {
if (!lastcp)
return ixpos;
break;
}
-
xpos += x_kern;
lastcp = codepoint;
@@ -219,6 +309,15 @@ draw_text(char *text,
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height);
}
+ if (background && bgcolor)
+ pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
+ &cur_bgcolor, 1, &(pixman_box32_t){
+ .x1 = xpos,
+ .x2 = nxpos,
+ .y1 = 0,
+ .y2 = height
+ });
+
/* increment pen position */
xpos = nxpos;
ypos += glyph->advance.y;
@@ -227,17 +326,18 @@ draw_text(char *text,
if (state != UTF8_ACCEPT)
fprintf(stderr, "malformed UTF-8 sequence\n");
- xpos = MIN(xpos + padding, max_x);
+ nxpos = MIN(xpos + padding, surface_width - 1);
if (background && bgcolor)
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
bgcolor, 1, &(pixman_box32_t){
- .x1 = ixpos,
- .x2 = xpos,
+ .x1 = xpos,
+ .x2 = nxpos,
.y1 = 0,
.y2 = height
});
-
+ xpos = nxpos;
+
pixman_image_unref(fgfill);
return xpos;
@@ -304,21 +404,21 @@ draw_frame(Bar *b)
if (urgent)
xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left,
- &urgtextcolor, &urgbgcolor, b->width, b->height, b->textpadding);
+ &urgtextcolor, &urgbgcolor, b->width, b->height, b->textpadding, false);
else
xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left,
- &textcolor, active ? &activecolor : &inactivecolor, b->width, b->height, b->textpadding);
+ &textcolor, active ? &activecolor : &inactivecolor, b->width, b->height, b->textpadding, false);
}
xpos_left = draw_text(b->layout, xpos_left, ypos, foreground_left, background_left,
- &textcolor, &inactivecolor, b->width, b->height, b->textpadding);
+ &textcolor, &inactivecolor, b->width, b->height, b->textpadding, false);
xpos_right = draw_text(b->status, 0, ypos, foreground_right, background_right,
- &textcolor, &inactivecolor, b->width, b->height, b->textpadding);
+ &textcolor, &inactivecolor, b->width, b->height, b->textpadding, true);
if (xpos_right > b->width)
xpos_right = b->width;
draw_text(b->title, 0, ypos, foreground_title, NULL,
- &textcolor, NULL, b->width, b->height, b->textpadding);
+ &textcolor, NULL, b->width, b->height, b->textpadding, false);
/* Draw background and foreground on bar */
pixman_image_composite32(PIXMAN_OP_OVER, foreground_title, NULL, bar, 0, 0, 0, 0, xpos_left, 0, b->width, b->height);
@@ -722,35 +822,6 @@ client_send_command(struct sockaddr_un *sock_address,
closedir(dir);
}
-/* Color parsing logic adapted from [sway] */
-static int
-parse_color(const char *str, pixman_color_t *clr)
-{
- if (*str == '#')
- str++;
- int len = strlen(str);
-
- // Disallows "0x" prefix that strtoul would ignore
- if ((len != 6 && len != 8) || !isxdigit(str[0]) || !isxdigit(str[1]))
- return -1;
-
- char *ptr;
- uint32_t parsed = strtoul(str, &ptr, 16);
- if (*ptr)
- return -1;
-
- if (len == 8) {
- clr->alpha = (parsed & 0xff) * 0x101;
- parsed >>= 8;
- } else {
- clr->alpha = 0xffff;
- }
- clr->red = ((parsed >> 16) & 0xff) * 0x101;
- clr->green = ((parsed >> 8) & 0xff) * 0x101;
- clr->blue = ((parsed >> 0) & 0xff) * 0x101;
- return 0;
-}
-
void
sig_handler(int sig)
{