From 96cc886097812dfeb3f1096492ff0c601e38b17f Mon Sep 17 00:00:00 2001 From: Ron Yorston <rmy@pobox.com> Date: Sun, 7 Feb 2021 13:31:27 +0000 Subject: winansi: code shrink Refactor handling of ESC[38...m and ESC[48...m: - At lower levels deal only with the standard console foreground colours. This makes handling of foreground and background colours more similar. - Many '|=' assignments (to combine attribute values) have been replaced by simple assinments. - Use a common routine to convert RGB to console colours; colours in the 8-bit 6x6x6 cube are scaled up to make use of this. - Detect invalid escape sequences to avoid setting incorrect colour values. Saves 296 bytes. --- win32/winansi.c | 161 +++++++++++++++++++++++++------------------------------- 1 file changed, 71 insertions(+), 90 deletions(-) diff --git a/win32/winansi.c b/win32/winansi.c index da3c977f0..efb6efeb7 100644 --- a/win32/winansi.c +++ b/win32/winansi.c @@ -262,49 +262,53 @@ static void move_cursor(int x, int y) SetConsoleCursorPosition(console, pos); } -/* 24-bit colour */ -static char *process_fg_24bit(char *str, WORD *attr) +static WORD rgb_to_console(int *rgb) { - int count = 0; - int val[3] = {0, 0, 0}; - int dark, bright = 0; + int dark = 0, bright; + WORD attr = 0; - do { - val[count++] = strtol(str, (char **)&str, 10); - ++str; - } while (*(str-1) == ';' && count < 3); + if (rgb[0] > 85) + attr |= FOREGROUND_RED; + else + ++dark; - *attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); - if (val[0] > 85) - *attr |= FOREGROUND_RED; - if (val[1] > 85) - *attr |= FOREGROUND_GREEN; - if (val[2] > 85) - *attr |= FOREGROUND_BLUE; + if (rgb[1] > 85) + attr |= FOREGROUND_GREEN; + else + ++dark; + + if (rgb[2] > 85) + attr |= FOREGROUND_BLUE; + else + ++dark; /* increase intensity if all components are either bright or * dark and at least one is bright */ - dark = (val[0] <= 85) + (val[1] <= 85) + (val[2] <= 85); - bright = (val[0] > 171) + (val[1] > 171) + (val[2] > 171); + bright = (rgb[0] > 171) + (rgb[1] > 171) + (rgb[2] > 171); if (bright + dark == 3 && dark != 3) { - *attr |= FOREGROUND_INTENSITY; + attr |= FOREGROUND_INTENSITY; } - return str; + return attr; } -static char *process_bg_24bit(char *str, WORD *attr) +/* 24-bit colour */ +static char *process_24bit(char *str, WORD *attr) { - WORD t = 0; - char *s = process_fg_24bit(str, &t); + int count = 0; + int rgb[3] = {0, 0, 0}; - *attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); - *attr |= t << 4; + do { + rgb[count++] = strtol(str, (char **)&str, 10); + ++str; + } while (*(str-1) == ';' && count < 3); - return s; + *attr = rgb_to_console(rgb); + + return str; } -static unsigned char colour_1bit[8] = { +static const unsigned char colour_1bit[16] = { /* Black */ 0, /* Red */ FOREGROUND_RED, /* Green */ FOREGROUND_GREEN, @@ -312,100 +316,69 @@ static unsigned char colour_1bit[8] = { /* Blue */ FOREGROUND_BLUE, /* Magenta */ FOREGROUND_RED | FOREGROUND_BLUE, /* Cyan */ FOREGROUND_GREEN | FOREGROUND_BLUE, - /* White */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE + /* White */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + /* ... and again but brighter */ + FOREGROUND_INTENSITY, + FOREGROUND_RED | FOREGROUND_INTENSITY, + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_INTENSITY, + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; /* 8-bit colour */ -static char *process_fg_8bit(char *str, WORD *attr) +static char *process_8bit(char *str, WORD *attr) { - int dark, bright = 0; int val = strtol(str, &str, 10); - int r, g, b; - *attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); if (val < 16) { - *attr |= colour_1bit[val % 8]; - if (val > 8) - *attr |= FOREGROUND_INTENSITY; + *attr = colour_1bit[val]; } else if (val < 232) { + int i, rgb[3]; + val -= 16; - r = val / 36 % 6; - g = val / 6 % 6; - b = val % 6; - - if (r > 1) - *attr |= FOREGROUND_RED; - if (g > 1) - *attr |= FOREGROUND_GREEN; - if (b > 1) - *attr |= FOREGROUND_BLUE; - - /* increase intensity if all components are either bright or - * dark and at least one is bright */ - dark = (r <= 1) + (g <= 1) + (b <= 1); - bright = (r >= 4) + (g >= 4) + (b >= 4); - if (bright + dark == 3 && dark != 3) { - *attr |= FOREGROUND_INTENSITY; + for (i = 2; i >= 0; --i) { + rgb[i] = (val % 6) * 42 + 21; + val /= 6; } + + *attr = rgb_to_console(rgb); } else if (val < 238) { /* black */ + *attr = 0; } else if (val < 244) { /* bright black */ - *attr |= FOREGROUND_INTENSITY; + *attr = FOREGROUND_INTENSITY; } else if (val < 250) { /* white */ - *attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + *attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; } - else { + else if (val < 256) { /* bright white */ - *attr |= FOREGROUND_INTENSITY; - *attr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + *attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | + FOREGROUND_INTENSITY; } return str; } -static char *process_bg_8bit(char *str, WORD *attr) -{ - WORD t = 0; - char *s = process_fg_8bit(str, &t); - - *attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); - *attr |= t << 4; - - return s; -} - -static char *process_fg(char *str, WORD *attr) +static char *process_colour(char *str, WORD *attr) { long val = strtol(str, (char **)&str, 10); - switch (val) { - case 2: - str = process_fg_24bit(++str, attr); - break; - case 5: - str = process_fg_8bit(++str, attr); - break; - default: - break; - } - - return str; -} -static char *process_bg(char *str, WORD *attr) -{ - long val = strtol(str, (char **)&str, 10); + *attr = -1; /* error return */ switch (val) { case 2: - str = process_bg_24bit(++str, attr); + str = process_24bit(++str, attr); break; case 5: - str = process_bg_8bit(++str, attr); + str = process_8bit(++str, attr); break; default: break; @@ -422,7 +395,7 @@ static char *process_escape(char *pos) char *str, *func; char *bel; size_t len; - WORD attr = get_console_attr(); + WORD t, attr = get_console_attr(); int invert = FALSE; static int inverse = 0; @@ -511,7 +484,11 @@ static char *process_escape(char *pos) attr |= colour_1bit[val - 30]; break; case 38: /* 8/24 bit */ - str = process_fg(++str, &attr); + str = process_colour(++str, &t); + if (t != -1) { + attr &= ~(FOREGROUND_ALL|FOREGROUND_INTENSITY); + attr |= t; + } break; case 39: /* reset */ attr &= ~FOREGROUND_ALL; @@ -531,7 +508,11 @@ static char *process_escape(char *pos) attr |= colour_1bit[val - 40] << 4; break; case 48: /* 8/24 bit */ - str = process_bg(++str, &attr); + str = process_colour(++str, &t); + if (t != -1) { + attr &= ~(BACKGROUND_ALL|BACKGROUND_INTENSITY); + attr |= t << 4; + } break; case 49: /* reset */ attr &= ~BACKGROUND_ALL; -- cgit v1.2.3-55-g6feb