From 17f82a3e2161434cee1d05891396478308db19e0 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sat, 31 Jul 2010 20:51:24 +0200 Subject: [PATCH] Decode ESC color sequences in the plain renderer. Added functions for screen_char->color -> color_T conversion. --- src/document/plain/renderer.c | 92 ++++++++++++++++++++++++++++++++++- src/terminal/color.c | 86 ++++++++++++++++++++++++++++++++ src/terminal/color.h | 13 ++++- 3 files changed, 189 insertions(+), 2 deletions(-) diff --git a/src/document/plain/renderer.c b/src/document/plain/renderer.c index 98c0f26e5..be6eb85f7 100644 --- a/src/document/plain/renderer.c +++ b/src/document/plain/renderer.c @@ -5,6 +5,7 @@ #endif #include +#include #include #include "elinks.h" @@ -227,6 +228,87 @@ print_document_link(struct plain_renderer *renderer, int lineno, return len; } +static void +decode_esc_color(unsigned char *text, int *line_pos, int width, + struct screen_char *template, enum color_mode mode, + int *was_reversed) +{ + struct screen_char ch; + struct color_pair color; + char *buf, *tail, *begin, *end; + int k, foreground, background, f1, b1; /* , intensity; */ + + ++(*line_pos); + buf = (char *)&text[*line_pos]; + + if (*buf != '[') return; + ++buf; + ++(*line_pos); + + k = strspn(buf, "0123456789;"); + *line_pos += k; + if (!k || buf[k] != 'm') return; + + end = buf + k; + begin = tail = buf; + + get_screen_char_color(template, &color, 0, mode); + set_term_color(&ch, &color, 0, COLOR_MODE_16); + b1 = background = (ch.color[0] >> 4) & 7; + f1 = foreground = ch.color[0] & 7; + + while (tail < end) { + unsigned char kod = (unsigned char)strtol(begin, &tail, 10); + + begin = tail + 1; + switch (kod) { + case 0: + background = 0; + foreground = 7; + break; + case 7: + if (*was_reversed == 0) { + background = f1 & 7; + foreground = b1; + *was_reversed = 1; + } + break; + case 27: + if (*was_reversed == 1) { + background = f1 & 7; + foreground = b1; + *was_reversed = 0; + } + break; + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + foreground = kod - 30; + break; + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + background = kod - 40; + break; + default: + break; + } + } + color.background = get_term_color16(background); + color.foreground = get_term_color16(foreground); + set_term_color(template, &color, 0, mode); +} + static inline int add_document_line(struct plain_renderer *renderer, unsigned char *line, int line_width) @@ -235,8 +317,11 @@ add_document_line(struct plain_renderer *renderer, struct screen_char *template = &renderer->template; struct screen_char saved_renderer_template = *template; struct screen_char *pos, *startpos; + struct document_options *doc_opts = &document->options; + int was_reversed = 0; + #ifdef CONFIG_UTF8 - int utf8 = document->options.utf8; + int utf8 = doc_opts->utf8; #endif /* CONFIG_UTF8 */ int cells = 0; int lineno = renderer->lineno; @@ -411,6 +496,11 @@ add_document_line(struct plain_renderer *renderer, /* Handle _^Hx^Hx as both bold and underlined */ if (template->attr) template->attr |= pos->attr; + } else if (line_char == 27) { + decode_esc_color(line, &line_pos, width, + &saved_renderer_template, + doc_opts->color_mode, &was_reversed); + *template = saved_renderer_template; } else { int added_chars = 0; diff --git a/src/terminal/color.c b/src/terminal/color.c index 9b13ac6d1..5beb9e4c1 100644 --- a/src/terminal/color.c +++ b/src/terminal/color.c @@ -288,6 +288,92 @@ set_term_color16(struct screen_char *schar, enum color_flags flags, schar->color[0] = (bg << 4 | fg); } +color_T +get_term_color16(unsigned int index) +{ + if (index > 15) return 0; + return ((palette16[index].r << 16) | + (palette16[index].g << 8) | + palette16[index].b); +} + +#ifdef CONFIG_88_COLORS +color_T +get_term_color88(unsigned int index) +{ + if (index > 87) return 0; + return ((palette88[index].r << 16) | + (palette88[index].g << 8) | + palette88[index].b); +} +#endif + +#ifdef CONFIG_256_COLORS +color_T +get_term_color256(unsigned int index) +{ + if (index > 255) return 0; + return ((palette256[index].r << 16) | + (palette256[index].g << 8) | + palette256[index].b); +} +#endif + +void +get_screen_char_color(struct screen_char *schar, struct color_pair *pair, + enum color_flags flags, enum color_mode color_mode) +{ + unsigned char fg, bg; + + assert(color_mode >= COLOR_MODE_DUMP && color_mode < COLOR_MODES); + + /* Options for the various color modes. */ + switch (color_mode) { + + case COLOR_MODE_MONO: + break; + + default: + /* If the desired color mode was not compiled in, + * use 16 colors. */ + case COLOR_MODE_16: + bg = (schar->color[0] >> 4) & 7; + fg = schar->color[0]; + pair->foreground = get_term_color16(fg); + pair->background = get_term_color16(bg); + break; +#ifdef CONFIG_88_COLORS + case COLOR_MODE_88: + pair->foreground = get_term_color88(schar->color[0]); + pair->background = get_term_color88(schar->color[1]); + break; +#endif +#ifdef CONFIG_256_COLORS + case COLOR_MODE_256: + pair->foreground = get_term_color256(schar->color[0]); + pair->background = get_term_color256(schar->color[1]); + break; +#endif +#ifdef CONFIG_TRUE_COLOR + case COLOR_MODE_TRUE_COLOR: + pair->foreground = ((schar->color[0] << 16) + | (schar->color[1] << 8) + | schar->color[2]); + + pair->background = ((schar->color[3] << 16) + | (schar->color[4] << 8) + | schar->color[5]); + break; +#endif + case COLOR_MODE_DUMP: + break; + + case COLOR_MODES: + /* This is caught by the assert() above. */ + break; + } +} + void set_term_color(struct screen_char *schar, struct color_pair *pair, enum color_flags flags, enum color_mode color_mode) diff --git a/src/terminal/color.h b/src/terminal/color.h index e466bf7a8..1d4c28348 100644 --- a/src/terminal/color.h +++ b/src/terminal/color.h @@ -1,7 +1,7 @@ #ifndef EL__TERMINAL_COLOR_H #define EL__TERMINAL_COLOR_H -struct color_pair; +#include "util/color.h" struct screen_char; /* Terminal color encoding: */ @@ -72,6 +72,17 @@ void set_term_color16(struct screen_char *schar, enum color_flags flags, * * XXX: @a schar may not be NULL and is modified adding stuff like * boldness. */ + +color_T get_term_color16(unsigned int index); +#ifdef CONFIG_88_COLORS +color_T get_term_color88(unsigned int index); +#endif +#ifdef CONFIG_256_COLORS +color_T get_term_color256(unsigned int index); +#endif + +void get_screen_char_color(struct screen_char *schar, struct color_pair *pair, + enum color_flags flags, enum color_mode color_mode); void set_term_color(struct screen_char *schar, struct color_pair *pair, enum color_flags flags, enum color_mode mode);