diff --git a/degesch.c b/degesch.c index 012e54a..30c1645 100644 --- a/degesch.c +++ b/degesch.c @@ -1473,6 +1473,10 @@ serialize_configuration (struct app_context *ctx, struct str *output) /// Bright versions of the basic color set #define COLOR_BRIGHT(x) (COLOR_ ## x + 8) +/// Builds a color pair for 256-color terminals with a 16-color backup value +#define COLOR_256(name, c256) \ + (COLOR_ ## name) & 0xFFFF | ((c256 << 16) & 0xFFFF) + static struct { bool initialized; ///< Terminal is available @@ -1559,6 +1563,10 @@ free_terminal (void) del_curterm (cur_term); } +// NOTE: commonly terminals have 8 colors (worst), 16 colors (allows brightness +// without the bold/blink attributes), 88 colors (the same plus a 4^3 RGB cube +// and a few shades of gray), or 256 colors (best) + static int index_to_terminal_palette (int color) { @@ -1706,6 +1714,21 @@ init_colors (struct app_context *ctx) g_log_message_real = log_message_attributed; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// A little tool that tries to make the most of the terminal's capabilities +// to set up text attributes. It mostly targets just terminal emulators as that +// is what people are using these days. At least no stupid ncurses limits us +// with color pairs. + +enum +{ + ATTRIBUTE_BOLD = 1 << 0, + ATTRIBUTE_ITALIC = 1 << 1, + ATTRIBUTE_UNDERLINE = 1 << 2, + ATTRIBUTE_INVERSE = 1 << 3 +}; + // --- Output formatter -------------------------------------------------------- // This complicated piece of code makes attributed text formatting simple. @@ -1728,13 +1751,7 @@ enum formatter_item_type FORMATTER_ITEM_ATTR, ///< Formatting attributes FORMATTER_ITEM_FG_COLOR, ///< Foreground color FORMATTER_ITEM_BG_COLOR, ///< Background color - - // These are internal, for mIRC formatting only so far: - - FORMATTER_ITEM_BOLD, ///< Bold - FORMATTER_ITEM_ITALIC, ///< Italic - FORMATTER_ITEM_UNDERLINE, ///< Underline - FORMATTER_ITEM_INVERSE ///< Inverse + FORMATTER_ITEM_SIMPLE ///< For mIRC formatting only so far }; struct formatter_item @@ -1786,65 +1803,28 @@ formatter_free (struct formatter *self) formatter_item_destroy (iter); } -static struct formatter_item * -formatter_add_blank (struct formatter *self) +static void +formatter_add_item (struct formatter *self, struct formatter_item template_) { + if (template_.type != FORMATTER_ITEM_TEXT && self->ignore_new_attributes) + return; + if (template_.text) + template_.text = xstrdup (template_.text); + struct formatter_item *item = formatter_item_new (); + *item = template_; LIST_APPEND_WITH_TAIL (self->items, self->items_tail, item); - return item; } -static void -formatter_add_text (struct formatter *self, const char *text) -{ - struct formatter_item *item = formatter_add_blank (self); - item->type = FORMATTER_ITEM_TEXT; - item->text = xstrdup (text); -} +#define FORMATTER_ADD_ITEM(self, type_, ...) formatter_add_item ((self), \ + (struct formatter_item) { .type = FORMATTER_ITEM_ ## type_, __VA_ARGS__ }) -static void -formatter_add_reset (struct formatter *self) -{ - if (self->ignore_new_attributes) - return; - - struct formatter_item *item = formatter_add_blank (self); - item->type = FORMATTER_ITEM_ATTR; - item->attribute = ATTR_RESET; -} - -static void -formatter_add_attr (struct formatter *self, int attr_id) -{ - if (self->ignore_new_attributes) - return; - - struct formatter_item *item = formatter_add_blank (self); - item->type = FORMATTER_ITEM_ATTR; - item->attribute = attr_id; -} - -static void -formatter_add_fg_color (struct formatter *self, int color) -{ - if (self->ignore_new_attributes) - return; - - struct formatter_item *item = formatter_add_blank (self); - item->type = FORMATTER_ITEM_FG_COLOR; - item->color = color; -} - -static void -formatter_add_bg_color (struct formatter *self, int color) -{ - if (self->ignore_new_attributes) - return; - - struct formatter_item *item = formatter_add_blank (self); - item->type = FORMATTER_ITEM_BG_COLOR; - item->color = color; -} +#define FORMATTER_ADD_RESET(self) \ + FORMATTER_ADD_ITEM ((self), ATTR, .attribute = ATTR_RESET) +#define FORMATTER_ADD_TEXT(self, text_) \ + FORMATTER_ADD_ITEM ((self), TEXT, .text = (text_)) +#define FORMATTER_ADD_SIMPLE(self, attribute_) \ + FORMATTER_ADD_ITEM ((self), SIMPLE, .attribute = ATTRIBUTE_ ## attribute_) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1859,41 +1839,26 @@ enum // We use estimates from the 16 color terminal palette, or the 256 color cube, // which is not always available. The mIRC orange colour is only in the cube. -// NOTE: commonly terminals have 8 colors (worst), 16 colors (allows brightness -// without the bold/blink attributes), 88 colors (the same plus a 4^3 RGB cube -// and a few shades of gray), or 256 colors (best) - -/// Builds a color pair for 256-color terminals with a 16-color backup value -#define FORMATTER_COLOR(name, c256) \ - (COLOR_ ## name) & 0xFFFF | ((c256 << 16) & 0xFFFF) - -static const int g_mirc_to_term[] = +static const int g_mirc_to_terminal[] = { - [MIRC_WHITE] = FORMATTER_COLOR (BRIGHT (WHITE), 231), - [MIRC_BLACK] = FORMATTER_COLOR (BLACK, 16), - [MIRC_BLUE] = FORMATTER_COLOR (BLUE, 19), - [MIRC_GREEN] = FORMATTER_COLOR (GREEN, 34), - [MIRC_L_RED] = FORMATTER_COLOR (BRIGHT (RED), 196), - [MIRC_RED] = FORMATTER_COLOR (RED, 124), - [MIRC_PURPLE] = FORMATTER_COLOR (MAGENTA, 127), - [MIRC_ORANGE] = FORMATTER_COLOR (BRIGHT (YELLOW), 214), - [MIRC_YELLOW] = FORMATTER_COLOR (BRIGHT (YELLOW), 226), - [MIRC_L_GREEN] = FORMATTER_COLOR (BRIGHT (GREEN), 46), - [MIRC_CYAN] = FORMATTER_COLOR (CYAN, 37), - [MIRC_L_CYAN] = FORMATTER_COLOR (BRIGHT (CYAN), 51), - [MIRC_L_BLUE] = FORMATTER_COLOR (BRIGHT (BLUE), 21), - [MIRC_L_PURPLE] = FORMATTER_COLOR (BRIGHT (MAGENTA),201), - [MIRC_GRAY] = FORMATTER_COLOR (BRIGHT (BLACK), 244), - [MIRC_L_GRAY] = FORMATTER_COLOR (WHITE, 252), + [MIRC_WHITE] = COLOR_256 (BRIGHT (WHITE), 231), + [MIRC_BLACK] = COLOR_256 (BLACK, 16), + [MIRC_BLUE] = COLOR_256 (BLUE, 19), + [MIRC_GREEN] = COLOR_256 (GREEN, 34), + [MIRC_L_RED] = COLOR_256 (BRIGHT (RED), 196), + [MIRC_RED] = COLOR_256 (RED, 124), + [MIRC_PURPLE] = COLOR_256 (MAGENTA, 127), + [MIRC_ORANGE] = COLOR_256 (BRIGHT (YELLOW), 214), + [MIRC_YELLOW] = COLOR_256 (BRIGHT (YELLOW), 226), + [MIRC_L_GREEN] = COLOR_256 (BRIGHT (GREEN), 46), + [MIRC_CYAN] = COLOR_256 (CYAN, 37), + [MIRC_L_CYAN] = COLOR_256 (BRIGHT (CYAN), 51), + [MIRC_L_BLUE] = COLOR_256 (BRIGHT (BLUE), 21), + [MIRC_L_PURPLE] = COLOR_256 (BRIGHT (MAGENTA),201), + [MIRC_GRAY] = COLOR_256 (BRIGHT (BLACK), 244), + [MIRC_L_GRAY] = COLOR_256 (WHITE, 252), }; -static void -formatter_add_simple (struct formatter *self, enum formatter_item_type type) -{ - if (!self->ignore_new_attributes) - formatter_add_blank (self)->type = type; -} - static const char * formatter_parse_mirc_color (struct formatter *self, const char *s) { @@ -1904,7 +1869,7 @@ formatter_parse_mirc_color (struct formatter *self, const char *s) if (isdigit_ascii (*s)) fg = fg * 10 + (*s++ - '0'); if (fg >= 0 && fg < 16) - formatter_add_fg_color (self, g_mirc_to_term[fg]); + FORMATTER_ADD_ITEM (self, FG_COLOR, .color = g_mirc_to_terminal[fg]); if (*s != ',' || !isdigit_ascii (s[1])) return s; @@ -1913,7 +1878,7 @@ formatter_parse_mirc_color (struct formatter *self, const char *s) if (isdigit_ascii (s[1])) bg = bg * 10 + (*++s - '0'); if (bg >= 0 && bg < 16) - formatter_add_bg_color (self, g_mirc_to_term[bg]); + FORMATTER_ADD_ITEM (self, BG_COLOR, .color = g_mirc_to_terminal[bg]); return s; } @@ -1924,33 +1889,29 @@ formatter_parse_mirc (struct formatter *self, const char *s) struct str buf; str_init (&buf); - formatter_add_reset (self); + FORMATTER_ADD_RESET (self); char c; while ((c = *s++)) { if (buf.len && c < 0x20) { - formatter_add_text (self, buf.str); + FORMATTER_ADD_TEXT (self, buf.str); str_reset (&buf); } -#define SIMPLE(type) formatter_add_simple (self, FORMATTER_ITEM_ ## type) - switch (c) { - case '\x02': SIMPLE (BOLD); break; - case '\x1d': SIMPLE (ITALIC); break; - case '\x1f': SIMPLE (UNDERLINE); break; - case '\x16': SIMPLE (INVERSE); break; - -#undef SIMPLE + case '\x02': FORMATTER_ADD_SIMPLE (self, BOLD); break; + case '\x1d': FORMATTER_ADD_SIMPLE (self, ITALIC); break; + case '\x1f': FORMATTER_ADD_SIMPLE (self, UNDERLINE); break; + case '\x16': FORMATTER_ADD_SIMPLE (self, INVERSE); break; case '\x03': s = formatter_parse_mirc_color (self, s); break; case '\x0f': - formatter_add_reset (self); + FORMATTER_ADD_RESET (self); break; default: str_append_c (&buf, c); @@ -1958,10 +1919,10 @@ formatter_parse_mirc (struct formatter *self, const char *s) } if (buf.len) - formatter_add_text (self, buf.str); + FORMATTER_ADD_TEXT (self, buf.str); str_free (&buf); - formatter_add_reset (self); + FORMATTER_ADD_RESET (self); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1994,22 +1955,21 @@ restart: str_append (buf, s); free (s); break; - case 'm': - formatter_parse_mirc (self, va_arg (*ap, char *)); + formatter_parse_mirc (self, va_arg (*ap, char *)); break; case 'a': - formatter_add_attr (self, va_arg (*ap, int)); + FORMATTER_ADD_ITEM (self, ATTR, .attribute = va_arg (*ap, int)); break; case 'c': - formatter_add_fg_color (self, va_arg (*ap, int)); + FORMATTER_ADD_ITEM (self, FG_COLOR, .color = va_arg (*ap, int)); break; case 'C': - formatter_add_bg_color (self, va_arg (*ap, int)); + FORMATTER_ADD_ITEM (self, BG_COLOR, .color = va_arg (*ap, int)); break; case 'r': - formatter_add_reset (self); + FORMATTER_ADD_RESET (self); break; default: @@ -2044,7 +2004,7 @@ formatter_add (struct formatter *self, const char *format, ...) } if (buf.len) { - formatter_add_text (self, buf.str); + FORMATTER_ADD_TEXT (self, buf.str); str_reset (&buf); } @@ -2052,7 +2012,7 @@ formatter_add (struct formatter *self, const char *format, ...) } if (buf.len) - formatter_add_text (self, buf.str); + FORMATTER_ADD_TEXT (self, buf.str); str_free (&buf); va_end (ap);