From fb19fe2e49613ae280437459870cd0d4e404ed5c Mon Sep 17 00:00:00 2001 From: Matteo Signer Date: Sat, 9 Apr 2016 16:52:01 +0200 Subject: [PATCH 1/3] Add xbm support --- Makefile | 2 +- lemonbar.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 24800a5..06abaae 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ endif CC ?= gcc CFLAGS += -Wall -std=c99 -Os -DVERSION="\"$(VERSION)\"" -LDFLAGS += -lxcb -lxcb-xinerama -lxcb-randr +LDFLAGS += -lxcb -lxcb-xinerama -lxcb-randr -lxcb-image CFDEBUG = -g3 -pedantic -Wall -Wunused-parameter -Wlong-long \ -Wsign-conversion -Wconversion -Wimplicit-function-declaration diff --git a/lemonbar.c b/lemonbar.c index 2198731..86d0116 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -13,6 +13,7 @@ #include #include #include +#include // Here be dragons @@ -60,6 +61,12 @@ typedef struct area_stack_t { area_t *area; } area_stack_t; +typedef struct xbm_icon_t { + int width, height; + char *filename; + xcb_image_t* image; +} xbm_icon_t; + enum { ATTR_OVERL = (1<<0), ATTR_UNDERL = (1<<1), @@ -98,6 +105,11 @@ static rgba_t fgc, bgc, ugc; static rgba_t dfgc, dbgc, dugc; static area_stack_t area_stack; +#define ICON_CACHE_SIZE 256 +static int icon_count = 0; +static int icon_index = 0; +static xbm_icon_t* icon_cache[ICON_CACHE_SIZE]; + void update_gc (void) { @@ -231,6 +243,134 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, uint16_t ch) return ch_width; } +xbm_icon_t* load_xbm(char* filename) { + for (int i=0; ifilename, filename) == 0) { + return icon_cache[i]; + } + } + FILE *f = NULL; + f = fopen(filename, "r"); + if (!f) + return NULL; + + int width = -1; + int height = -1; + + char line[256]; + char define_name[256]; + int value; + while (fgets(line, sizeof(line), f)) { + if (line[0] == '\n') continue; + if (sscanf(line, "#define %s %d", define_name, &value) == 2) { + char *type = strrchr(define_name, '_'); + if (type) + type++; + else + type = define_name; + + if (strcmp(type, "width") == 0) + width = value; + if (strcmp(type, "height") == 0) + height = value; + + continue; + } + if (width <= 0 || height <= 0) { + fclose(f); + return NULL; + } + if ( + sscanf(line, "static const unsigned char %s = {", define_name) == 1|| + sscanf(line, "static unsigned char %s = {", define_name) == 1|| + sscanf(line, "static const char %s = {", define_name) == 1|| + sscanf(line, "static char %s = {", define_name) == 1 + ) { + } else { + fclose(f); + return NULL; + } + + //const int n = (width/8 + (width%8) ? 1 : 0) * height; + xbm_icon_t *icon = calloc(1, sizeof(xbm_icon_t)); + icon->width = width; + icon->height = height; + icon->filename = calloc(strlen(filename), sizeof(char)); + if (icon->filename == NULL) { + exit(1); + } + strcpy(icon->filename, filename); + + xcb_image_t *img = xcb_image_create_native(c, width, height, XCB_IMAGE_FORMAT_XY_BITMAP, 1, NULL, ~0, NULL); + img->data = calloc(1, img->size); + if (img->data == NULL) { + exit(1); + } + + for (int y = 0; y < height; y ++) { + for (int x = 0; x < width; x+= 8) { + if (x != 0 || y != 0) + fgetc(f); + int val; + if (fscanf(f, "%x", &val)) { + + } else { + xcb_image_destroy(img); + free(icon); + fclose(f); + return NULL; + } + for (int x2 = x; x2 < width && x2 < x + 8; x2++) { + bool pix = (val >> (x2%8)) & 1; + xcb_image_put_pixel(img, x2, y, pix); + } + } + } + icon->image = img; + + if (icon_count < ICON_CACHE_SIZE) + icon_count++; + icon_cache[icon_index] = icon; + icon_index++; + icon_index %= ICON_CACHE_SIZE; + fclose(f); + return icon; + } + // Instruction pointer modifiecd by cosmic rays + return NULL; +} + +int +draw_icon (monitor_t *mon, int x, int align, char *filename) +{ + xbm_icon_t *icon = load_xbm(filename); + if (icon == NULL) + return 0; + int icon_width = icon->width; + + + switch (align) { + case ALIGN_C: + xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], + mon->width / 2 - x / 2, 0, + mon->width / 2 - (x + icon_width) / 2, 0, + x, bh); + x = mon->width / 2 - (x + icon_width) / 2 + x; + break; + case ALIGN_R: + xcb_copy_area(c, mon->pixmap, mon->pixmap, gc[GC_DRAW], + mon->width - x, 0, + mon->width - x - icon_width, 0, + x, bh); + x = mon->width - icon_width; + break; + } + + fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, icon->width, bh); + xcb_image_put(c, mon->pixmap, gc[GC_DRAW], icon->image, x, (bh-icon->height) / 2, 0); + return 0; +} + rgba_t parse_color (const char *str, char **end, const rgba_t def) { @@ -509,6 +649,17 @@ parse (char *text) case 'c': pos_x = 0; align = ALIGN_C; break; case 'r': pos_x = 0; align = ALIGN_R; break; + case 'I': + if (block_end-p > 255) + break; + char filename[256]; + strncpy(filename, p, block_end-p); + int icon_width = draw_icon(cur_mon, pos_x, align, filename); + pos_x += icon_width; + area_shift(cur_mon->window, align, icon_width); + + break; + case 'A': button = XCB_BUTTON_INDEX_1; // The range is 1-5 From c2716d9af9d1bfb44aba7cb8c07472d0e1f96b54 Mon Sep 17 00:00:00 2001 From: Matteo Signer Date: Sat, 9 Apr 2016 17:52:51 +0200 Subject: [PATCH 2/3] Fix background --- lemonbar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lemonbar.c b/lemonbar.c index 86d0116..1c1e846 100644 --- a/lemonbar.c +++ b/lemonbar.c @@ -114,6 +114,7 @@ void update_gc (void) { xcb_change_gc(c, gc[GC_DRAW], XCB_GC_FOREGROUND, (const uint32_t []){ fgc.v }); + xcb_change_gc(c, gc[GC_DRAW], XCB_GC_BACKGROUND, (const uint32_t []){ bgc.v }); xcb_change_gc(c, gc[GC_CLEAR], XCB_GC_FOREGROUND, (const uint32_t []){ bgc.v }); xcb_change_gc(c, gc[GC_ATTR], XCB_GC_FOREGROUND, (const uint32_t []){ ugc.v }); } @@ -368,7 +369,7 @@ draw_icon (monitor_t *mon, int x, int align, char *filename) fill_rect(mon->pixmap, gc[GC_CLEAR], x, by, icon->width, bh); xcb_image_put(c, mon->pixmap, gc[GC_DRAW], icon->image, x, (bh-icon->height) / 2, 0); - return 0; + return icon_width; } rgba_t @@ -654,6 +655,7 @@ parse (char *text) break; char filename[256]; strncpy(filename, p, block_end-p); + filename[block_end-p] = '\0'; int icon_width = draw_icon(cur_mon, pos_x, align, filename); pos_x += icon_width; area_shift(cur_mon->window, align, icon_width); @@ -1302,7 +1304,7 @@ init (char *wm_name) // Create the gc for drawing gc[GC_DRAW] = xcb_generate_id(c); - xcb_create_gc(c, gc[GC_DRAW], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ fgc.v }); + xcb_create_gc(c, gc[GC_DRAW], monhead->pixmap, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t []){ fgc.v, bgc.v }); gc[GC_CLEAR] = xcb_generate_id(c); xcb_create_gc(c, gc[GC_CLEAR], monhead->pixmap, XCB_GC_FOREGROUND, (const uint32_t []){ bgc.v }); From 246ac3bc51222171505299965d09ff28c029141d Mon Sep 17 00:00:00 2001 From: Matteo Signer Date: Sat, 9 Apr 2016 17:56:41 +0200 Subject: [PATCH 3/3] Update README --- README.pod | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.pod b/README.pod index dc7307a..c72e282 100644 --- a/README.pod +++ b/README.pod @@ -105,6 +105,10 @@ Set the font used to draw the following text. The parameter I can either Set the text underline color. The parameter I can be I<-> or a color in one of the formats mentioned before. The special value I<-> resets the color to the default one. +=item BI + +Draw the icon specified by I. The icon must be in xbm format. + =item BI