From 2494a2e0828804eeca0da47d0c35e29c9a5be183 Mon Sep 17 00:00:00 2001 From: Mark Nudelman Date: Tue, 18 Oct 2022 16:15:27 -0700 Subject: [PATCH 24/48] Handle fg and bg colors. --- lesstest/display.c | 46 ++++++++++--------------- lesstest/lesstest.h | 1 + lesstest/lt_screen.c | 80 ++++++++++++++++++++++++++++++++------------ lesstest/lt_types.h | 3 +- lesstest/term.c | 1 + 5 files changed, 81 insertions(+), 50 deletions(-) diff --git a/lesstest/display.c b/lesstest/display.c index 54ae7c5..2a8f030 100644 --- a/lesstest/display.c +++ b/lesstest/display.c @@ -3,16 +3,12 @@ extern TermInfo terminfo; -static void display_attr(Attr attr) { - static Attr prev_attr = 0; - if (prev_attr & ATTR_STANDOUT) - printf("%s", terminfo.exit_standout); - if (prev_attr & ATTR_BLINK) - printf("%s", terminfo.exit_blink); - if (prev_attr & ATTR_BOLD) - printf("%s", terminfo.exit_bold); - if (prev_attr & ATTR_UNDERLINE) - printf("%s", terminfo.exit_underline); +static void display_attr_color(Attr attr, Color fg_color, Color bg_color) { + printf("%s", terminfo.exit_all_modes); + if (fg_color != NULL_COLOR) + printf("\33[%dm", fg_color); + if (bg_color != NULL_COLOR) + printf("\33[%dm", bg_color); if (attr & ATTR_UNDERLINE) printf("%s", terminfo.enter_underline); if (attr & ATTR_BOLD) @@ -21,14 +17,6 @@ static void display_attr(Attr attr) { printf("%s", terminfo.enter_blink); if (attr & ATTR_STANDOUT) printf("%s", terminfo.enter_standout); - prev_attr = attr; -} - -static void display_color(Color color) { - if (color == NULL_COLOR) - printf("\33[m"); - else - printf("\33[%dm", color); } void display_screen(const byte* img, int imglen, int screen_width, int screen_height) { @@ -38,7 +26,8 @@ void display_screen(const byte* img, int imglen, int screen_width, int screen_he int cursor_y = 0; int literal = 0; Attr curr_attr = 0; - Color curr_color = NULL_COLOR; + Color curr_fg_color = NULL_COLOR; + Color curr_bg_color = NULL_COLOR; while (imglen-- > 0) { wchar ch = load_wchar(&img); if (!literal) { @@ -48,15 +37,15 @@ void display_screen(const byte* img, int imglen, int screen_width, int screen_he continue; case LTS_CHAR_ATTR: curr_attr = *img++; - display_attr(curr_attr); - if (curr_color != NULL_COLOR) - display_color(curr_color); + display_attr_color(curr_attr, curr_fg_color, curr_bg_color); + continue; + case LTS_CHAR_FG_COLOR: + curr_fg_color = *img++; + display_attr_color(curr_attr, curr_fg_color, curr_bg_color); continue; - case LTS_CHAR_COLOR: - curr_color = *img++; - display_color(curr_color); - if (curr_attr != 0) - display_attr(curr_attr); + case LTS_CHAR_BG_COLOR: + curr_bg_color = *img++; + display_attr_color(curr_attr, curr_fg_color, curr_bg_color); continue; case LTS_CHAR_CURSOR: cursor_x = x; @@ -94,7 +83,8 @@ void display_screen_debug(const byte* img, int imglen, int screen_width, int scr literal = 1; continue; case LTS_CHAR_ATTR: - case LTS_CHAR_COLOR: + case LTS_CHAR_FG_COLOR: + case LTS_CHAR_BG_COLOR: x -= 2; // don't count LTS_CHAR or following byte literal = 1; break; diff --git a/lesstest/lesstest.h b/lesstest/lesstest.h index 93bbed3..dab0fa8 100644 --- a/lesstest/lesstest.h +++ b/lesstest/lesstest.h @@ -44,6 +44,7 @@ typedef struct TermInfo { char* exit_blink; char* enter_standout; char* exit_standout; + char* exit_all_modes; char* clear_screen; char* cursor_move; char* key_right; diff --git a/lesstest/lt_screen.c b/lesstest/lt_screen.c index 2805289..723a0e9 100644 --- a/lesstest/lt_screen.c +++ b/lesstest/lt_screen.c @@ -21,7 +21,8 @@ int usage(void) { typedef struct ScreenChar { wchar ch; Attr attr; - Color color; + Color fg_color; + Color bg_color; } ScreenChar; typedef struct ScreenState { @@ -31,7 +32,8 @@ typedef struct ScreenState { int cx; int cy; Attr curr_attr; - Color curr_color; + Color curr_fg_color; + Color curr_bg_color; int param_top; int params[MAX_PARAMS+1]; int in_esc; @@ -52,15 +54,19 @@ static void screen_init(void) { screen.cy = 0; screen.in_esc = 0; screen.curr_attr = 0; - screen.curr_color = NULL_COLOR; + screen.curr_fg_color = screen.curr_bg_color = NULL_COLOR; screen.param_top = -1; screen.params[0] = 0; } +static int num_params(void) { + return screen.param_top+1; +} + static void param_print(void) { int i; fprintf(stderr, "("); - for (i = 0; i <= screen.param_top; ++i) + for (i = 0; i < num_params(); ++i) fprintf(stderr, "%d ", screen.params[i]); fprintf(stderr, ")"); } @@ -76,7 +82,7 @@ static void param_clear(void) { } static int param_pop(void){ - if (screen.param_top < 0) + if (num_params() == 0) return -1; // missing param return screen.params[screen.param_top--]; } @@ -110,16 +116,17 @@ static int screen_incr(int* px, int* py) { return 1; } -static void screen_char_set(int x, int y, wchar ch, Attr attr, Color color) { +static void screen_char_set(int x, int y, wchar ch, Attr attr, Color fg_color, Color bg_color) { ScreenChar* sc = screen_char(x, y); sc->ch = ch; sc->attr = attr; - sc->color = color; + sc->fg_color = fg_color; + sc->bg_color = bg_color; } static int screen_clear(int x, int y, int count) { while (count-- > 0) { - screen_char_set(x, y, '_', 0, NULL_COLOR); + screen_char_set(x, y, '_', 0, NULL_COLOR, NULL_COLOR); screen_incr(&x, &y); } return 1; @@ -128,7 +135,8 @@ static int screen_clear(int x, int y, int count) { static int screen_read(int x, int y, int count) { //write(ttyout, "$|", 2); Attr attr = 0; - int color = NULL_COLOR; + int fg_color = NULL_COLOR; + int bg_color = NULL_COLOR; while (count-- > 0) { byte buf[32]; byte* bufp = buf; @@ -138,14 +146,19 @@ static int screen_read(int x, int y, int count) { *bufp++ = LTS_CHAR_ATTR; *bufp++ = attr; } - if (sc->color != color) { - color = sc->color; - *bufp++ = LTS_CHAR_COLOR; - *bufp++ = color; + if (sc->fg_color != fg_color) { + fg_color = sc->fg_color; + *bufp++ = LTS_CHAR_FG_COLOR; + *bufp++ = fg_color; + } + if (sc->bg_color != bg_color) { + bg_color = sc->bg_color; + *bufp++ = LTS_CHAR_BG_COLOR; + *bufp++ = bg_color; } if (x == screen.cx && y == screen.cy) *bufp++ = LTS_CHAR_CURSOR; - if (sc->ch == '\\' || sc->ch == LTS_CHAR_ATTR || sc->ch == LTS_CHAR_COLOR || sc->ch == LTS_CHAR_CURSOR) + if (sc->ch == '\\' || sc->ch == LTS_CHAR_ATTR || sc->ch == LTS_CHAR_FG_COLOR || sc->ch == LTS_CHAR_BG_COLOR || sc->ch == LTS_CHAR_CURSOR) *bufp++ = '\\'; store_wchar(&bufp, sc->ch); write(ttyout, buf, bufp-buf); @@ -199,9 +212,28 @@ static int screen_clear_attr(int attr) { } static int screen_set_color(int color) { - screen.curr_color = (color >= 0) ? color : NULL_COLOR; - if (verbose) fprintf(stderr, "[%d,%d] set_color(%d)=%d\n", screen.cx, screen.cy, color, screen.curr_color); - return 1; + int ret = 0; + switch (color) { + case 1: ret = screen_set_attr(ATTR_BOLD); break; + case 4: ret = screen_set_attr(ATTR_UNDERLINE); break; + case 5: + case 6: ret = screen_set_attr(ATTR_BLINK); break; + case 7: ret = screen_set_attr(ATTR_STANDOUT); break; + case 22: ret = screen_clear_attr(ATTR_BOLD); break; + case 24: ret = screen_clear_attr(ATTR_UNDERLINE); break; + default: + if (color < 0) + screen.curr_fg_color = screen.curr_bg_color = NULL_COLOR; + else if ((color >= 30 && color <= 37) || (color >= 90 && color <= 97)) + screen.curr_fg_color = color; + else if ((color >= 40 && color <= 47) || (color >= 100 && color <= 107)) + screen.curr_bg_color = color; + else + fprintf(stderr, "unrecognized color %d\n", color); + if (verbose) fprintf(stderr, "[%d,%d] set_color(%d)=%d/%d\n", screen.cx, screen.cy, color, screen.curr_fg_color, screen.curr_bg_color); + break; + } + return ret; } // ------------------------------------------------------------------ @@ -269,7 +301,13 @@ static int exec_esc(wchar ch) { case 'E': // exit bold/blink return screen_clear_attr(ATTR_BOLD|ATTR_BLINK); case 'm': // set color - return screen_set_color(param_pop()); + if (num_params() == 0) { + screen_set_color(-1); + } else { + while (num_params() > 0) + screen_set_color(param_pop()); + } + return 0; case '?': // print version string write(ttyout, version, strlen(version)); return 1; @@ -280,14 +318,14 @@ static int exec_esc(wchar ch) { static int add_char(wchar ch) { //if (verbose) fprintf(stderr, "add (%c) %lx at %d,%d\n", (char)ch, (long)ch, screen.cx, screen.cy); - screen_char_set(screen.cx, screen.cy, ch, screen.curr_attr, screen.curr_color); + screen_char_set(screen.cx, screen.cy, ch, screen.curr_attr, screen.curr_fg_color, screen.curr_bg_color); int fits = 1; int zero_width = (is_composing_char(ch) || (screen.cx > 0 && is_combining_char(screen_char(screen.cx-1,screen.cy)->ch, ch))); if (!zero_width) { fits = screen_incr(&screen.cx, &screen.cy); if (fits && is_wide_char(ch)) { - screen_char_set(screen.cx, screen.cy, 0, 0, NULL_COLOR); + screen_char_set(screen.cx, screen.cy, 0, 0, NULL_COLOR, NULL_COLOR); fits = screen_incr(&screen.cx, &screen.cy); } } @@ -303,7 +341,7 @@ static int process_char(wchar ch) { int ok = 1; if (screen.in_esc) { if (ch >= '0' && ch <= '9') { - int d = (screen.param_top < 0) ? 0 : screen.params[screen.param_top--]; + int d = (num_params() == 0) ? 0 : screen.params[screen.param_top--]; param_push(10 * d + ch - '0'); } else if (ch == ';') { param_push(0); diff --git a/lesstest/lt_types.h b/lesstest/lt_types.h index 2015582..a2cae31 100644 --- a/lesstest/lt_types.h +++ b/lesstest/lt_types.h @@ -21,7 +21,8 @@ typedef unsigned char Color; #define RUN_ERR 1 #define LTS_CHAR_ATTR '@' -#define LTS_CHAR_COLOR '$' +#define LTS_CHAR_FG_COLOR '$' +#define LTS_CHAR_BG_COLOR '!' #define LTS_CHAR_CURSOR '#' #define is_ascii(ch) ((ch) >= ' ' && (ch) < 0x7f) diff --git a/lesstest/term.c b/lesstest/term.c index db294a6..b244f3e 100644 --- a/lesstest/term.c +++ b/lesstest/term.c @@ -50,6 +50,7 @@ int setup_term(void) { setup_mode("us", "ue", &terminfo.enter_underline, &terminfo.exit_underline, &sp); setup_mode("md", "me", &terminfo.enter_bold, &terminfo.exit_bold, &sp); setup_mode("mb", "me", &terminfo.enter_blink, &terminfo.exit_blink, &sp); + terminfo.exit_all_modes = terminfo.exit_bold; terminfo.cursor_move = tgetstr("cm", &sp); if (terminfo.cursor_move == NULL) terminfo.cursor_move = ""; terminfo.clear_screen = tgetstr("cl", &sp); -- 2.27.0