From ae57646896bd218b1c5c3087d8937da635fb9ef7 Mon Sep 17 00:00:00 2001 From: Mark Nudelman Date: Wed, 12 Oct 2022 09:35:22 -0700 Subject: [PATCH 21/48] lesstest: add support for combining and composing chars. --- lesstest/display.c | 1 + lesstest/lt_screen.c | 11 ++++++++--- lesstest/parse.c | 1 + lesstest/pipeline.c | 4 ++-- lesstest/run.c | 5 +++-- lesstest/unicode.c | 23 +++++++++++++++++++++++ lesstest/wchar.h | 2 ++ 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/lesstest/display.c b/lesstest/display.c index 5243337..54ae7c5 100644 --- a/lesstest/display.c +++ b/lesstest/display.c @@ -119,6 +119,7 @@ void display_screen_debug(const byte* img, int imglen, int screen_width, int scr } void print_strings(const char* title, char* const* strings) { + if (1) return; /// fprintf(stderr, "%s:\n", title); char* const* s; for (s = strings; *s != NULL; ++s) { diff --git a/lesstest/lt_screen.c b/lesstest/lt_screen.c index 4bc1c50..6677650 100644 --- a/lesstest/lt_screen.c +++ b/lesstest/lt_screen.c @@ -277,10 +277,15 @@ 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); - int fits = screen_incr(&screen.cx, &screen.cy); - if (fits && is_wide_char(ch)) { - screen_char_set(screen.cx, screen.cy, 0, 0, NULL_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); + fits = screen_incr(&screen.cx, &screen.cy); + } } if (!fits) { // Wrap at bottom of screen = scroll screen.cx = 0; diff --git a/lesstest/parse.c b/lesstest/parse.c index 3d79a83..d1e8c74 100644 --- a/lesstest/parse.c +++ b/lesstest/parse.c @@ -100,6 +100,7 @@ int read_zline(FILE* fd, char* line, int line_len) { return nread; } +// Read the header of a .lt file (up to the R line). TestSetup* read_test_setup(FILE* fd, const char* less) { TestSetup* setup = new_test_setup(); int hdr_complete = 0; diff --git a/lesstest/pipeline.c b/lesstest/pipeline.c index 4122f4a..01fe15d 100644 --- a/lesstest/pipeline.c +++ b/lesstest/pipeline.c @@ -42,7 +42,7 @@ static void become_child_less(char* less, int argc, char* const* argv, char* con less_argv[less_argc++] = (argc > 1 || tempfile == NULL) ? arg : (char*) tempfile; } less_argv[less_argc] = NULL; - //if (verbose) { print_strings("less argv", less_argv); print_strings("less envp", envp); } + if (verbose) { print_strings("less argv", less_argv); print_strings("less envp", envp); } execve(less, less_argv, envp); fprintf(stderr, "cannot exec %s: %s\n", less, strerror(errno)); exit(1); @@ -74,7 +74,7 @@ static void become_child_screen(char* lt_screen, int screen_width, int screen_he if (1) screen_argv[screen_argc++] = "-q"; screen_argv[screen_argc] = NULL; - //if (verbose) print_strings("screen argv", screen_argv); + if (verbose) print_strings("screen argv", screen_argv); char* const screen_envp[] = { NULL }; execve(lt_screen, screen_argv, screen_envp); fprintf(stderr, "cannot exec %s: %s\n", lt_screen, strerror(errno)); diff --git a/lesstest/run.c b/lesstest/run.c index 25850d5..f35781f 100644 --- a/lesstest/run.c +++ b/lesstest/run.c @@ -178,7 +178,8 @@ static int run_test(TestSetup* setup, FILE* testfd) { return ok; } -// Should run in empty directory. +// Should be run in an empty temp directory; +// it creates its own files in the current directory. int run_testfile(const char* testfile, const char* less) { FILE* testfd = fopen(testfile, "r"); if (testfd == NULL) { @@ -187,7 +188,7 @@ int run_testfile(const char* testfile, const char* less) { } int tests = 0; int fails = 0; - for (;;) { + for (;;) { // might be multiple tests in one file TestSetup* setup = read_test_setup(testfd, less); if (setup == NULL) break; diff --git a/lesstest/unicode.c b/lesstest/unicode.c index beb9bfc..c2320a8 100644 --- a/lesstest/unicode.c +++ b/lesstest/unicode.c @@ -5,6 +5,15 @@ typedef struct wchar_range { wchar first, last; } wchar_range; static wchar_range wide_chars[] = { #include "../wide.uni" }; +static wchar_range compose_table[] = { +#include "../compose.uni" +}; +static wchar_range fmt_table[] = { +#include "../fmt.uni" +}; +static wchar_range comb_table[] = { + {0x0644,0x0622}, {0x0644,0x0623}, {0x0644,0x0625}, {0x0644,0x0627}, +}; static int is_in_table(wchar ch, wchar_range table[], int count) { if (ch < table[0].first) @@ -26,3 +35,17 @@ static int is_in_table(wchar ch, wchar_range table[], int count) { int is_wide_char(wchar ch) { return is_in_table(ch, wide_chars, countof(wide_chars)); } + +int is_composing_char(wchar ch) { + return is_in_table(ch, compose_table, countof(compose_table)) || + is_in_table(ch, fmt_table, countof(fmt_table)); +} + +int is_combining_char(wchar ch1, wchar ch2) { + for (int i = 0; i < countof(comb_table); i++) { + if (ch1 == comb_table[i].first && + ch2 == comb_table[i].last) + return 1; + } + return 0; +} diff --git a/lesstest/wchar.h b/lesstest/wchar.h index 0ffd541..84af5ee 100644 --- a/lesstest/wchar.h +++ b/lesstest/wchar.h @@ -3,3 +3,5 @@ void store_wchar(byte** p, wchar ch); wchar load_wchar(const byte** p); wchar read_wchar(int fd); int is_wide_char(wchar ch); +int is_composing_char(wchar ch); +int is_combining_char(wchar ch1, wchar ch2); -- 2.27.0