diff --git a/README.md b/README.md index 8235b39..fe05782 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ b(ar) a(in't) r(ecursive) 2012 (C) The Lemon Man A lightweight bar based on XCB (yay). Provides foreground/background color -switching along with text alignment (screw you dzen!), nothing less and -nothing more. +switching along with text alignment (screw you dzen!), full utf8 support +and reduced memory footprint. Nothing less and nothing more. Options ------- @@ -43,7 +43,7 @@ To draw a backslash just backslash escape it (\\\\). f<0-9> Selects the text foreground color from the palette. b<0-9> Selects the text background color from the palette. u<0-9> Selects the underline color from the palette. - To reset the bg/fg color just pass 'r' as color index. + To reset the bg/fg/underline color just pass 'r' as the color index. l Aligns the text to the left. c Aligns the text to the center. diff --git a/bar.c b/bar.c index c6d5677..0740f4c 100644 --- a/bar.c +++ b/bar.c @@ -16,12 +16,12 @@ #define MAX(a,b) ((a > b) ? a : b) typedef struct fontset_item_t { - xcb_font_t xcb_ft; - int height; - int width; - int descent; - unsigned short char_max; - unsigned short char_min; + xcb_font_t xcb_ft; + xcb_query_font_reply_t *info; + xcb_charinfo_t *table; + int avg_height; + unsigned short char_max; + unsigned short char_min; } fontset_item_t; enum { @@ -54,7 +54,6 @@ xcb_set_bg (int i) { xcb_change_gc (c, draw_gc , XCB_GC_BACKGROUND, (const unsigned []){ palette[i] }); xcb_change_gc (c, clear_gc , XCB_GC_FOREGROUND, (const unsigned []){ palette[i] }); - xcb_change_gc (c, underl_gc, XCB_GC_FOREGROUND, (const unsigned []){ palette[i] }); } void @@ -85,34 +84,44 @@ xcb_set_fontset (int i) int draw_char (int x, int align, wchar_t ch) { + int ch_width; + + ch_width = (ch > sel_font->char_min && ch < sel_font->char_max) ? + sel_font->table[ch - sel_font->char_min].character_width : + 0; + + + if (ch_width == 0) + return 0; + switch (align) { case ALIGN_C: xcb_copy_area (c, canvas, canvas, draw_gc, bar_width / 2 - x / 2, 0, - bar_width / 2 - (x + sel_font->width) / 2, 0, x, BAR_HEIGHT); - x = bar_width / 2 - (x + sel_font->width) / 2 + x; + bar_width / 2 - (x + ch_width) / 2, 0, x, BAR_HEIGHT); + x = bar_width / 2 - (x + ch_width) / 2 + x; break; case ALIGN_R: xcb_copy_area (c, canvas, canvas, draw_gc, bar_width - x, 0, - bar_width - x - sel_font->width, 0, x, BAR_HEIGHT); - x = bar_width - sel_font->width; + bar_width - x - ch_width, 0, x, BAR_HEIGHT); + x = bar_width - ch_width; break; } /* Draw the background first */ - xcb_fill_rect (clear_gc, x, 0, sel_font->width, BAR_HEIGHT); - - /* Draw the underline */ - if (BAR_UNDERLINE_HEIGHT) - xcb_fill_rect (underl_gc, x, BAR_HEIGHT-BAR_UNDERLINE_HEIGHT, sel_font->width, BAR_UNDERLINE_HEIGHT); + xcb_fill_rect (clear_gc, x, 0, ch_width, BAR_HEIGHT); /* xcb accepts string in UCS-2 BE, so swap */ ch = (ch >> 8) | (ch << 8); /* String baseline coordinates */ - xcb_image_text_16 (c, 1, canvas, draw_gc, x, BAR_HEIGHT / 2 + sel_font->height / 2 - sel_font->descent, + xcb_image_text_16 (c, 1, canvas, draw_gc, x, BAR_HEIGHT / 2 + sel_font->avg_height / 2 - sel_font->info->font_descent, (xcb_char2b_t *)&ch); - return sel_font->width; + /* Draw the underline */ + if (BAR_UNDERLINE_HEIGHT) + xcb_fill_rect (underl_gc, x, BAR_UNDERLINE*(BAR_HEIGHT-BAR_UNDERLINE_HEIGHT), ch_width, BAR_UNDERLINE_HEIGHT); + + return ch_width; } void @@ -214,19 +223,17 @@ font_load (const char **font_list) font_info = xcb_query_font_reply (c, queryreq, NULL); fontset[i].xcb_ft = font; - fontset[i].width = font_info->max_bounds.character_width; - fontset[i].descent = font_info->font_descent; + fontset[i].table = xcb_query_font_char_infos (font_info); + fontset[i].info = font_info; fontset[i].char_max= font_info->max_byte1 << 8 | font_info->max_char_or_byte2; fontset[i].char_min= font_info->min_byte1 << 8 | font_info->min_char_or_byte2; max_height = MAX(font_info->font_ascent + font_info->font_descent, max_height); - - free (font_info); } /* To have an uniform alignment */ for (int i = 0; i < FONT_MAX; i++) - fontset[i].height = max_height; + fontset[i].avg_height = max_height; return 0; } @@ -258,12 +265,12 @@ set_ewmh_atoms (xcb_window_t root) reply = xcb_intern_atom_reply (c, cookies[4], NULL); atoms[4] = reply->atom; free (reply); - do { - reply1 = xcb_get_property_reply (c, xcb_get_property (c, 0, root, atoms[4], XCB_ATOM_ATOM, 0, -1), NULL); - } while (!xcb_get_property_value_length (reply1)); - compliance_lvl = 0; + reply1 = xcb_get_property_reply (c, xcb_get_property (c, 0, root, atoms[4], XCB_ATOM_ATOM, 0, -1), NULL); + if (!reply) + return compliance_lvl; + for (xcb_atom_t *a = xcb_get_property_value (reply1); a && a != xcb_get_property_value_end (reply1).data; a++) @@ -319,7 +326,7 @@ init (void) root = scr->root; /* Load the font */ - if (font_load ((const char* []){ BAR_MAIN_FONT, BAR_FALLBACK_FONT })) + if (font_load ((const char* []){ BAR_FONT })) exit (1); /* Create the main window */ @@ -360,10 +367,13 @@ init (void) void cleanup (void) { - if (fontset[FONT_MAIN].xcb_ft) - xcb_close_font (c, fontset[FONT_MAIN].xcb_ft); - if (fontset[FONT_FALLBACK].xcb_ft) - xcb_close_font (c, fontset[FONT_FALLBACK].xcb_ft); + int i; + for (i = 0; i < FONT_MAX; i++) { + if (fontset[i].info) + free (fontset[i].info); + if (fontset[i].xcb_ft) + xcb_close_font (c, fontset[i].xcb_ft); + } if (canvas) xcb_free_pixmap (c, canvas); if (win) diff --git a/config.def.h b/config.def.h index 422ffae..d81ce55 100644 --- a/config.def.h +++ b/config.def.h @@ -1,12 +1,13 @@ /* The height of the bar (in pixels) */ #define BAR_HEIGHT 18 -/* The thickness of the underline (in pixels) */ +/* Choose between an underline or an overline */ +#define BAR_UNDERLINE 1 +/* The thickness of the underline (in pixels). Set to 0 to disable. */ #define BAR_UNDERLINE_HEIGHT 2 /* Default bar position, overwritten by '-b' switch */ #define BAR_BOTTOM 0 -/* The font used for the bar */ -#define BAR_MAIN_FONT "-*-terminus-medium-r-normal-*-12-*-*-*-c-*-*-1" -#define BAR_FALLBACK_FONT "fixed" +/* The fonts used for the bar, comma separated. Only the first 2 will be used. */ +#define BAR_FONT "-*-terminus-medium-r-normal-*-12-*-*-*-c-*-*-1","fixed" /* Color palette */ #define COLOR0 0x1A1A1A /* background */ #define COLOR1 0xA9A9A9 /* foreground */