diff --git a/watch.c b/watch.c index 860d7021..c202ed7b 100644 --- a/watch.c +++ b/watch.c @@ -137,7 +137,41 @@ static void init_ansi_colors(void) } -static int set_ansi_attribute(const int attrib) +static int process_ansi_color_escape_sequence(char** escape_sequence) { + // process SGR ANSI color escape sequence + // Eg 8-bit + // 38;5;⟨n⟩ (set fg color to n) + // 48;5;⟨n⟩ (set bg color to n) + // + // Eg 24-bit (not yet implemented) + // ESC[ 38;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB foreground color + // ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB background color + int num; + + if ((*escape_sequence)[0] != ';') + return 0; /* not understood */ + + if ((*escape_sequence)[1] == '5') { + // 8 bit! ANSI specifies a predefined set of 256 colors here. + if ((*escape_sequence)[2] != ';') + return 0; /* not understood */ + num = strtol((*escape_sequence) + 3, escape_sequence, 10); + if (num >= 0 && num <= 7) { + // 0-7 are standard colors same as SGR 30-37 + return num + 1; + } + + // Remainder aren't yet implemented + // 8- 15: high intensity colors (as in ESC [ 90–97 m) + // 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) + // 232-255: grayscale from black to white in 24 steps + } + + return 0; /* not understood */ +} + + +static int set_ansi_attribute(const int attrib, char** escape_sequence) { switch (attrib) { case -1: /* restore last settings */ @@ -185,12 +219,24 @@ static int set_ansi_attribute(const int attrib) case 27: /* unset inversed */ attributes &= ~A_REVERSE; break; - case 39: - fg_col = 0; - break; - case 49: - bg_col = 0; - break; + case 38: + fg_col = process_ansi_color_escape_sequence(escape_sequence); + if (fg_col == 0) { + return 0; /* not understood */ + } + break; + case 39: + fg_col = 0; + break; + case 48: + bg_col = process_ansi_color_escape_sequence(escape_sequence); + if (bg_col == 0) { + return 0; /* not understood */ + } + break; + case 49: + bg_col = 0; + break; default: if (attrib >= 30 && attrib <= 37) { /* set foreground color */ fg_col = attrib - 30 + 1; @@ -207,6 +253,7 @@ static int set_ansi_attribute(const int attrib) static void process_ansi(FILE * fp) { int i, c; + int ansi_attribute; char buf[MAX_ANSIBUF]; char *numstart, *endptr; @@ -237,10 +284,11 @@ static void process_ansi(FILE * fp) /* Special case of [m */ if (buf[0] == '\0') - set_ansi_attribute(0); + set_ansi_attribute(0, NULL); for (endptr = numstart = buf; *endptr != '\0'; numstart = endptr + 1) { - if (!set_ansi_attribute(strtol(numstart, &endptr, 10))) + ansi_attribute = strtol(numstart, &endptr, 10); + if (!set_ansi_attribute(ansi_attribute, &endptr)) break; } } @@ -522,7 +570,7 @@ static int run_command(char *restrict command, char **restrict command_argv) for (y = show_title; y < height; y++) { int eolseen = 0, tabpending = 0, tabwaspending = 0; if (flags & WATCH_COLOR) - set_ansi_attribute(-1); + set_ansi_attribute(-1, NULL); #ifdef WITH_WATCH8BIT wint_t carry = WEOF; #endif @@ -535,7 +583,7 @@ static int run_command(char *restrict command, char **restrict command_argv) int attr = 0; if (tabwaspending && (flags & WATCH_COLOR)) - set_ansi_attribute(-1); + set_ansi_attribute(-1, NULL); tabwaspending = 0; if (!eolseen) {