Centralize code to convert to SGR

Conversion from formatting attributes to SGR now always goes through a
Cursor.
This commit is contained in:
Kovid Goyal
2017-12-04 10:51:06 +05:30
parent 52ecdfe3a9
commit 27cd303a05
6 changed files with 45 additions and 71 deletions

View File

@@ -129,34 +129,42 @@ color_as_sgr(char *buf, size_t sz, unsigned long val, unsigned simple_code, unsi
case 1:
val >>= 8;
if (val < 16 && simple_code) {
return snprintf(buf, sz, "%ld;", (val < 8) ? simple_code + val : aix_code + (val - 8));
return snprintf(buf, sz, "%lu;", (val < 8) ? simple_code + val : aix_code + (val - 8));
}
return snprintf(buf, sz, "%d:5:%ld;", complex_code, val);
return snprintf(buf, sz, "%u:5:%lu;", complex_code, val);
case 2:
return snprintf(buf, sz, "%d:2:%ld:%ld:%ld;", complex_code, (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff);
return snprintf(buf, sz, "%u:2:%lu:%lu:%lu;", complex_code, (val >> 24) & 0xff, (val >> 16) & 0xff, (val >> 8) & 0xff);
default:
return 0;
return snprintf(buf, sz, "%u;", complex_code + 1); // reset
}
}
static inline const char*
decoration_as_sgr(uint8_t decoration) {
switch(decoration) {
case 1: return "4";
case 2: return "6"; // UNDERCURL_CODE
default: return "24";
}
}
const char*
cursor_as_sgr(Cursor *self) {
cursor_as_sgr(Cursor *self, Cursor *prev) {
static char buf[128], *p;
#define SZ sizeof(buf) - (p - buf) - 2
#define P(fmt, ...) { p += snprintf(p, SZ, fmt ";", __VA_ARGS__); }
p = buf;
if (self->bold) P("%d", 1);
if (self->italic) P("%d", 3);
if (self->reverse) P("%d", 7);
if (self->strikethrough) P("%d", 9);
if (self->decoration) P("%d", self->decoration == 1 ? 4 : UNDERCURL_CODE);
if (self->fg) p += color_as_sgr(p, SZ, self->fg, 30, 90, 38);
if (self->bg) p += color_as_sgr(p, SZ, self->bg, 40, 100, 48);
if (self->decoration_fg) p += color_as_sgr(p, SZ, self->decoration_fg, 0, 0, DECORATION_FG_CODE);
if (self->bold != prev->bold) P("%d", self->bold ? 1 : 22);
if (self->italic != prev->italic) P("%d", self->italic ? 3 : 23);
if (self->reverse != prev->reverse) P("%d", self->reverse ? 7 : 27);
if (self->strikethrough != prev->strikethrough) P("%d", self->strikethrough ? 9 : 29);
if (self->decoration != prev->decoration) P("%s", decoration_as_sgr(self->decoration));
if (self->fg != prev->fg) p += color_as_sgr(p, SZ, self->fg, 30, 90, 38);
if (self->bg != prev->bg) p += color_as_sgr(p, SZ, self->bg, 40, 100, 48);
if (self->decoration_fg != prev->decoration_fg) p += color_as_sgr(p, SZ, self->decoration_fg, 0, 0, DECORATION_FG_CODE);
#undef P
#undef SZ
if (p > buf) *(p - 1) = 0; // remove trailing semi-colon
else *(p++) = '0'; // no formatting
*p = 0; // ensure string is null-terminated
return buf;
}