From b5a7ea63c249fa40af1f77d079c476e44ea4f7e6 Mon Sep 17 00:00:00 2001 From: Přemysl Janouch Date: Mon, 11 May 2015 19:09:42 +0200 Subject: degesch: make mIRC formatting actually work --- degesch.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 21 deletions(-) diff --git a/degesch.c b/degesch.c index 744cd87..501b63e 100644 --- a/degesch.c +++ b/degesch.c @@ -1475,7 +1475,7 @@ serialize_configuration (struct app_context *ctx, struct str *output) /// 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) + ((COLOR_ ## name) & 0xFFFF | ((c256 & 0xFFFF) << 16)) static struct { @@ -1729,6 +1729,104 @@ enum ATTRIBUTE_INVERSE = 1 << 3 }; +struct attribute_printer +{ + struct app_context *ctx; ///< Application context + terminal_printer_fn printer; ///< Terminal printer + bool dirty; ///< Attributes are set + + int want; ///< Desired attributes + int want_foreground; ///< Desired foreground color + int want_background; ///< Desired background color +}; + +static void +attribute_printer_reset (struct attribute_printer *self) +{ + if (self->dirty) + tputs (self->ctx->attrs[ATTR_RESET], 1, self->printer); + + self->dirty = false; +} + +static void +attribute_printer_init (struct attribute_printer *self, + struct app_context *ctx, terminal_printer_fn printer) +{ + self->ctx = ctx; + self->printer = printer; + self->dirty = true; + + self->want = 0; + self->want_foreground = -1; + self->want_background = -1; +} + +static void +attribute_printer_apply (struct attribute_printer *self, int attribute) +{ + attribute_printer_reset (self); + if (attribute != ATTR_RESET) + { + tputs (self->ctx->attrs[attribute], 1, self->printer); + self->dirty = true; + } +} + +// TODO: 256-color output +// - 8 color -> maybe bold, maybe inverse (should text be bold now?) +// - 16 color -> just use the fallback color +// - 88 color -> use the 256color value if available +// - 256 color -> use the 256color value if available + +static void +attribute_printer_update (struct attribute_printer *self) +{ + int fg = 0; + if ((int16_t) (self->want_foreground >> 16) > 0) + fg = index_to_terminal_palette ((int16_t) (self->want_foreground >> 16)); + int bg = 0; + if ((int16_t) (self->want_background >> 16) > 0) + bg = index_to_terminal_palette ((int16_t) (self->want_background >> 16)); + if (fg <= 0) fg = (int16_t) (self->want_foreground); + if (bg <= 0) bg = (int16_t) (self->want_background); + + int attributes = self->want; + if (max_colors == 8) + { + if (fg >= 8) + { + attributes |= ATTRIBUTE_BOLD; + fg -= 8; + } + if (bg >= 8) + { + attributes |= ATTRIBUTE_BOLD; + bg -= 8; + } + } + + attribute_printer_reset (self); + + if (fg >= 0) tputs (g_terminal.color_set_fg[fg], 1, self->printer); + if (bg >= 0) tputs (g_terminal.color_set_bg[bg], 1, self->printer); + + if (attributes) + tputs (tparm (set_attributes, + 0, // standout + attributes & ATTRIBUTE_UNDERLINE, + attributes & ATTRIBUTE_INVERSE, + 0, // blink + 0, // dim + attributes & ATTRIBUTE_BOLD, + 0, // blank + 0, // protect + 0) // acs + , 1, self->printer); + + self->dirty = true; +} + // --- Output formatter -------------------------------------------------------- // This complicated piece of code makes attributed text formatting simple. @@ -2030,10 +2128,10 @@ formatter_flush (struct formatter *self, FILE *stream) return; } - const char *attr_reset = self->ctx->attrs[ATTR_RESET]; - tputs (attr_reset, 1, printer); + struct attribute_printer state; + attribute_printer_init (&state, self->ctx, printer); + attribute_printer_reset (&state); - bool is_attributed = false; LIST_FOR_EACH (struct formatter_item, iter, self->items) { switch (iter->type) @@ -2046,30 +2144,26 @@ formatter_flush (struct formatter *self, FILE *stream) free (term); break; case FORMATTER_ITEM_ATTR: - if (is_attributed) - { - tputs (attr_reset, 1, printer); - is_attributed = false; - } - if (iter->attribute != ATTR_RESET) - { - tputs (self->ctx->attrs[iter->attribute], 1, printer); - is_attributed = true; - } + attribute_printer_apply (&state, iter->attribute); + state.want = 0; + state.want_foreground = -1; + state.want_background = -1; + break; + case FORMATTER_ITEM_SIMPLE: + state.want |= iter->attribute; + attribute_printer_update (&state); break; case FORMATTER_ITEM_FG_COLOR: - tputs (g_terminal.color_set_fg[iter->color], 1, printer); - is_attributed = true; + state.want_foreground = iter->color; + attribute_printer_update (&state); break; case FORMATTER_ITEM_BG_COLOR: - tputs (g_terminal.color_set_bg[iter->color], 1, printer); - is_attributed = true; + state.want_background = iter->color; + attribute_printer_update (&state); break; } } - - if (is_attributed) - tputs (attr_reset, 1, printer); + attribute_printer_reset (&state); } // --- Buffers ----------------------------------------------------------------- -- cgit v1.2.3-70-g09d2