aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c136
1 files 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 -----------------------------------------------------------------