diff --git a/degesch.c b/degesch.c index cb9c741..52a7f94 100644 --- a/degesch.c +++ b/degesch.c @@ -21,6 +21,7 @@ /// Some arbitrary limit for the history file #define HISTORY_LIMIT 10000 +// A table of all attributes we use for output #define ATTR_TABLE(XX) \ XX( PROMPT, "prompt", "Terminal attributes for the prompt" ) \ XX( RESET, "reset", "String to reset terminal attributes" ) \ @@ -41,13 +42,6 @@ enum ATTR_COUNT }; -static const char *g_attr_table[ATTR_COUNT] = -{ -#define XX(x, y, z) [ATTR_ ## x] = "attr_" y, - ATTR_TABLE (XX) -#undef XX -}; - // User data for logger functions to enable formatted logging #define print_fatal_data ((void *) ATTR_ERROR) #define print_error_data ((void *) ATTR_ERROR) @@ -430,6 +424,7 @@ struct app_context // Configuration: struct str_map config; ///< User configuration + char *attrs[ATTR_COUNT]; ///< Terminal attributes bool no_colors; ///< Colour output mode bool reconnect; ///< Whether to reconnect on conn. fail. unsigned long reconnect_delay; ///< Reconnect delay in seconds @@ -562,6 +557,8 @@ static void app_context_free (struct app_context *self) { str_map_free (&self->config); + for (size_t i = 0; i < ATTR_COUNT; i++) + free (self->attrs[i]); str_free (&self->read_buffer); if (self->irc_fd != -1) @@ -730,20 +727,12 @@ vprint_attributed (struct app_context *ctx, printer = NULL; if (printer) - { - const char *value = str_map_find - (&ctx->config, g_attr_table[attribute]); - tputs (value, 1, printer); - } + tputs (ctx->attrs[attribute], 1, printer); vfprintf (stream, fmt, ap); if (printer) - { - const char *value = str_map_find - (&ctx->config, g_attr_table[ATTR_RESET]); - tputs (value, 1, printer); - } + tputs (ctx->attrs[ATTR_RESET], 1, printer); } static void @@ -774,31 +763,47 @@ log_message_attributed (void *user_data, const char *quote, const char *fmt, app_readline_restore (&state, g_ctx->readline_prompt); } +static void +init_attribute (struct app_context *ctx, int id, const char *default_) +{ + static const char *table[ATTR_COUNT] = + { +#define XX(x, y, z) [ATTR_ ## x] = "attr_" y, + ATTR_TABLE (XX) +#undef XX + }; + + const char *user = str_map_find (&ctx->config, table[id]); + if (user) + ctx->attrs[id] = xstrdup (user); + else + ctx->attrs[id] = xstrdup (default_); +} + static void init_colors (struct app_context *ctx) { bool have_ti = init_terminal (); // Use escape sequences from terminfo if possible, and SGR as a fallback -#define INIT_ATTR(id, ti) \ - str_map_set (&ctx->config, g_attr_table[id], xstrdup (have_ti ? (ti) : "")) +#define INIT_ATTR(id, ti) init_attribute (ctx, ATTR_ ## id, have_ti ? (ti) : "") - INIT_ATTR (ATTR_PROMPT, enter_bold_mode); - INIT_ATTR (ATTR_RESET, exit_attribute_mode); - INIT_ATTR (ATTR_WARNING, g_terminal.color_set_fg[3]); - INIT_ATTR (ATTR_ERROR, g_terminal.color_set_fg[1]); + INIT_ATTR (PROMPT, enter_bold_mode); + INIT_ATTR (RESET, exit_attribute_mode); + INIT_ATTR (WARNING, g_terminal.color_set_fg[3]); + INIT_ATTR (ERROR, g_terminal.color_set_fg[1]); - INIT_ATTR (ATTR_EXTERNAL, g_terminal.color_set_fg[7]); - INIT_ATTR (ATTR_TIMESTAMP, g_terminal.color_set_fg[7]); - INIT_ATTR (ATTR_ACTION, g_terminal.color_set_fg[1]); - INIT_ATTR (ATTR_JOIN, g_terminal.color_set_fg[2]); - INIT_ATTR (ATTR_PART, g_terminal.color_set_fg[1]); + INIT_ATTR (EXTERNAL, g_terminal.color_set_fg[7]); + INIT_ATTR (TIMESTAMP, g_terminal.color_set_fg[7]); + INIT_ATTR (ACTION, g_terminal.color_set_fg[1]); + INIT_ATTR (JOIN, g_terminal.color_set_fg[2]); + INIT_ATTR (PART, g_terminal.color_set_fg[1]); char *highlight = xstrdup_printf ("%s%s%s", g_terminal.color_set_fg[3], g_terminal.color_set_bg[5], enter_bold_mode); - INIT_ATTR (ATTR_HIGHLIGHT, highlight); + INIT_ATTR (HIGHLIGHT, highlight); free (highlight); #undef INIT_ATTR @@ -896,7 +901,7 @@ setup_signal_handlers (void) enum formatter_item_type { FORMATTER_ITEM_TEXT, ///< Text - FORMATTER_ITEM_ATTR, ///< Named formatting attributes + FORMATTER_ITEM_ATTR, ///< Formatting attributes FORMATTER_ITEM_FG_COLOR, ///< Foreground color FORMATTER_ITEM_BG_COLOR ///< Background color }; @@ -907,7 +912,8 @@ struct formatter_item enum formatter_item_type type; ///< Type of this item int color; ///< Color - char *data; ///< Either text or an attribute string + int attribute; ///< Attribute ID + char *text; ///< Either text or an attribute string }; static struct formatter_item * @@ -920,7 +926,7 @@ formatter_item_new (void) static void formatter_item_destroy (struct formatter_item *self) { - free (self->data); + free (self->text); free (self); } @@ -962,7 +968,7 @@ formatter_add_text (struct formatter *self, const char *text) { struct formatter_item *item = formatter_add_blank (self); item->type = FORMATTER_ITEM_TEXT; - item->data = xstrdup (text); + item->text = xstrdup (text); } static void @@ -973,7 +979,7 @@ formatter_add_reset (struct formatter *self) struct formatter_item *item = formatter_add_blank (self); item->type = FORMATTER_ITEM_ATTR; - item->data = NULL; + item->attribute = ATTR_RESET; } static void @@ -984,8 +990,7 @@ formatter_add_attr (struct formatter *self, int attr_id) struct formatter_item *item = formatter_add_blank (self); item->type = FORMATTER_ITEM_ATTR; - item->data = xstrdup (str_map_find - (&self->ctx->config, g_attr_table[attr_id])); + item->attribute = attr_id; } static void @@ -1106,12 +1111,11 @@ formatter_flush (struct formatter *self, FILE *stream) { LIST_FOR_EACH (struct formatter_item, iter, self->items) if (iter->type == FORMATTER_ITEM_TEXT) - fputs (iter->data, stream); + fputs (iter->text, stream); return; } - const char *attr_reset = str_map_find - (&self->ctx->config, g_attr_table[ATTR_RESET]); + const char *attr_reset = self->ctx->attrs[ATTR_RESET]; tputs (attr_reset, 1, printer); bool is_attributed = false; @@ -1122,7 +1126,7 @@ formatter_flush (struct formatter *self, FILE *stream) char *term; case FORMATTER_ITEM_TEXT: term = iconv_xstrdup - (self->ctx->term_from_utf8, iter->data, -1, NULL); + (self->ctx->term_from_utf8, iter->text, -1, NULL); fputs (term, stream); free (term); break; @@ -1132,9 +1136,9 @@ formatter_flush (struct formatter *self, FILE *stream) tputs (attr_reset, 1, printer); is_attributed = false; } - if (iter->data) + if (iter->attribute != ATTR_RESET) { - tputs (iter->data, 1, printer); + tputs (self->ctx->attrs[iter->attribute], 1, printer); is_attributed = true; } break; @@ -2142,14 +2146,12 @@ refresh_prompt (struct app_context *ctx) else { // XXX: to be completely correct, we should use tputs, but we cannot - const char *prompt_attrs = str_map_find - (&ctx->config, g_attr_table[ATTR_PROMPT]); - const char *reset_attrs = str_map_find - (&ctx->config, g_attr_table[ATTR_RESET]); ctx->readline_prompt = xstrdup_printf ("%c%s%c%s%c%s%c", - RL_PROMPT_START_IGNORE, prompt_attrs, RL_PROMPT_END_IGNORE, + RL_PROMPT_START_IGNORE, ctx->attrs[ATTR_PROMPT], + RL_PROMPT_END_IGNORE, prompt.str, - RL_PROMPT_START_IGNORE, reset_attrs, RL_PROMPT_END_IGNORE); + RL_PROMPT_START_IGNORE, ctx->attrs[ATTR_RESET], + RL_PROMPT_END_IGNORE); } str_free (&prompt); @@ -4549,7 +4551,6 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - // FIXME: this overwrites all custom attribute settings init_colors (&ctx); init_poller_events (&ctx); init_buffers (&ctx);