less/backport-makecheck-0017-lesstest-handle-colored-text-with-less-R.patch

304 lines
8.8 KiB
Diff

From 68932004a8eb935f18732913ca904e466f320753 Mon Sep 17 00:00:00 2001
From: Mark Nudelman <markn@greenwoodsoftware.com>
Date: Mon, 10 Oct 2022 12:31:36 -0700
Subject: [PATCH 11/48] lesstest: handle colored text with less -R.
---
lesstest/display.c | 33 ++++++++++++---------
lesstest/lt_screen.c | 68 ++++++++++++++++++++++++++------------------
lesstest/lt_types.h | 6 ++++
lesstest/runtest | 3 +-
4 files changed, 68 insertions(+), 42 deletions(-)
diff --git a/lesstest/display.c b/lesstest/display.c
index 5c9355e..a7e1954 100644
--- a/lesstest/display.c
+++ b/lesstest/display.c
@@ -5,8 +5,6 @@ extern TermInfo terminfo;
static void display_attr(Attr attr) {
static Attr prev_attr = 0;
- if (attr == prev_attr)
- return;
if (prev_attr & ATTR_STANDOUT)
printf("%s", terminfo.exit_standout);
if (prev_attr & ATTR_BLINK)
@@ -26,8 +24,11 @@ static void display_attr(Attr attr) {
prev_attr = attr;
}
-static void display_color(Color fg_color, Color bg_color) {
-printf("{%x/%x}", fg_color, bg_color);
+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, int move_cursor) {
@@ -36,22 +37,28 @@ void display_screen(const byte* img, int imglen, int screen_width, int screen_he
int cursor_x = 0;
int cursor_y = 0;
int literal = 0;
+ Attr curr_attr = 0;
+ Color curr_color = NULL_COLOR;
while (imglen-- > 0) {
wchar ch = load_wchar(&img);
if (!literal) {
- if (ch == '\\') {
+ switch (ch) {
+ case '\\':
literal = 1;
continue;
- } else if (ch == '@') {
- Attr attr = *img++;
- display_attr(attr);
+ case LTS_CHAR_ATTR:
+ curr_attr = *img++;
+ display_attr(curr_attr);
+ if (curr_color != NULL_COLOR)
+ display_color(curr_color);
continue;
- } else if (ch == '$') {
- Color fg_color = *img++;
- Color bg_color = *img++;
- display_color(fg_color, bg_color);
+ case LTS_CHAR_COLOR:
+ curr_color = *img++;
+ display_color(curr_color);
+ if (curr_attr != 0)
+ display_attr(curr_attr);
continue;
- } else if (ch == '#') {
+ case LTS_CHAR_CURSOR:
cursor_x = x;
cursor_y = y;
continue;
diff --git a/lesstest/lt_screen.c b/lesstest/lt_screen.c
index 3574320..6b1fde4 100644
--- a/lesstest/lt_screen.c
+++ b/lesstest/lt_screen.c
@@ -9,7 +9,7 @@
static const char version[] = "lt_screen|v=1";
int usage(void) {
- fprintf(stderr, "usage: lt_screen\n");
+ fprintf(stderr, "usage: lt_screen [-w width] [-h height] [-qv]\n");
return 0;
}
@@ -20,8 +20,7 @@ int usage(void) {
typedef struct ScreenChar {
wchar ch;
Attr attr;
- Color fg_color;
- Color bg_color;
+ Color color;
} ScreenChar;
typedef struct ScreenState {
@@ -31,8 +30,7 @@ typedef struct ScreenState {
int cx;
int cy;
Attr curr_attr;
- Color curr_fg_color;
- Color curr_bg_color;
+ Color curr_color;
int param_top;
int params[MAX_PARAMS+1];
int in_esc;
@@ -53,7 +51,7 @@ static void screen_init(void) {
screen.cy = 0;
screen.in_esc = 0;
screen.curr_attr = 0;
- screen.curr_fg_color = screen.curr_bg_color = 0;
+ screen.curr_color = NULL_COLOR;
screen.param_top = -1;
screen.params[0] = 0;
}
@@ -74,7 +72,7 @@ static void param_push(int v) {
static int param_pop(void){
if (screen.param_top < 0)
- return 0; // missing param is assumed to be 0
+ return -1; // missing param
return screen.params[screen.param_top--];
}
@@ -107,17 +105,16 @@ static int screen_incr(int* px, int* py) {
return 1;
}
-static void screen_char_set(int x, int y, wchar ch, Attr attr, Color fg_color, Color bg_color) {
+static void screen_char_set(int x, int y, wchar ch, Attr attr, Color color) {
ScreenChar* sc = screen_char(x, y);
sc->ch = ch;
sc->attr = attr;
- sc->fg_color = fg_color;
- sc->bg_color = bg_color;
+ sc->color = color;
}
static int screen_clear(int x, int y, int count) {
while (count-- > 0) {
- screen_char_set(x, y, '_', 0, 0, 0);
+ screen_char_set(x, y, '_', 0, NULL_COLOR);
screen_incr(&x, &y);
}
return 1;
@@ -125,28 +122,25 @@ static int screen_clear(int x, int y, int count) {
static int screen_read(int x, int y, int count) {
//write(ttyout, "$|", 2);
- int attr = 0;
- int fg_color = 0;
- int bg_color = 0;
+ Attr attr = 0;
+ int color = NULL_COLOR;
while (count-- > 0) {
byte buf[32];
byte* bufp = buf;
ScreenChar* sc = screen_char(x, y);
if (sc->attr != attr) {
attr = sc->attr;
- *bufp++ = '@';
+ *bufp++ = LTS_CHAR_ATTR;
*bufp++ = attr;
}
- if (sc->fg_color != fg_color || sc->bg_color != bg_color) {
- fg_color = sc->fg_color;
- bg_color = sc->bg_color;
- *bufp++ = '$';
- *bufp++ = fg_color;
- *bufp++ = bg_color;
+ if (sc->color != color) {
+ color = sc->color;
+ *bufp++ = LTS_CHAR_COLOR;
+ *bufp++ = color;
}
if (x == screen.cx && y == screen.cy)
- *bufp++ = '#';
- if (sc->ch == '@' || sc->ch == '$' || sc->ch == '\\' || sc->ch == '#')
+ *bufp++ = LTS_CHAR_CURSOR;
+ if (sc->ch == '\\' || sc->ch == LTS_CHAR_ATTR || sc->ch == LTS_CHAR_COLOR || sc->ch == LTS_CHAR_CURSOR)
*bufp++ = '\\';
store_wchar(&bufp, sc->ch);
write(ttyout, buf, bufp-buf);
@@ -189,12 +183,20 @@ static int screen_rscroll(void) {
static int screen_set_attr(int attr) {
screen.curr_attr |= attr;
- return 0;
+ if (verbose) fprintf(stderr, "[%d,%d] set_attr(%d)=%d\n", screen.cx, screen.cy, attr, screen.curr_attr);
+ return 1;
}
static int screen_clear_attr(int attr) {
screen.curr_attr &= ~attr;
- return 0;
+ if (verbose) fprintf(stderr, "[%d,%d] clr_attr(%d)=%d\n", screen.cx, screen.cy, attr, screen.curr_attr);
+ return 1;
+}
+
+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;
}
// ------------------------------------------------------------------
@@ -223,10 +225,15 @@ static int exec_esc(wchar ch) {
count = param_pop();
y = param_pop();
x = param_pop();
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (count < 0) count = 0;
return screen_read(x, y, count);
case 'j': // jump cursor to (N1,N2)
y = param_pop();
x = param_pop();
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
return screen_move(x, y);
case 'g': // visual bell
return 0;
@@ -256,6 +263,8 @@ static int exec_esc(wchar ch) {
return screen_clear_attr(ATTR_BLINK);
case 'E': // exit bold/blink
return screen_clear_attr(ATTR_BOLD|ATTR_BLINK);
+ case 'm': // set color
+ return screen_set_color(param_pop());
case '?': // print version string
write(ttyout, version, strlen(version));
return 1;
@@ -266,10 +275,10 @@ 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_fg_color, screen.curr_bg_color);
+ screen_char_set(screen.cx, screen.cy, ch, screen.curr_attr, screen.curr_color);
int fits = screen_incr(&screen.cx, &screen.cy);
if (fits && is_wide_char(ch)) {
- screen_char_set(screen.cx, screen.cy, 0, 0, 0, 0);
+ screen_char_set(screen.cx, screen.cy, 0, 0, NULL_COLOR);
fits = screen_incr(&screen.cx, &screen.cy);
}
if (!fits) { // Wrap at bottom of screen = scroll
@@ -284,9 +293,12 @@ static int process_char(wchar ch) {
int ok = 1;
if (screen.in_esc) {
if (ch >= '0' && ch <= '9') {
- param_push(10 * param_pop() + ch - '0');
+ int d = (screen.param_top < 0) ? 0 : screen.params[screen.param_top--];
+ param_push(10 * d + ch - '0');
} else if (ch == ';') {
param_push(0);
+ } else if (ch == '[') {
+ ; // ANSI sequence
} else {
screen.in_esc = 0;
ok = exec_esc(ch);
diff --git a/lesstest/lt_types.h b/lesstest/lt_types.h
index 2b3c1bc..3f98376 100644
--- a/lesstest/lt_types.h
+++ b/lesstest/lt_types.h
@@ -5,6 +5,8 @@ typedef unsigned char byte;
typedef unsigned char Attr;
typedef unsigned char Color;
+#define NULL_COLOR ((Color)0xff)
+
#define ATTR_BOLD (1<<0)
#define ATTR_UNDERLINE (1<<1)
#define ATTR_STANDOUT (1<<2)
@@ -18,6 +20,10 @@ typedef unsigned char Color;
#define RUN_OK 0
#define RUN_ERR 1
+#define LTS_CHAR_ATTR '@'
+#define LTS_CHAR_COLOR '$'
+#define LTS_CHAR_CURSOR '#'
+
#define is_ascii(ch) ((ch) >= ' ' && (ch) < 0x7f)
#define pr_ascii(ch) (is_ascii(ch) ? ((char)ch) : '.')
diff --git a/lesstest/runtest b/lesstest/runtest
index fe7fcab..2a39047 100755
--- a/lesstest/runtest
+++ b/lesstest/runtest
@@ -59,7 +59,8 @@ sub run {
print "ERR cannot open $file\n";
return 1;
}
- print "TEST $file\n";
+ my ($basename) = $file =~ m|^.*/([^/]+)$|;
+ print "TEST $basename\n";
my $cmd = "$lesstest $lt_opts -s '$lt_screen' -t '$file' '$less'";
my $err = system $cmd;
if ($err) {
--
2.27.0