From 828b5b5368bc5054b16a2504fcbb7a7e77087598 Mon Sep 17 00:00:00 2001 From: blastmaster Date: Sat, 16 Jul 2016 01:53:42 +0200 Subject: enabling colors for bmon This commit enables colors in bmon. It adds configuration options to let the user decide, which colors should be used. Therefor the graph_rx and graph_tx layouts are introduced and applied respectively. * Add graph_rx, graph_tx and layout_cfg fields. * Setting default colors if colorized output is enabled. * draw_table accept additional layout parameter and apply the given layout for the table graph. * Apply layouts for rx, tx graph and header and statusbar. * Add include/layout.h, which provides functions to parse, color and attribute strings and set the layout. * Adding a default layout-config example in examples/bmon.conf. [Edit: Based on original work by eri!, #PR23] --- examples/bmon.conf | 24 ++++++++++ include/bmon/conf.h | 2 + include/bmon/layout.h | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/conf.c | 100 ++++++++++++++++++++++++++++++++++----- src/out_curses.c | 17 ++++--- 5 files changed, 253 insertions(+), 18 deletions(-) create mode 100644 include/bmon/layout.h diff --git a/examples/bmon.conf b/examples/bmon.conf index 389b054..93d64c3 100644 --- a/examples/bmon.conf +++ b/examples/bmon.conf @@ -86,3 +86,27 @@ history day { interval = 86400. size = 60 } + +layout colors { + color default { + color_pair = {"white", "black"} + } + color statusbar { + color_pair = {"blue", "white", "reverse"} + } + color header { + color_pair = {"yellow", "black"} + } + color list { + color_pair = {"white", "black"} + } + color selected { + color_pair = {"white", "black", "reverse"} + } + color RX_graph { + color_pair = {"green", "black"} + } + color TX_graph { + color_pair = {"red", "black"} + } +} diff --git a/include/bmon/conf.h b/include/bmon/conf.h index f95d48f..6f248af 100644 --- a/include/bmon/conf.h +++ b/include/bmon/conf.h @@ -74,6 +74,8 @@ enum { LAYOUT_HEADER, LAYOUT_LIST, LAYOUT_SELECTED, + LAYOUT_RX_GRAPH, + LAYOUT_TX_GRAPH, __LAYOUT_MAX }; diff --git a/include/bmon/layout.h b/include/bmon/layout.h new file mode 100644 index 0000000..cca2a4c --- /dev/null +++ b/include/bmon/layout.h @@ -0,0 +1,128 @@ + +#ifndef __BMON_LAYOUT_H_ +#define __BMON_LAYOUT_H_ + +#include +#include +#include +#include + + +static int parse_color(const char* color) +{ + int color_code = -1; + + if ((strcasestr(color, "red") != NULL)) + color_code = COLOR_RED; + else if ((strcasestr(color, "green") != NULL)) + color_code = COLOR_GREEN; + else if ((strcasestr(color, "white") != NULL)) + color_code = COLOR_WHITE; + else if ((strcasestr(color, "black") != NULL)) + color_code = COLOR_BLACK; + else if ((strcasestr(color, "blue") != NULL)) + color_code = COLOR_BLUE; + else if ((strcasestr(color, "yellow") != NULL)) + color_code = COLOR_YELLOW; + else if ((strcasestr(color, "magenta") != NULL)) + color_code = COLOR_MAGENTA; + else if ((strcasestr(color, "cyan") != NULL)) + color_code = COLOR_CYAN; + + return color_code; +} + +/* + A_NORMAL Normal display (no highlight) + A_STANDOUT Best highlighting mode of the terminal. + A_UNDERLINE Underlining + A_REVERSE Reverse video + A_BLINK Blinking + A_DIM Half bright + A_BOLD Extra bright or bold + A_PROTECT Protected mode + A_INVIS Invisible or blank mode + A_ALTCHARSET Alternate character set + A_CHARTEXT Bit-mask to extract a character +*/ + +static int parse_attribute(const char* attr) +{ + /* no attribute is valid, so we have nothing to do */ + if (attr == NULL) + return 0; + + if ((strcasestr(attr, "normal") != NULL)) + return A_NORMAL; + else if ((strcasestr(attr, "standout") != NULL)) + return A_STANDOUT; + else if ((strcasestr(attr, "underline") != NULL)) + return A_UNDERLINE; + else if ((strcasestr(attr, "reverse") != NULL)) + return A_REVERSE; + else if ((strcasestr(attr, "blink") != NULL)) + return A_BLINK; + else if ((strcasestr(attr, "dim") != NULL)) + return A_DIM; + else if ((strcasestr(attr, "bold") != NULL)) + return A_BOLD; + else if ((strcasestr(attr, "protect") != NULL)) + return A_PROTECT; + else if ((strcasestr(attr, "invis") != NULL)) + return A_INVIS; + else if ((strcasestr(attr, "altcharset") != NULL)) + return A_ALTCHARSET; + else if ((strcasestr(attr, "chartext") != NULL)) + return A_CHARTEXT; + + return -1; +} + + +static void add_layout(const char *layout_name, cfg_t *color_cfg) +{ + const char *fg, *bg, *attr_str = NULL; + int size = -1, fg_code, bg_code, attr_mask, layout_idx = 0; + + size = cfg_size(color_cfg, "color_pair"); + fg = cfg_getnstr(color_cfg, "color_pair", 0); + bg = cfg_getnstr(color_cfg, "color_pair", 1); + if (size > 2) + attr_str = cfg_getnstr(color_cfg, "color_pair", 2); + + fg_code = parse_color(fg); + bg_code = parse_color(bg); + if (fg_code == -1 || bg_code == -1) { + quit("Unknown color [%s]: %s\n", (fg_code == -1) ? "fg" : "bg", + (fg_code == -1) ? fg : bg); + } + attr_mask = parse_attribute(attr_str); + if (attr_mask == -1) { + quit("Unknown attribute: '%s'\n", attr_str); + } + + DBG("%s:\tfg: %s bg: %s attr: %s\n", layout_name, fg, bg, attr_str); + + if ((strcasecmp(layout_name, "default") == 0)) + layout_idx = LAYOUT_DEFAULT; + else if ((strcasecmp(layout_name, "statusbar") == 0)) + layout_idx = LAYOUT_STATUSBAR; + else if ((strcasecmp(layout_name, "header") == 0)) + layout_idx = LAYOUT_HEADER; + else if ((strcasecmp(layout_name, "list") == 0)) + layout_idx = LAYOUT_LIST; + else if ((strcasecmp(layout_name, "selected") == 0)) + layout_idx = LAYOUT_SELECTED; + else if ((strcasecmp(layout_name, "rx_graph") == 0)) + layout_idx = LAYOUT_RX_GRAPH; + else if ((strcasecmp(layout_name, "tx_graph") == 0)) + layout_idx = LAYOUT_TX_GRAPH; + else { + quit("Unknown layout name: '%s'\n", layout_name); + } + + struct layout l = { fg_code, bg_code, attr_mask}; + cfg_layout[layout_idx] = l; +} + +#endif /* __BMON_LAYOUT_H_ */ diff --git a/src/conf.c b/src/conf.c index d85e9f6..c61fcf8 100644 --- a/src/conf.c +++ b/src/conf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include cfg_t *cfg; @@ -69,6 +70,16 @@ static cfg_opt_t unit_opts[] = { CFG_END() }; +static cfg_opt_t color_opts[] = { + CFG_STR_LIST("color_pair", "", CFGF_NONE), + CFG_END() +}; + +static cfg_opt_t layout_opts[] = { + CFG_SEC("color", color_opts, CFGF_MULTI | CFGF_TITLE), + CFG_END() +}; + static cfg_opt_t global_opts[] = { CFG_FLOAT("read_interval", 1.0f, CFGF_NONE), CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE), @@ -87,6 +98,7 @@ static cfg_opt_t global_opts[] = { CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE), CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE), CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE), + CFG_SEC("layout", layout_opts, CFGF_MULTI | CFGF_TITLE), CFG_END() }; @@ -103,22 +115,26 @@ static char * configfile = NULL; #if defined HAVE_USE_DEFAULT_COLORS struct layout cfg_layout[] = { - {-1, -1, 0}, /* dummy, not used */ - {-1, -1, 0}, /* default */ - {-1, -1, A_REVERSE}, /* statusbar */ - {-1, -1, 0}, /* header */ - {-1, -1, 0}, /* list */ - {-1, -1, A_REVERSE}, /* selected */ + {-1, -1, 0}, /* dummy, not used */ + {-1, -1, 0}, /* default */ + {-1, -1, A_REVERSE}, /* statusbar */ + {-1, -1, 0}, /* header */ + {-1, -1, 0}, /* list */ + {-1, -1, A_REVERSE}, /* selected */ + {-1, -1, 0}, /* RX graph */ + {-1, -1, 0}, /* TX graph */ }; #else struct layout cfg_layout[] = { - {0, 0, 0}, /* dummy, not used */ - {COLOR_BLACK, COLOR_WHITE, 0}, /* default */ - {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* statusbar */ - {COLOR_BLACK, COLOR_WHITE, 0}, /* header */ - {COLOR_BLACK, COLOR_WHITE, 0}, /* list */ - {COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* selected */ + {0, 0, 0}, /* dummy, not used */ + {COLOR_WHITE, COLOR_BLACK, 0}, /* default */ + {COLOR_BLUE, COLOR_GREEN, A_REVERSE}, /* statusbar */ + {COLOR_GREEN, COLOR_BLACK, 0}, /* header */ + {COLOR_WHITE, COLOR_BLACK, 0}, /* list */ + {COLOR_YELLOW, COLOR_BLACK, A_REVERSE}, /* selected */ + {COLOR_GREEN, COLOR_BLACK, 0}, /* RX graph */ + {COLOR_RED, COLOR_BLACK, 0}, /* TX graph */ }; #endif #endif @@ -423,6 +439,41 @@ static void configfile_read_attrs(void) } } +static void configfile_read_layout_cfg(void) +{ + int i, nlayouts; + cfg_t *lout; + nlayouts = cfg_size(cfg, "layout"); + for (i = 0; i < nlayouts; i++) + { + int c, ncolors; + const char *name; + if (!(lout = cfg_getnsec(cfg, "layout", i))) + BUG(); + + if (!(name = cfg_title(lout))) + BUG(); + + ncolors = cfg_size(lout, "color"); + if (ncolors > LAYOUT_MAX) { + fprintf(stderr, "Warning excceeded maximum number of layouts\n"); + ncolors = LAYOUT_MAX; + } + + for (c = 0; c < ncolors; c++) { + cfg_t *color_pair; + + if (!(color_pair = cfg_getnsec(lout, "color", c))) + BUG(); + + if (!(name = cfg_title(color_pair))) + BUG(); + + add_layout(name, color_pair); + } + } +} + static void conf_read(const char *path, int must) { int err; @@ -450,6 +501,7 @@ static void conf_read(const char *path, int must) configfile_read_history(); configfile_read_attrs(); configfile_read_element_cfg(); + configfile_read_layout_cfg(); } static const char default_config[] = \ @@ -508,6 +560,29 @@ static const char default_config[] = \ "history day {" \ " interval = 86400.0" \ " size = 60" \ +"}" +"layout colors {" \ +" color default {" \ +" color_pair = { \"white\", \"black\" }" \ +" }" \ +" color statusbar{" \ +" color_pair = { \"blue\", \"white\", \"reverse\" }" \ +" }" \ +" color header {" \ +" color_pair = { \"yellow\", \"black\" }" \ +" }" \ +" color list {" \ +" color_pair = { \"white\", \"black\" }" \ +" }" \ +" color selected {" \ +" color_pair = { \"yellow\", \"black\", \"reverse\" }" \ +" }" \ +" color rx_graph {" \ +" color_pair = { \"green\", \"black\" }" \ +" }" \ +" color tx_graph {" \ +" color_pair = { \"red\", \"black\" }" \ +" }" \ "}"; static void conf_read_default(void) @@ -524,6 +599,7 @@ static void conf_read_default(void) configfile_read_history(); configfile_read_attrs(); configfile_read_element_cfg(); + configfile_read_layout_cfg(); } void configfile_read(void) diff --git a/src/out_curses.c b/src/out_curses.c index 7b8bc7a..5724121 100644 --- a/src/out_curses.c +++ b/src/out_curses.c @@ -420,6 +420,7 @@ static void draw_header(void) move(row, COLS - strlen(PACKAGE_STRING) - 1); put_line("%s", PACKAGE_STRING); move(row, 0); + apply_layout(LAYOUT_LIST); } static int lines_required_for_statusbar(void) @@ -632,6 +633,7 @@ static void draw_element(struct element_group *g, struct element *e, static void draw_group(struct element_group *g, void *arg) { + apply_layout(LAYOUT_HEADER); int *line = arg; if (line_visible(*line)) { @@ -684,7 +686,7 @@ static void draw_graph_centered(struct graph *g, int row, int ncol, static void draw_table(struct graph *g, struct graph_table *tbl, struct attr *a, struct history *h, - const char *hdr, int ncol) + const char *hdr, int ncol, int layout) { int i, save_row; char buf[32]; @@ -709,11 +711,14 @@ static void draw_table(struct graph *g, struct graph_table *tbl, //move(row, ncol + g->g_cfg.gc_width - 3); //put_line("[err %.2f%%]", rtiming.rt_variance.v_error); + memset(buf, 0, strlen(buf)); for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) { move(++row, ncol); - put_line("%'8.2f %s", - tbl->gt_scale[i], - tbl->gt_table + (i * graph_row_size(&g->g_cfg))); + sprintf(buf, "%'8.2f ", tbl->gt_scale[i]); + addstr(buf); + apply_layout(layout); + put_line("%s", tbl->gt_table + (i * graph_row_size(&g->g_cfg))); + apply_layout(LAYOUT_LIST); } move(++row, ncol); @@ -747,14 +752,14 @@ static void draw_history_graph(struct attr *a, struct history *h) graph_refill(g, h); save_row = row; - draw_table(g, &g->g_rx, a, h, "RX", ncol); + draw_table(g, &g->g_rx, a, h, "RX", ncol, LAYOUT_RX_GRAPH); if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) { ncol = cols / 2; row = save_row; } - draw_table(g, &g->g_tx, a, h, "TX", ncol); + draw_table(g, &g->g_tx, a, h, "TX", ncol, LAYOUT_TX_GRAPH); graph_free(g); } -- cgit v1.2.3 From e47a376f70ef309b78eed864abecea9c1900a765 Mon Sep 17 00:00:00 2001 From: blastmaster Date: Tue, 19 Jul 2016 22:04:26 +0200 Subject: fix make distcheck error * add layout.h in include/Makefile.am --- include/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Makefile.am b/include/Makefile.am index 327db14..75a88fc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -16,4 +16,5 @@ noinst_HEADERS = \ bmon/module.h \ bmon/output.h \ bmon/unit.h \ + bmon/layout.h \ bmon/utils.h -- cgit v1.2.3