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]
This commit is contained in:
		| @ -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"} | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -74,6 +74,8 @@ enum { | ||||
| 	LAYOUT_HEADER, | ||||
| 	LAYOUT_LIST, | ||||
| 	LAYOUT_SELECTED, | ||||
|     LAYOUT_RX_GRAPH, | ||||
|     LAYOUT_TX_GRAPH, | ||||
| 	__LAYOUT_MAX | ||||
| }; | ||||
|  | ||||
|  | ||||
							
								
								
									
										128
									
								
								include/bmon/layout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								include/bmon/layout.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | ||||
|  | ||||
| #ifndef __BMON_LAYOUT_H_ | ||||
| #define __BMON_LAYOUT_H_ | ||||
|  | ||||
| #include <bmon/bmon.h> | ||||
| #include <bmon/conf.h> | ||||
| #include <bmon/unit.h> | ||||
| #include <bmon/utils.h> | ||||
|  | ||||
|  | ||||
| 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_ */ | ||||
							
								
								
									
										86
									
								
								src/conf.c
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								src/conf.c
									
									
									
									
									
								
							| @ -30,6 +30,7 @@ | ||||
| #include <bmon/element.h> | ||||
| #include <bmon/element_cfg.h> | ||||
| #include <bmon/history.h> | ||||
| #include <bmon/layout.h> | ||||
| #include <bmon/utils.h> | ||||
|  | ||||
| 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() | ||||
| }; | ||||
|  | ||||
| @ -109,16 +121,20 @@ struct layout cfg_layout[] = | ||||
|     {-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 */ | ||||
| 	{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) | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user