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
|
/// Builds a color pair for 256-color terminals with a 16-color backup value
|
||||||
#define COLOR_256(name, c256) \
|
#define COLOR_256(name, c256) \
|
||||||
(COLOR_ ## name) & 0xFFFF | ((c256 << 16) & 0xFFFF)
|
((COLOR_ ## name) & 0xFFFF | ((c256 & 0xFFFF) << 16))
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
|
@ -1729,6 +1729,104 @@ enum
|
||||||
ATTRIBUTE_INVERSE = 1 << 3
|
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 --------------------------------------------------------
|
// --- Output formatter --------------------------------------------------------
|
||||||
|
|
||||||
// This complicated piece of code makes attributed text formatting simple.
|
// This complicated piece of code makes attributed text formatting simple.
|
||||||
|
@ -2030,10 +2128,10 @@ formatter_flush (struct formatter *self, FILE *stream)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *attr_reset = self->ctx->attrs[ATTR_RESET];
|
struct attribute_printer state;
|
||||||
tputs (attr_reset, 1, printer);
|
attribute_printer_init (&state, self->ctx, printer);
|
||||||
|
attribute_printer_reset (&state);
|
||||||
|
|
||||||
bool is_attributed = false;
|
|
||||||
LIST_FOR_EACH (struct formatter_item, iter, self->items)
|
LIST_FOR_EACH (struct formatter_item, iter, self->items)
|
||||||
{
|
{
|
||||||
switch (iter->type)
|
switch (iter->type)
|
||||||
|
@ -2046,30 +2144,26 @@ formatter_flush (struct formatter *self, FILE *stream)
|
||||||
free (term);
|
free (term);
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_ATTR:
|
case FORMATTER_ITEM_ATTR:
|
||||||
if (is_attributed)
|
attribute_printer_apply (&state, iter->attribute);
|
||||||
{
|
state.want = 0;
|
||||||
tputs (attr_reset, 1, printer);
|
state.want_foreground = -1;
|
||||||
is_attributed = false;
|
state.want_background = -1;
|
||||||
}
|
break;
|
||||||
if (iter->attribute != ATTR_RESET)
|
case FORMATTER_ITEM_SIMPLE:
|
||||||
{
|
state.want |= iter->attribute;
|
||||||
tputs (self->ctx->attrs[iter->attribute], 1, printer);
|
attribute_printer_update (&state);
|
||||||
is_attributed = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_FG_COLOR:
|
case FORMATTER_ITEM_FG_COLOR:
|
||||||
tputs (g_terminal.color_set_fg[iter->color], 1, printer);
|
state.want_foreground = iter->color;
|
||||||
is_attributed = true;
|
attribute_printer_update (&state);
|
||||||
break;
|
break;
|
||||||
case FORMATTER_ITEM_BG_COLOR:
|
case FORMATTER_ITEM_BG_COLOR:
|
||||||
tputs (g_terminal.color_set_bg[iter->color], 1, printer);
|
state.want_background = iter->color;
|
||||||
is_attributed = true;
|
attribute_printer_update (&state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
attribute_printer_reset (&state);
|
||||||
if (is_attributed)
|
|
||||||
tputs (attr_reset, 1, printer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Buffers -----------------------------------------------------------------
|
// --- Buffers -----------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue