summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--degesch.c41
1 files changed, 25 insertions, 16 deletions
diff --git a/degesch.c b/degesch.c
index 4e58684..7063343 100644
--- a/degesch.c
+++ b/degesch.c
@@ -3413,8 +3413,8 @@ formatter_add (struct formatter *self, const char *format, ...)
struct line_char_attrs
{
- int named; ///< Named attribute or -1
- int text; ///< Text attributes
+ short named; ///< Named attribute or -1
+ short text; ///< Text attributes
int fg; ///< Foreground colour (-1 for default)
int bg; ///< Background colour (-1 for default)
};
@@ -3423,18 +3423,15 @@ struct line_char
{
LIST_HEADER (struct line_char)
- char bytes[MB_LEN_MAX]; ///< The character
- size_t len; ///< Length of the character in bytes
wchar_t wide; ///< The character as a wchar_t
int width; ///< Width of the character in cells
struct line_char_attrs attrs; ///< Attributes
};
static struct line_char *
-line_char_new (const char *mb, size_t mb_len, wchar_t wc)
+line_char_new (wchar_t wc)
{
struct line_char *self = xcalloc (1, sizeof *self);
- memcpy (self->bytes, mb, (self->len = MIN (mb_len, sizeof self->bytes)));
self->width = wcwidth ((self->wide = wc));
// Typically various control characters
@@ -3476,7 +3473,7 @@ struct line_wrap_state
static void
line_wrap_flush_split (struct line_wrap_state *s, struct line_wrap_mark *before)
{
- struct line_char *nl = line_char_new ("\n", 1, L'\n');
+ struct line_char *nl = line_char_new (L'\n');
LIST_INSERT_WITH_TAIL (s->result, s->result_tail, nl, before->start);
s->line_used = before->used;
}
@@ -3512,7 +3509,7 @@ static void
line_wrap_nl (struct line_wrap_state *s)
{
line_wrap_flush (s, true);
- struct line_char *nl = line_char_new ("\n", 1, L'\n');
+ struct line_char *nl = line_char_new (L'\n');
LIST_APPEND_WITH_TAIL (s->result, s->result_tail, nl);
s->line_used = 0;
}
@@ -3533,7 +3530,7 @@ line_wrap_tab (struct line_wrap_state *s, struct line_char *c)
s->line_used += tab_width;
while (tab_width--)
{
- struct line_char *space = line_char_new (" ", 1, L' ');
+ struct line_char *space = line_char_new (L' ');
space->attrs = c->attrs;
LIST_APPEND_WITH_TAIL (s->result, s->result_tail, space);
}
@@ -3664,7 +3661,7 @@ explode_text (struct exploder *self, const char *text)
hard_assert (len != (size_t) -2 && len != (size_t) -1);
processed += len;
- struct line_char *c = line_char_new (term + processed - len, len, wch);
+ struct line_char *c = line_char_new (wch);
c->attrs = self->attrs;
LIST_APPEND_WITH_TAIL (self->result, self->result_tail, c);
}
@@ -3698,6 +3695,18 @@ enum
FLUSH_OPT_NOWRAP = (1 << 1) ///< Do not wrap
};
+/// The input is a bunch of wide characters--respect shift state encodings
+static void
+formatter_putc (struct line_char *c, FILE *stream)
+{
+ static mbstate_t mb;
+ char buf[MB_LEN_MAX] = {};
+ size_t len = wcrtomb (buf, c ? c->wide : L'\0', &mb);
+ if (len != (size_t) -1 && len)
+ fwrite (buf, len - !c, 1, stream);
+ free (c);
+}
+
static void
formatter_flush (struct formatter *self, FILE *stream, int flush_opts)
{
@@ -3707,10 +3716,8 @@ formatter_flush (struct formatter *self, FILE *stream, int flush_opts)
if (!is_tty && !(flush_opts & FLUSH_OPT_RAW))
{
LIST_FOR_EACH (struct line_char, c, line)
- {
- fwrite (c->bytes, c->len, 1, stream);
- free (c);
- }
+ formatter_putc (c, stream);
+ formatter_putc (NULL, stream);
return;
}
@@ -3726,6 +3733,8 @@ formatter_flush (struct formatter *self, FILE *stream, int flush_opts)
|| attrs.named != c->attrs.named
|| attrs.text != c->attrs.text)
{
+ formatter_putc (NULL, stream);
+
attrs = c->attrs;
if (attrs.named != -1)
attr_printer_apply_named (&state, attrs.named);
@@ -3733,9 +3742,9 @@ formatter_flush (struct formatter *self, FILE *stream, int flush_opts)
attr_printer_apply (&state, attrs.text, attrs.fg, attrs.bg);
}
- fwrite (c->bytes, c->len, 1, stream);
- free (c);
+ formatter_putc (c, stream);
}
+ formatter_putc (NULL, stream);
attr_printer_reset (&state);
}