degesch: make mIRC formatting actually work
This commit is contained in:
parent
1a24ab7085
commit
b5a7ea63c2
136
degesch.c
136
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 -----------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user