degesch: make mIRC formatting actually work

This commit is contained in:
Přemysl Eric Janouch 2015-05-11 19:09:42 +02:00
parent 1a24ab7085
commit b5a7ea63c2
1 changed files with 115 additions and 21 deletions

136
degesch.c
View File

@ -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 -----------------------------------------------------------------