Mercurial > nirc
changeset 33:791e72e43120
ui: use wchar_t to output to the screen
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 10 Mar 2020 20:00:00 +0100 |
parents | 1dad4f87fd47 |
children | aeeddb9ce9c9 |
files | ui.c |
diffstat | 1 files changed, 84 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/ui.c Mon Mar 09 20:10:00 2020 +0100 +++ b/ui.c Tue Mar 10 20:00:00 2020 +0100 @@ -509,18 +509,18 @@ else bg = 0; - return COLOR_PAIR((64 + 1) + fg + (bg * SIZE(irc_colors))); + return (64 + 1) + fg + (bg * SIZE(irc_colors)); } -static int -view_apply_color(const char **p) +static short +view_get_color(const wchar_t **p) { assert(*p && **p == 0x03); int foreground = 0; int background = -1; - int attrs; + short color; /* * Three possibilities: @@ -531,24 +531,90 @@ */ (*p)++; - switch (sscanf(*p, "%2d,%2d", &foreground, &background)) { + switch (swscanf(*p, L"%2d,%2d", &foreground, &background)) { case 1: /* Only foreground. */ - attrs = view_pair(foreground, background); + color = view_pair(foreground, background); (*p) += (foreground >= 10) ? 2 : 1; break; case 2: - attrs = view_pair(foreground, background); + color = view_pair(foreground, background); (*p) += (foreground >= 10) ? 2 : 1; (*p) += 1; (*p) += (background >= 10) ? 2 : 1; break; default: - attrs = 0; + color = 0; break; } - return attrs; + return color; +} + +static wchar_t * +view_convert(const char *s) +{ + assert(s); + + wchar_t *wstr; + size_t length; + + /* Determine the length required. */ + if ((length = mbstowcs(NULL, s, 0)) == (size_t)-1) + return NULL; + + wstr = ecalloc(sizeof (wchar_t), length + 1); + mbstowcs(wstr, s, length); + + return wstr; +} + +static void +view_output_char(wchar_t ch, attr_t attrs, short color) +{ + WINDOW *f = widgets[UI_ELT_VIEW].frame; + cchar_t cc = { 0 }; + + setcchar(&cc, (const wchar_t []) { ch, 0 }, attrs, color, NULL); + wadd_wch(f, &cc); +} + +static void +view_output_line(const wchar_t *line) +{ + assert(line); + + attr_t attrs = A_NORMAL; + short color = 0; + + for (const wchar_t *p = line; *p; ++p) { + switch (*p) { + case 0x02: /* BOLD */ + attrs ^= A_BOLD; + break; + case 0x1d: /* ITALICS */ + attrs ^= A_ITALIC; + break; + case 0x1f: /* UNDERLINE */ + attrs ^= A_UNDERLINE; + break; + case 0x16: /* REVERSE */ + attrs ^= A_REVERSE; + break; + case 0x0f: /* RESET */ + attrs = 0; + color = 0; + break; + case 0x03: /* COLORS */ + color = view_get_color(&p); + /* Fallthrough. */ + default: + view_output_char(*p, attrs, color); + break; + } + } + + view_output_char('\n', A_NORMAL, 0); } static void @@ -566,35 +632,17 @@ wmove(f, 0, 0); for (size_t i = 0; i < j->linesz; ++i) { - int attrs = 0; + wchar_t *line; - for (const char *p = j->lines[i]; *p; ++p) { - switch (*p) { - case 0x02: /* BOLD */ - attrs ^= A_BOLD; - break; - case 0x1d: /* ITALICS */ - attrs ^= A_ITALIC; - break; - case 0x1f: /* UNDERLINE */ - attrs ^= A_UNDERLINE; - break; - case 0x16: /* REVERSE */ - attrs ^= A_REVERSE; - break; - case 0x0f: /* RESET */ - attrs = 0; - break; - case 0x03: /* COLORS */ - attrs |= view_apply_color(&p); - /* Fallthrough. */ - default: - waddch(f, *p | attrs); - break; - } + /* + * It's easier to convert the line into a wide-string as + * outputing individual UTF-8 characters with (w)addch could + * add some video attributes which we want to avoid. + */ + if ((line = view_convert(j->lines[i]))) { + view_output_line(line); + free(line); } - - waddch(f, '\n'); } prefresh(f, 0, 0, 1, x, h, COLS);