diff options
92 files changed, 5026 insertions, 5023 deletions
@@ -1,12 +1,13 @@ -# term +# wsap_vtcore -term is a headless terminal core: the parser, screen ring, logical-line -history store, write core, and viewport snapshots. It is a C11 library -with no dependency but libm and, on POSIX, the thread library (`-pthread`). +wsap_vtcore is a headless terminal core: the parser, screen ring, +logical-line history store, write core, and viewport snapshots. It is a C11 +library with no dependency but libm and, on POSIX, the thread library +(`-pthread`). | Path | Contents | | --- | --- | -| `include/term/` | The public headers: `term.h`, and the header-only `unicode/` | +| `include/wsap_vtcore/` | The public headers: `wsap_vtcore.h`, and the header-only `unicode/` | | `src/` | The core. Its headers are private. | | `tests/` | Unit, model, fuzz, and portability tests, and the Kitty parser suite | | `benchmarks/` | `term-write-bench`, `term-resize-bench`, and `hist-bench` | @@ -18,20 +19,20 @@ with no dependency but libm and, on POSIX, the thread library (`-pthread`). Pick one of these: -- **Meson subproject**: `dependency('term')`, or - `subproject('term').get_variable('term_dep')`. The `arch_flag` option - sets the lowest instruction set, such as `-march=x86-64-v3`. +- **Meson subproject**: `dependency('wsap_vtcore')`, or + `subproject('wsap_vtcore').get_variable('wsap_vtcore_dep')`. The `arch_flag` + option sets the lowest instruction set, such as `-march=x86-64-v3`. - **Amalgamation**: run `tools/amalgamate.py . OUT`. It writes - `OUT/term.c` and `OUT/term.h`. Compile `term.c` with any C11 compiler - and link libm and the thread library: `cc -std=c11 -pthread -c term.c` - on POSIX. A Rust `build.rs` needs one - `cc::Build::new().file("term.c").compile("term")`. + `OUT/wsap_vtcore.c` and `OUT/wsap_vtcore.h`. Compile `wsap_vtcore.c` with any + C11 compiler and link libm and the thread library: + `cc -std=c11 -pthread -c wsap_vtcore.c` on POSIX. A Rust `build.rs` needs one + `cc::Build::new().file("wsap_vtcore.c").compile("wsap_vtcore")`. - **Sources**: compile `src/*.c` and `src/osc/*.c` once, with `src` and - `include/term` on the include path. Link the thread library too. + `include/wsap_vtcore` on the include path. Link the thread library too. The library needs nothing else. On Windows the writer lock is an SRWLOCK from the system library, so it needs no extra link. The `*-amalgamation` -tests run the term tests against the generated `term.c`, and +tests run the wsap_vtcore tests against the generated `wsap_vtcore.c`, and `term-cross-test` compiles it for aarch64, macOS, and Windows. ### SIMD level @@ -41,10 +42,10 @@ scroll and line-feed output runs 8 to 30 times slower. The build needs no flags to get them: - On x86-64 with GCC or Clang, each kernel compiles at every level with - a target attribute. The first `term_new()` picks the highest level the + a target attribute. The first `wsap_vtcore_new()` picks the highest level the CPU supports. The levels are `base` (x86-64), `avx2` (x86-64-v3), and - `avx512` (x86-64-v4 with VBMI and VBMI2). `term_isa()` names the level - in use. Set `TERM_HEADLESS_ISA` to a lower level to force it. + `avx512` (x86-64-v4 with VBMI and VBMI2). `wsap_vtcore_isa()` names the level + in use. Set `WSAP_VTCORE_ISA` to a lower level to force it. - `-march` sets the lowest level. The checks for that level and below become constants, and their kernels inline into their callers. - aarch64 always has NEON, so it needs no choice at run time. @@ -52,31 +53,31 @@ no flags to get them: `simd.h` states the rules for a new kernel. -- `term.h` is the only header a host includes. A host writes - `#include <term/term.h>`. The package adds only the include directory, - so `term.h` from another library, such as ncurses, is not shadowed. The - header includes `term_input.h` and `term_types.h`. It compiles as C11 - and as C++. -- Every global symbol starts with `term_`. The library builds with hidden - symbols, so a shared build exports only the `TERM_API` functions of - `term.h`. `term-symbols-test` checks both. +- `wsap_vtcore.h` is the only header a host includes. A host writes + `#include <wsap_vtcore/wsap_vtcore.h>`. The package adds only the include + directory, so `wsap_vtcore.h` from another library, such as ncurses, is not + shadowed. The header includes `wsap_vtcore_input.h` and + `wsap_vtcore_types.h`. It compiles as C11 and as C++. +- Every global symbol starts with `wsap_vtcore_`. The library builds with hidden + symbols, so a shared build exports only the `WSAP_VTCORE_API` functions of + `wsap_vtcore.h`. `term-symbols-test` checks both. - Any thread can call any function. Calls on one terminal run one at a - time. `term.h` states the rules. -- The `static inline` helpers (`term_color_*`, `term_view_color`, - `term_attr_underline`) only decode documented bit layouts. A binding + time. `wsap_vtcore.h` states the rules. +- The `static inline` helpers (`wsap_vtcore_color_*`, `wsap_vtcore_view_color`, + `wsap_vtcore_attr_underline`) only decode documented bit layouts. A binding generator such as bindgen skips them. Mirror them in the binding, or use the generator's static-function wrappers. A host wires the terminal in four places: -1. Create it with `term_new()`. Set `term_options.callbacks.reply` to - send replies to the program. Set `term_options.name` to the name - programs read with XTVERSION and XTGETTCAP. It defaults to `term`. -2. Feed program output with `term_feed()`. -3. Translate key and mouse events into `struct term_key_event` and - `struct term_mouse_event`. Encode them with `term_input_encode_key()` - and `term_input_encode_mouse()`, and send the bytes to the program. -4. Paint from a `struct term_snapshot`. The terminal gives code points, +1. Create it with `wsap_vtcore_new()`. Set `wsap_vtcore_options.callbacks.reply` to + send replies to the program. Set `wsap_vtcore_options.name` to the name + programs read with XTVERSION and XTGETTCAP. It defaults to `wsap_vtcore`. +2. Feed program output with `wsap_vtcore_feed()`. +3. Translate key and mouse events into `struct wsap_vtcore_key_event` and + `struct wsap_vtcore_mouse_event`. Encode them with `wsap_vtcore_input_encode_key()` + and `wsap_vtcore_input_encode_mouse()`, and send the bytes to the program. +4. Paint from a `struct wsap_vtcore_snapshot`. The terminal gives code points, colors, and attributes. The host shapes and draws the glyphs. ## Files and responsibilities @@ -138,11 +139,11 @@ Snapshot capture makes the counts exact for lines in the view. Counts above 254 rows use a separate cache. That cache grows only when a visited line needs it. -`term_snapshot_update` takes a mutable terminal. +`wsap_vtcore_snapshot_update` takes a mutable terminal. It updates history query metadata before it copies the view. Snapshot getters and history getters do not change terminal state. Renderers do not read terminal memory directly. Renderers read an -immutable snapshot (`struct term_snapshot`). +immutable snapshot (`struct wsap_vtcore_snapshot`). Snapshots track row keys based on row content identities. When output scrolls, snapshots detect the scroll distance `k`. Renderers shift existing pixels and draw records by `k` rows and paint diff --git a/benchmarks/hist_bench.c b/benchmarks/hist_bench.c index 2cf5608..bf3d1ca 100644 --- a/benchmarks/hist_bench.c +++ b/benchmarks/hist_bench.c @@ -14,7 +14,7 @@ static double now(void) /* Rows shaped like the term-write-bench lines that scroll into history. */ static int make_row(const char *name, struct cell *row) { - struct cell d = { ' ', TERM_COLOR_FG, TERM_COLOR_BG, 0, 0 }; + struct cell d = { ' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, 0, 0 }; int n = 0; if (!strcmp(name, "ascii-row")) { const char *s = "The quick brown fox jumps over the lazy dog. 0123456789"; @@ -37,15 +37,15 @@ static int make_row(const char *name, struct cell *row) row[n] = d; row[n].c = (uint8_t)s[n]; if (n < 3) - row[n].fg = term_color_index(1); + row[n].fg = wsap_vtcore_color_index(1); if (n > 3) - row[n].fg = term_color_rgb(12, 34, 56); + row[n].fg = wsap_vtcore_color_rgb(12, 34, 56); } } else if (!strcmp(name, "fg-char-row")) { for (; n < 120; n++) { row[n] = d; row[n].c = 'a' + (uint32_t)(n % 26); - row[n].fg = term_color_rgb((uint8_t)n, (uint8_t)(n * 3), (uint8_t)(n * 7)); + row[n].fg = wsap_vtcore_color_rgb((uint8_t)n, (uint8_t)(n * 3), (uint8_t)(n * 7)); } } return n; @@ -55,7 +55,7 @@ int main(int argc, char **argv) { int iterations = argc > 1 ? atoi(argv[1]) : 10000000; struct hist h; - if (!term_hist_init(&h, 10000, 8 * 1024 * 1024)) { + if (!wsap_vtcore_hist_init(&h, 10000, 8 * 1024 * 1024)) { fprintf(stderr, "failed to initialize hist\n"); return EXIT_FAILURE; } @@ -63,31 +63,31 @@ int main(int argc, char **argv) const char *line = "abcdefghijklmnopqrstuvwxyz\n"; int len = (int)strlen(line); for (int i = 0; i < 10000; i++) - term_hist_push_ascii(&h, line, len, NULL, false); + wsap_vtcore_hist_push_ascii(&h, line, len, NULL, false); double t0 = now(); for (int i = 0; i < iterations; i++) - term_hist_push_ascii(&h, line, len, NULL, false); + wsap_vtcore_hist_push_ascii(&h, line, len, NULL, false); double elapsed = now() - t0; printf("%-12s %6.2f ns/line %.2f GiB/s (%d B/line)\n", "ascii", elapsed * 1e9 / iterations, (double)iterations * len / (1024.0 * 1024.0 * 1024.0) / elapsed, len); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); static const char *rows[] = { "ascii-row", "cjk-row", "colors-row", "fg-char-row" }; for (size_t k = 0; k < sizeof(rows) / sizeof(rows[0]); k++) { struct cell row[128]; int n = make_row(rows[k], row); int iters = iterations / 4; - if (!term_hist_init(&h, 4096, 0)) + if (!wsap_vtcore_hist_init(&h, 4096, 0)) return EXIT_FAILURE; for (int i = 0; i < 10000; i++) - term_hist_push_row(&h, row, n, false, NULL); + wsap_vtcore_hist_push_row(&h, row, n, false, NULL); t0 = now(); for (int i = 0; i < iters; i++) - term_hist_push_row(&h, row, n, false, NULL); + wsap_vtcore_hist_push_row(&h, row, n, false, NULL); elapsed = now() - t0; printf("%-12s %6.2f ns/row (%d cells)\n", rows[k], elapsed * 1e9 / iters, n); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } return EXIT_SUCCESS; } diff --git a/benchmarks/meson.build b/benchmarks/meson.build index ef78f28..bd508b6 100644 --- a/benchmarks/meson.build +++ b/benchmarks/meson.build @@ -6,7 +6,7 @@ foreach entry : [ benchmark(entry[0], executable(entry[0], entry[1], c_args: ['-D_POSIX_C_SOURCE=200809L'], - dependencies: term_internal_dep, + dependencies: wsap_vtcore_internal_dep, build_by_default: false), timeout: 600, ) diff --git a/benchmarks/term_resize_bench.c b/benchmarks/term_resize_bench.c index 08634d1..2899dae 100644 --- a/benchmarks/term_resize_bench.c +++ b/benchmarks/term_resize_bench.c @@ -1,4 +1,4 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -34,7 +34,7 @@ static int cmp_double(const void *a, const void *b) enum content { SHORT, WRAPPED, MIXED, PROMPT, WIDE, CONTENT_COUNT }; static const char *content_names[] = {"short", "wrapped", "mixed", "prompt", "wide"}; -static void emit_line(struct term *t, enum content kind, int n, int cols) +static void emit_line(struct wsap_vtcore *t, enum content kind, int n, int cols) { char line[4096]; int len = 0; @@ -74,12 +74,12 @@ static void emit_line(struct term *t, enum content kind, int n, int cols) break; } (void)cols; - term_feed(t, line, (size_t)len, 0); + wsap_vtcore_feed(t, line, (size_t)len, 0); } -static struct term *make_filled(enum content kind, int cols, int rows, int history) +static struct wsap_vtcore *make_filled(enum content kind, int cols, int rows, int history) { - struct term *t = term_new(&(struct term_options){ + struct wsap_vtcore *t = wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = cols, .y = rows }, .scrollback = history, }); @@ -89,10 +89,10 @@ static struct term *make_filled(enum content kind, int cols, int rows, int histo return t; } -static void resize(struct term *t, int cols, int rows) +static void resize(struct wsap_vtcore *t, int cols, int rows) { - if (!term_resize(t, (struct term_vector2i){ .x = cols, .y = rows })) { - fprintf(stderr, "term_resize failed: out of memory\n"); + if (!wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ .x = cols, .y = rows })) { + fprintf(stderr, "wsap_vtcore_resize failed: out of memory\n"); exit(EXIT_FAILURE); } } @@ -113,12 +113,12 @@ static double bench_pair(enum content kind, int from_cols, int to_cols, int rows { double worst = 0; for (int i = 0; i < samples; i++) { - struct term *t = make_filled(kind, from_cols, rows, history); + struct wsap_vtcore *t = make_filled(kind, from_cols, rows, history); if (!t) exit(EXIT_FAILURE); double start = now(); resize(t, to_cols, rows); double ms = (now() - start) * 1e3; - term_free(t); + wsap_vtcore_free(t); out[i] = ms; if (ms > worst) worst = ms; } @@ -132,14 +132,14 @@ static int bench_drag(enum content kind, int from_cols, int to_cols, int rows, int n = 0; int step = from_cols > to_cols ? -1 : 1; for (int p = 0; p < passes; p++) { - struct term *t = make_filled(kind, from_cols, rows, history); + struct wsap_vtcore *t = make_filled(kind, from_cols, rows, history); if (!t) exit(EXIT_FAILURE); for (int c = from_cols + step; c != to_cols + step; c += step) { double start = now(); resize(t, c, rows); out[n++] = (now() - start) * 1e3; } - term_free(t); + wsap_vtcore_free(t); } return n; } diff --git a/benchmarks/term_write_bench.c b/benchmarks/term_write_bench.c index 7649ed8..f393b4c 100644 --- a/benchmarks/term_write_bench.c +++ b/benchmarks/term_write_bench.c @@ -1,4 +1,4 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -20,13 +20,13 @@ static int cmp_double(const void *a, const void *b) /* Timed sample: iterations full-buffer writes split at raw byte offsets, so a * chunk smaller than len cuts UTF-8/CSI sequences mid-stream and exercises the * parser's save-and-resume path, like real PTY reads do. */ -static double run_sample(struct term *t, const char *buf, size_t len, +static double run_sample(struct wsap_vtcore *t, const char *buf, size_t len, size_t chunk, int iterations, unsigned flags) { double start = now(); for (int i = 0; i < iterations; i++) { for (size_t pos = 0; pos < len; pos += chunk) - term_feed(t, buf + pos, len - pos < chunk ? len - pos : chunk, flags); + wsap_vtcore_feed(t, buf + pos, len - pos < chunk ? len - pos : chunk, flags); } return now() - start; } @@ -146,25 +146,25 @@ int main(int argc, char **argv) } for (int k = 0; k < nchunks; k++) { size_t ck = chunks[k]; - const char *env_cols = getenv("TERM_COLS"); + const char *env_cols = getenv("WSAP_VTCORE_COLS"); int cols_val = env_cols ? atoi(env_cols) : 120; - struct term *t = term_new(&(struct term_options){ + struct wsap_vtcore *t = wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = cols_val, .y = 40 }, .scrollback = BENCH_SCROLLBACK, }); if (!t) { - fprintf(stderr, "term_new failed: TERM_COLS must be 0 to %d\n", TERM_MAX_COLS); + fprintf(stderr, "wsap_vtcore_new failed: WSAP_VTCORE_COLS must be 0 to %d\n", WSAP_VTCORE_MAX_COLS); return EXIT_FAILURE; } /* manyline has bare LFs: each one also returns the cursor to * column 0, as a tty with ONLCR does. */ - unsigned flags = !strcmp(cases[c].name, "manyline") ? TERM_FEED_ONLCR : 0; + unsigned flags = !strcmp(cases[c].name, "manyline") ? WSAP_VTCORE_FEED_ONLCR : 0; if (!strncmp(cases[c].name, "margin-", 7)) { const char setup[] = "\033[5;36r\033[36;1H"; - term_feed(t, setup, sizeof(setup) - 1, 0); + wsap_vtcore_feed(t, setup, sizeof(setup) - 1, 0); } else if (strstr(cases[c].name, "-burst")) { const char setup[] = "\033[40;1H"; - term_feed(t, setup, sizeof(setup) - 1, 0); + wsap_vtcore_feed(t, setup, sizeof(setup) - 1, 0); } /* Untimed warmup reaches steady-state scroll so rep 1 isn't a * cold outlier. */ @@ -179,7 +179,7 @@ int main(int argc, char **argv) printf("%-9s %6zu %10.2f %10.2f %10.2f %8.3f\n", cases[c].name, ck, med, min, max, samples[reps / 2] * 1e9 / bytes); - term_free(t); + wsap_vtcore_free(t); } } if (!matched) fprintf(stderr, "unknown benchmark case: %s\n", argv[1]); diff --git a/docs/correctness-audit.md b/docs/correctness-audit.md index dd854a1..0326d1b 100644 --- a/docs/correctness-audit.md +++ b/docs/correctness-audit.md @@ -16,7 +16,8 @@ meson setup build-audit --buildtype=debug -Db_lto=false \ -Db_sanitize=address,undefined -Dkitty=disabled meson compile -C build-audit -j 4 cc -std=c11 -g -UNDEBUG -fsanitize=address,undefined \ - -Iinclude/term -Isrc tests/correctness_probe.c build-audit/src/libterm.a \ + -Iinclude/wsap_vtcore -Isrc tests/correctness_probe.c \ + build-audit/src/libwsap_vtcore.a \ -Wl,--wrap=realloc -Wl,--wrap=calloc -lm -o build-audit/correctness-probe ASAN_OPTIONS=detect_leaks=0 build-audit/correctness-probe ``` @@ -69,7 +70,7 @@ threshold, independently of how many lines have scrolled past it. ### Failed height shrink changes terminal state -In `src/screen.c`, `term_resize_internal()` scrolls and adjusts the cursor +In `src/screen.c`, `wsap_vtcore_resize_internal()` scrolls and adjusts the cursor before allocating the replacement screen. If that allocation fails, it returns false after changing the terminal, violating the documented promise that a failed resize leaves it unchanged. diff --git a/include/term/term.h b/include/term/term.h deleted file mode 100644 index 8b98a25..0000000 --- a/include/term/term.h +++ /dev/null @@ -1,492 +0,0 @@ -#ifndef TERM_H -#define TERM_H - -/* - * Terminal emulator core. - * - * A struct term parses the bytes that a program writes and keeps the screen, - * the history, and the modes. The application feeds bytes with term_feed() - * and reads state with the getters below. A renderer never reads the - * terminal directly: it copies the viewport into a struct term_snapshot and - * paints from that copy. - * - * All functions take the terminal as the first argument. Functions that take - * a const struct term do not change what it shows. Selection, history, link, - * directory, and pointer-shape queries return owned strings; release them - * with term_text_free(). - * - * Threads. Any thread can call any function. Each call that reads or changes - * a terminal enters its writer section, so calls on one terminal run one at a - * time. A thread that waits for the section sleeps. On POSIX the section is a - * mutex with priority inheritance where the platform has it. A snapshot - * belongs to one thread at a time. term_free() is the last call on a terminal. - */ - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#include "term_input.h" -#include "term_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct term; -struct term_snapshot; - -/* A row holds at most this many cells. */ -#define TERM_MAX_COLS 65535 -/* The history limit when term_options.scrollback is 0. */ -#define TERM_SCROLLBACK_DEFAULT 10000 -/* The largest term_options.scrollback. */ -#define TERM_SCROLLBACK_MAX 1000000 - -/* - * The version of this header. A host compares TERM_VERSION_CODE with - * term_version() to check that the library matches the header. - */ -#define TERM_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch)) -#define TERM_VERSION_MAJOR 0 -#define TERM_VERSION_MINOR 1 -#define TERM_VERSION_PATCH 0 -#define TERM_VERSION_CODE TERM_VERSION(TERM_VERSION_MAJOR, TERM_VERSION_MINOR, TERM_VERSION_PATCH) - -/* - * Colors. A term_color is either a direct color (alpha 0xFF, then RGB) or a - * palette slot: an index 0-255, the default foreground, or the default - * background. A slot resolves when a snapshot is painted, so a theme change - * recolors text that is already on screen. - */ -typedef uint32_t term_color; - -#define TERM_COLOR_SLOT 0x01000000u -/* The palette index of a slot; see struct term_view.palette. */ -#define TERM_COLOR_SLOT_INDEX 0x1FFu -#define TERM_COLOR_FG (TERM_COLOR_SLOT | 0x100u) -#define TERM_COLOR_BG (TERM_COLOR_SLOT | 0x101u) - -static inline term_color term_color_index(int n) -{ - return TERM_COLOR_SLOT | ((uint32_t)n & 0xFFu); -} - -static inline term_color term_color_rgb(uint8_t r, uint8_t g, uint8_t b) -{ - return 0xFF000000u | (uint32_t)r << 16 | (uint32_t)g << 8 | b; -} - -static inline bool term_color_is_slot(term_color c) -{ - return (c >> 24) == (TERM_COLOR_SLOT >> 24); -} - -/* Parse an X11 or OSC color specification ("#rgb", "rgb:r/g/b", ...). */ -TERM_API bool term_color_parse(const char *spec, uint32_t *argb); - -/* The colors a terminal starts with. All values are ARGB. An all-zero theme - * selects the built-in theme. */ -struct term_theme { - uint32_t fg, bg, cursor; - uint32_t ansi[16]; -}; - -/* Fill theme with the built-in theme. */ -TERM_API void term_theme_default(struct term_theme *theme); -/* Fill theme with the high-contrast theme. */ -TERM_API void term_theme_high_contrast(struct term_theme *theme); -/* Sets one palette key: foreground, background, or color0 to color15. - * An empty value resets the key to the built-in theme. False, with no - * change, for an unknown key or a bad color. */ -TERM_API bool term_theme_set_key(struct term_theme *p, const char *key, const char *val); - -enum term_cursor_style { - TERM_CURSOR_BLOCK, - TERM_CURSOR_UNDERLINE, - TERM_CURSOR_BAR, -}; - -/* Mouse reporting modes and encodings. The values are the DEC mode numbers. */ -enum term_mouse { - TERM_MOUSE_OFF = 0, - TERM_MOUSE_X10 = 9, - TERM_MOUSE_NORMAL = 1000, - TERM_MOUSE_BUTTON = 1002, - TERM_MOUSE_ANY = 1003, -}; - -enum term_mouse_encoding { - TERM_MOUSE_ENC_X10 = 0, - TERM_MOUSE_ENC_UTF8 = 1005, - TERM_MOUSE_ENC_SGR = 1006, - TERM_MOUSE_ENC_URXVT = 1015, - TERM_MOUSE_ENC_SGR_PIXELS = 1016, -}; - -/* - * Callbacks. They run inside term_feed() and term_focus(), on the thread - * that calls those functions. A callback must not call back into the - * terminal. String arguments are valid only during the call. - */ -struct term_callbacks { - void *ud; - /* Bytes the terminal sends back to the program (replies to queries). */ - void (*reply)(void *ud, const char *bytes, size_t len); - void (*title)(void *ud, const char *title); - /* - * OSC 52 clipboard callback. - * selection names the target clipboard buffer(s), commonly: - * "c" - clipboard (system clipboard) - * "p" - primary selection (X11 primary) - * "q" - secondary selection - * "s" - select selection - * "0".."7" - cut buffers 0 to 7 - * A parameter may contain multiple targets (e.g. "cp"). - * data contains decoded bytes of length len. - */ - void (*clipboard)(void *ud, const char *selection, const char *data, size_t len); - void (*notify)(void *ud, const char *title, const char *body); - void (*bell)(void *ud); - /* Parser trace lines for debugging. NULL turns tracing off. The line has no newline. */ - void (*trace)(void *ud, const char *line); -}; - -/* - * Options for term_new(). An all-zero value is valid. A size component of 0 - * selects 80 columns or 24 rows. A negative component, or columns above - * TERM_MAX_COLS, makes term_new() fail. A scrollback below 0 or above - * TERM_SCROLLBACK_MAX fails too. - * cursor_style must be a value of enum term_cursor_style. - */ -struct term_options { - struct term_vector2i size; /* columns and rows */ - int scrollback; /* history lines; 0 selects TERM_SCROLLBACK_DEFAULT */ - struct term_theme theme; - enum term_cursor_style cursor_style; - bool cursor_steady; /* false: the cursor blinks */ - /* - * The terminal's name. Programs read it with XTVERSION and XTGETTCAP. - * It is also the title of a notification that has none. NULL or "" - * selects "term". Otherwise 1 to 63 printable ASCII bytes, or term_new() - * returns NULL. term_new() copies the name. - */ - const char *name; - struct term_callbacks callbacks; - /* Must be zero. term_new() returns NULL if any word is nonzero, so a - * later version can give a word a meaning. */ - uint32_t reserved[8]; -}; - -/* The Unicode version of the width tables, such as "18.0.0". A host can - * pass it to programs as UNICODE_VERSION. */ -TERM_API const char *term_unicode_version(void); -/* The TERM_VERSION_CODE the library was built with. */ -TERM_API unsigned term_version(void); - -/* The length of the prefix of buf made of bytes in [0x20, hi). With hi - * 0x7f, it finds a run of printable ASCII in UTF-8 text, so a host can - * skip shaping for it. Any thread can call it. */ -TERM_API size_t term_scan_printable_span(const char *buf, size_t len, unsigned char hi); - -/* The instruction set level of the running code: "base", "avx2", "avx512", - * or "neon". On x86-64, the first term_new() picks the highest level the CPU - * supports. Set TERM_HEADLESS_ISA to a lower level to force it, for tests - * and comparisons. */ -TERM_API const char *term_isa(void); - -/* NULL when memory runs out or an option is invalid. */ -TERM_API struct term *term_new(const struct term_options *opt); -TERM_API void term_free(struct term *t); - -/* Hold the writer section across several calls, so that no other thread - * changes the terminal between them. The section is a mutex, and a waiting - * thread sleeps. Keep it short. The thread that holds it can call every - * function, and it can enter the section again. Each term_lock() needs one - * term_unlock(). */ -TERM_API void term_lock(struct term *t); -TERM_API void term_unlock(struct term *t); - -/* Change the size in cells. Returns false, and the terminal is unchanged, - * when a component is below 1, when cols is above TERM_MAX_COLS, or when - * memory runs out. The screen reflows to the new width. */ -TERM_API bool term_resize(struct term *t, struct term_vector2i size); - -/* Replace the theme. A different theme also drops the colors that the - * program set with OSC; the same theme changes nothing. */ -TERM_API void term_set_theme(struct term *t, const struct term_theme *theme); - -/* The cursor style that DECSCUSR 0 and a reset restore. */ -TERM_API void term_set_cursor_default(struct term *t, enum term_cursor_style style, bool steady); - -/* - * Bytes from the program. - * - * TERM_FEED_ONLCR: a line feed also returns the cursor to column 0, as a tty - * with OPOST and ONLCR does. Set it when the bytes did not pass through the - * tty output processing (for example the fast pipe). - */ -enum term_feed_flags { - TERM_FEED_ONLCR = 1u << 0, -}; - -/* - * Feed bytes from the program. Returns false, and changes nothing, when t is - * NULL, when bytes is NULL and len is not 0, or when flags has a bit that is - * not in enum term_feed_flags. A len of 0 is a no-op that returns true. - */ -TERM_API bool term_feed(struct term *t, const char *bytes, size_t len, unsigned flags); - -/* Report a focus change. The terminal replies only in focus-event mode. */ -TERM_API void term_focus(struct term *t, bool focused); - -/* Modes that affect how the application encodes input. */ -struct term_modes { - unsigned keyboard; /* kitty keyboard protocol flags */ - enum term_mouse mouse; - enum term_mouse_encoding mouse_encoding; - struct term_vector2i grid; /* columns and rows */ - bool app_cursor; /* DECCKM */ - bool app_keypad; /* DECKPAM */ - bool backarrow_bs; /* DECBKM */ - bool bracketed_paste; - bool focus_events; - bool alternate; /* the alternate screen is active */ - bool reverse_video; /* DECSCNM */ - bool synchronized; /* mode 2026 */ -}; - -struct term_cursor { - struct term_vector2i pos; - enum term_cursor_style style; - bool visible; - bool blink; -}; - -TERM_API struct term_vector2i term_size(const struct term *t); -TERM_API struct term_modes term_modes(const struct term *t); - -/* - * Encode an input event as the bytes the program expects. Get modes from - * term_modes(). Record ev in keyboard with term_keyboard_update() first. Send - * the bytes to the program yourself. - */ -TERM_API struct term_input_result term_input_encode_key( - const struct term_keyboard_state *keyboard, - const struct term_key_event *ev, - const struct term_modes *modes, - char *buf, size_t capacity -); - -TERM_API struct term_input_result term_input_encode_mouse( - const struct term_mouse_event *ev, - const struct term_modes *modes, - char *buf, size_t capacity -); - -/* Bytes term_input_encode_paste() adds to the text at most. */ -#define TERM_PASTE_EXTRA 12 - -/* - * Encode pasted text. Drop control characters and bidi controls, so the - * program sees only what the user saw. Send a line break as CR. Add the - * bracketed-paste markers when the program asked for them. A buffer of - * len + TERM_PASTE_EXTRA bytes is always large enough. Text that is empty - * after the filter gives TERM_INPUT_CONSUMED. - */ -TERM_API struct term_input_result term_input_encode_paste( - const struct term_modes *modes, - const char *text, size_t len, - char *buf, size_t capacity -); -/* The cursor in screen coordinates (not the viewport). */ -TERM_API struct term_cursor term_cursor(const struct term *t); -/* Owned, NUL-terminated text from OSC 7 and OSC 22. NULL when unavailable - * or allocation fails. The strings stay valid after the terminal changes - * or is freed. Release them with term_text_free(). */ -TERM_API char *term_cwd(const struct term *t); -TERM_API char *term_pointer_shape(const struct term *t); -/* Release any owned text returned by the library. NULL is safe. */ -TERM_API void term_text_free(char *text); - -/* - * Viewport. The viewport shows as many rows as the screen. Offset 0 shows - * the live screen; a larger offset shows that many rows of history above it. - * The alternate screen has no history, so its offset is always 0. - */ -struct term_scrollback { - int offset; /* rows between the viewport and the live screen */ - int total; /* history rows at the current width */ -}; - -TERM_API struct term_scrollback term_scrollback(const struct term *t); -/* Scroll the viewport. A positive count moves back into history. */ -TERM_API void term_scroll(struct term *t, int lines); -TERM_API void term_scroll_to(struct term *t, int offset); - -/* - * Selection, in viewport coordinates. A selection starts at one cell and - * extends to another; the unit widens both ends to words or whole lines. - * The terminal clears the selection when the text under it changes. - */ -enum term_select_unit { - TERM_SELECT_CELL, - TERM_SELECT_WORD, - TERM_SELECT_LINE, -}; - -/* Start a selection at cell. For TERM_SELECT_CELL, right_half means the - * pointer is on the right half of the cell, so the selection starts after it. - * Returns false when memory runs out; the selection is then unchanged. */ -TERM_API bool term_select_start(struct term *t, struct term_vector2i cell, bool right_half, - enum term_select_unit unit); -/* Extend the selection from its start to cell. Returns false when memory runs - * out; the selection is then unchanged. */ -TERM_API bool term_select_extend(struct term *t, struct term_vector2i cell, bool right_half); -TERM_API void term_select_clear(struct term *t); -TERM_API bool term_has_selection(const struct term *t); -/* Owned, NUL-terminated UTF-8 of the selection. NULL when nothing is - * selected or allocation fails; a selection of blanks may produce an empty - * string. Capture is atomic with respect to other calls on t. Release the - * result with term_text_free(). */ -TERM_API char *term_selection_text(const struct term *t); -/* Owned OSC 8 link or detected URL at a viewport cell. NULL when there is - * no link or allocation fails. Release the result with term_text_free(). */ -TERM_API char *term_link_at(const struct term *t, struct term_vector2i cell); - -/* Cell attributes share the write core's bit layout. Underline styles are - * mutually exclusive flags, not a shifted enum; use term_attr_underline(). */ -enum term_attr { - TERM_ATTR_BOLD = 1u << 0, - TERM_ATTR_ITALIC = 1u << 1, - TERM_ATTR_UNDERLINE = 1u << 2, - TERM_ATTR_STRIKE = 1u << 3, - TERM_ATTR_OVERLINE = 1u << 4, - TERM_ATTR_EMOJI = 1u << 5, /* the text requested emoji presentation */ - TERM_ATTR_TEXT = 1u << 6, /* the text requested text presentation */ - TERM_ATTR_FAINT = 1u << 10, - TERM_ATTR_DOUBLE_UNDERLINE = 1u << 11, - TERM_ATTR_CURLY_UNDERLINE = 1u << 12, - TERM_ATTR_DOTTED_UNDERLINE = 1u << 13, - TERM_ATTR_DASHED_UNDERLINE = 1u << 14, - TERM_ATTR_LINK = 1u << 15, -}; - -#define TERM_ATTR_UNDERLINE_MASK \ - (TERM_ATTR_UNDERLINE | TERM_ATTR_DOUBLE_UNDERLINE | TERM_ATTR_CURLY_UNDERLINE | \ - TERM_ATTR_DOTTED_UNDERLINE | TERM_ATTR_DASHED_UNDERLINE) - -enum term_underline { - TERM_UNDERLINE_NONE, - TERM_UNDERLINE_SINGLE, - TERM_UNDERLINE_DOUBLE, - TERM_UNDERLINE_CURLY, - TERM_UNDERLINE_DOTTED, - TERM_UNDERLINE_DASHED, -}; - -static inline enum term_underline term_attr_underline(uint16_t attrs) -{ - if (attrs & TERM_ATTR_DOUBLE_UNDERLINE) return TERM_UNDERLINE_DOUBLE; - if (attrs & TERM_ATTR_CURLY_UNDERLINE) return TERM_UNDERLINE_CURLY; - if (attrs & TERM_ATTR_DOTTED_UNDERLINE) return TERM_UNDERLINE_DOTTED; - if (attrs & TERM_ATTR_DASHED_UNDERLINE) return TERM_UNDERLINE_DASHED; - return attrs & TERM_ATTR_UNDERLINE ? TERM_UNDERLINE_SINGLE : TERM_UNDERLINE_NONE; -} - -/* text refers to a grapheme cluster in the snapshot; see term_snapshot_cluster(). */ -#define TERM_TEXT_CLUSTER 0x80000000u - -/* One cell as a snapshot shows it. */ -struct term_cell { - uint32_t text; /* a code point, TERM_TEXT_CLUSTER | n, or 0 for an empty cell */ - term_color fg, bg; - uint16_t attrs; /* enum term_attr flags; at most one underline flag */ - uint8_t width; /* 1; 2 for a wide glyph; 0 for the right half of a wide glyph */ - uint8_t reserved; -}; - -#ifdef __cplusplus -static_assert(sizeof(struct term_cell) == 16, "four cells fill one 64-byte line"); -#else -_Static_assert(sizeof(struct term_cell) == 16, "four cells fill one 64-byte line"); -#endif - -/* - * Snapshot: a copy of the viewport for a renderer. It holds no pointer into - * the terminal, so it stays valid while the terminal changes. One terminal - * may have several snapshots, for example a window and a tab preview. - */ -TERM_API struct term_snapshot *term_snapshot_new(void); -TERM_API void term_snapshot_free(struct term_snapshot *s); - -/* Copy the viewport of t into s. Keep rows with unchanged content keys. - * Update the history view index and refine counts for visible wide lines. - * Return false when memory runs out. The snapshot then keeps its previous content. */ -TERM_API bool term_snapshot_update(struct term_snapshot *s, struct term *t); - -/* Palette entries of struct term_view.palette after the 256 indexed colors. */ -enum { - TERM_PALETTE_FG = 256, - TERM_PALETTE_BG = 257, - TERM_PALETTE_CURSOR = 258, - TERM_PALETTE_SIZE = 259, -}; - -struct term_view { - struct term_vector2i size; - struct term_cursor cursor; /* viewport coordinates; not visible when scrolled away */ - int scroll_offset; - /* Rows the content moved up since the previous update, when that movement - * explains the change; otherwise 0. */ - int scrolled; - bool reverse_video; - /* Changes when any part of the view changes. */ - uint64_t version; - /* Changes when a palette entry changes. */ - uint64_t palette_version; - const uint32_t *palette; /* TERM_PALETTE_SIZE ARGB entries */ -}; - -/* The view of s, NULL for a NULL s. The view and view->palette keep their - * address until term_snapshot_free(); their contents change on each update. */ -TERM_API const struct term_view *term_snapshot_view(const struct term_snapshot *s); -/* The cells of viewport row y: view->size.x entries. NULL when y is outside - * the viewport or s is NULL. An update can move the cells, so the pointer is - * valid only until the next term_snapshot_update() or term_snapshot_free() of s. */ -TERM_API const struct term_cell *term_snapshot_row(const struct term_snapshot *s, int y); -/* An identity for the content of row y. Two rows with the same key hold the - * same cells, also when the content moved to another row. 0 when y is outside - * the viewport or s is NULL. */ -TERM_API uint64_t term_snapshot_row_key(const struct term_snapshot *s, int y); - -/* Number of rows in history above the screen. 0 if alternate screen or no history. */ -TERM_API int term_history_rows(const struct term *t); -/* Owned, NUL-terminated UTF-8 of up to max_rows history rows before the - * current viewport. Join soft-wrapped rows and end closed lines with a - * newline. Does not change the selection. No history or max_rows <= 0 gives - * an empty string; NULL means allocation failed or t is NULL. Release the - * result with term_text_free(). */ -TERM_API char *term_history_text(struct term *t, int max_rows); -/* The selected columns of viewport row y, end exclusive. An empty span when y - * is outside the viewport or s is NULL. */ -TERM_API struct term_span term_snapshot_row_selection(const struct term_snapshot *s, int y); - -/* The code points of a cluster cell. Returns the number of code points and - * writes at most cap of them. Writes nothing when cps is NULL or cap is 0. - * Returns 0 when s is NULL. */ -TERM_API int term_snapshot_cluster(const struct term_snapshot *s, uint32_t text, uint32_t *cps, int cap); - -/* The ARGB value of a color in a view. */ -static inline uint32_t term_view_color(const struct term_view *v, term_color c) -{ - if (!term_color_is_slot(c)) - return c; - return v->palette[c & TERM_COLOR_SLOT_INDEX]; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/term/term_input.h b/include/term/term_input.h deleted file mode 100644 index 19d9355..0000000 --- a/include/term/term_input.h +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef TERM_INPUT_H -#define TERM_INPUT_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> -#include "term_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum term_key { - TERM_KEY_NONE = 0, - - TERM_KEY_RETURN, - TERM_KEY_BACKSPACE, - TERM_KEY_TAB, - TERM_KEY_ESCAPE, - - TERM_KEY_UP, - TERM_KEY_DOWN, - TERM_KEY_RIGHT, - TERM_KEY_LEFT, - TERM_KEY_HOME, - TERM_KEY_END, - TERM_KEY_PAGE_UP, - TERM_KEY_PAGE_DOWN, - TERM_KEY_INSERT, - TERM_KEY_DELETE, - - TERM_KEY_F1, TERM_KEY_F2, TERM_KEY_F3, TERM_KEY_F4, TERM_KEY_F5, - TERM_KEY_F6, TERM_KEY_F7, TERM_KEY_F8, TERM_KEY_F9, TERM_KEY_F10, - TERM_KEY_F11, TERM_KEY_F12, TERM_KEY_F13, TERM_KEY_F14, TERM_KEY_F15, - TERM_KEY_F16, TERM_KEY_F17, TERM_KEY_F18, TERM_KEY_F19, TERM_KEY_F20, - TERM_KEY_F21, TERM_KEY_F22, TERM_KEY_F23, TERM_KEY_F24, TERM_KEY_F25, - TERM_KEY_F26, TERM_KEY_F27, TERM_KEY_F28, TERM_KEY_F29, TERM_KEY_F30, - TERM_KEY_F31, TERM_KEY_F32, TERM_KEY_F33, TERM_KEY_F34, TERM_KEY_F35, - - TERM_KEY_KP_0, TERM_KEY_KP_1, TERM_KEY_KP_2, TERM_KEY_KP_3, TERM_KEY_KP_4, - TERM_KEY_KP_5, TERM_KEY_KP_6, TERM_KEY_KP_7, TERM_KEY_KP_8, TERM_KEY_KP_9, - TERM_KEY_KP_DECIMAL, - TERM_KEY_KP_ENTER, - TERM_KEY_KP_ADD, - TERM_KEY_KP_SUBTRACT, - TERM_KEY_KP_MULTIPLY, - TERM_KEY_KP_DIVIDE, - TERM_KEY_KP_EQUAL, - TERM_KEY_KP_SEPARATOR, - TERM_KEY_KP_LEFT, - TERM_KEY_KP_RIGHT, - TERM_KEY_KP_UP, - TERM_KEY_KP_DOWN, - TERM_KEY_KP_PAGE_UP, - TERM_KEY_KP_PAGE_DOWN, - TERM_KEY_KP_HOME, - TERM_KEY_KP_END, - TERM_KEY_KP_INSERT, - TERM_KEY_KP_DELETE, - TERM_KEY_KP_BEGIN, - - TERM_KEY_CAPS_LOCK, - TERM_KEY_SCROLL_LOCK, - TERM_KEY_NUM_LOCK, - TERM_KEY_PRINT_SCREEN, - TERM_KEY_PAUSE, - TERM_KEY_MENU, - - TERM_KEY_MEDIA_PLAY, - TERM_KEY_MEDIA_PAUSE, - TERM_KEY_MEDIA_STOP, - TERM_KEY_MEDIA_FORWARD, - TERM_KEY_MEDIA_REWIND, - TERM_KEY_MEDIA_NEXT, - TERM_KEY_MEDIA_PREV, - TERM_KEY_MEDIA_RECORD, - TERM_KEY_VOLUME_DOWN, - TERM_KEY_VOLUME_UP, - TERM_KEY_MUTE, - - TERM_KEY_LSHIFT, - TERM_KEY_LCTRL, - TERM_KEY_LALT, - TERM_KEY_LSUPER, - TERM_KEY_LHYPER, - TERM_KEY_LMETA, - TERM_KEY_RSHIFT, - TERM_KEY_RCTRL, - TERM_KEY_RALT, - TERM_KEY_RSUPER, - TERM_KEY_RHYPER, - TERM_KEY_RMETA, - TERM_KEY_ISO_LEVEL3_SHIFT, - TERM_KEY_ISO_LEVEL5_SHIFT, - - TERM_KEY_COUNT -}; - -enum term_mod { - TERM_MOD_SHIFT = 1, - TERM_MOD_ALT = 2, - TERM_MOD_CTRL = 4, - TERM_MOD_SUPER = 8, - TERM_MOD_HYPER = 16, - TERM_MOD_META = 32, - TERM_MOD_CAPS = 64, - TERM_MOD_NUM = 128, -}; - -enum term_key_action { - TERM_KEY_PRESS = 1, - TERM_KEY_REPEAT = 2, - TERM_KEY_RELEASE = 3, -}; - -enum term_mouse_button { - TERM_MOUSE_BUTTON_PRIMARY = 0, - TERM_MOUSE_BUTTON_MIDDLE, - TERM_MOUSE_BUTTON_SECONDARY, - TERM_MOUSE_BUTTON_NONE, - /* Extra buttons 8 through 11 in xterm mouse reporting (encoded as 128..131). */ - TERM_MOUSE_BUTTON_EXTRA_1, - TERM_MOUSE_BUTTON_EXTRA_2, - TERM_MOUSE_BUTTON_EXTRA_3, - TERM_MOUSE_BUTTON_EXTRA_4, - TERM_MOUSE_WHEEL_UP = 16, - TERM_MOUSE_WHEEL_DOWN, - TERM_MOUSE_WHEEL_LEFT, - TERM_MOUSE_WHEEL_RIGHT, -}; - -enum term_mouse_event_kind { - TERM_MOUSE_PRESS = 0, - TERM_MOUSE_RELEASE, - TERM_MOUSE_MOTION, - TERM_MOUSE_SCROLL, - TERM_MOUSE_LEAVE, -}; - -struct term_key_event { - enum term_key_action action; - uint16_t key; /* enum term_key; TERM_KEY_NONE for a text key */ - uint16_t keypad; /* the TERM_KEY_KP_* key when the key is on the keypad */ - unsigned mods; /* enum term_mod */ - uint32_t codepoint; /* the code point of the key without modifiers */ - uint32_t shifted; /* the code point of the key with Shift */ - uint32_t base; /* the code point of the key in the US layout */ - uint32_t text; /* the code point the key types, or 0 */ - bool text_deferred; /* an input method sends the text later */ -}; - -struct term_mouse_event { - struct term_vector2i pos; /* Grid cell coordinates (col, row) */ - struct term_vector2i pixel; /* Absolute pixel position in terminal grid */ - /* - * Button identifier: - * - Press and release: the button that changed state (TERM_MOUSE_BUTTON_*). - * - Motion: the held button for drag events, or TERM_MOUSE_BUTTON_NONE for hover. - * - Scroll: the wheel direction (TERM_MOUSE_WHEEL_*). - */ - int button; - unsigned mods; - int scroll_lines; - float scroll_delta; - enum term_mouse_event_kind kind; -}; - -/* The keys that are down. An all-zero value has no keys down. */ -struct term_keyboard_state { - uint64_t down[(TERM_KEY_COUNT + 63) / 64]; -}; - -/* Record a press, repeat, or release in s. */ -TERM_API void term_keyboard_update(struct term_keyboard_state *s, const struct term_key_event *ev); -TERM_API bool term_keyboard_key_down(const struct term_keyboard_state *s, enum term_key key); - -/* Kitty keyboard protocol flags, as in term_modes.keyboard. */ -enum term_keyboard_flag { - TERM_KEYBOARD_DISAMBIGUATE = 1, - TERM_KEYBOARD_EVENT_TYPES = 2, - TERM_KEYBOARD_ALTERNATE_KEYS = 4, - TERM_KEYBOARD_ALL_KEYS = 8, - TERM_KEYBOARD_ASSOCIATED_TEXT = 16, -}; - -enum term_input_status { - TERM_INPUT_UNHANDLED = 0, /* the terminal does not use the event */ - TERM_INPUT_CONSUMED, /* the terminal uses the event but sends nothing */ - TERM_INPUT_BYTES, /* send the len bytes in buf to the program */ - TERM_INPUT_BUFFER_FULL, /* buf is too small; len is 0 */ -}; - -struct term_input_result { - size_t len; - enum term_input_status status; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* TERM_INPUT_H */ diff --git a/include/term/unicode/grapheme.h b/include/term/unicode/grapheme.h deleted file mode 100644 index 0946bb6..0000000 --- a/include/term/unicode/grapheme.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TERM_UNICODE_GRAPHEME_H -#define TERM_UNICODE_GRAPHEME_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -#define TERM_GRAPHEME_MAX_LEN 20 -#define TERM_GRAPHEME_HANDLE_BASE 0x7F000000u - -static inline bool term_grapheme_is_handle(uint32_t c) -{ - return c >= TERM_GRAPHEME_HANDLE_BASE; -} - -static inline bool term_grapheme_regional_indicator(uint32_t cp) -{ - return cp >= 0x1F1E6 && cp <= 0x1F1FF; -} - -static inline bool term_grapheme_emoji_modifier(uint32_t cp) -{ - return cp >= 0x1F3FB && cp <= 0x1F3FF; -} - -#endif diff --git a/include/term/unicode/unicode.h b/include/term/unicode/unicode.h deleted file mode 100644 index 932cbf6..0000000 --- a/include/term/unicode/unicode.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef TERM_UNICODE_UNICODE_H -#define TERM_UNICODE_UNICODE_H - -#include "width.h" - -#endif diff --git a/include/term/unicode/width.h b/include/term/unicode/width.h deleted file mode 100644 index a85ec77..0000000 --- a/include/term/unicode/width.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef TERM_UNICODE_WIDTH_H -#define TERM_UNICODE_WIDTH_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -struct term_unicode_range { uint32_t lo, hi; }; - -#include "unicode_data.inc" - -static inline bool term_in_ranges(const struct term_unicode_range *ranges, size_t count, uint32_t cp) -{ - if (count == 0 || cp < ranges[0].lo || cp > ranges[count - 1].hi) - return false; - const struct term_unicode_range *base = ranges; - size_t n = count; - while (n > 1) { - size_t half = n / 2; - base = (base[half].lo <= cp) ? base + half : base; - n -= half; - } - return cp <= base->hi; -} - -#define TERM_IN_TABLE(table, cp) term_in_ranges(table, sizeof(table) / sizeof(table[0]), cp) - -static inline int term_unicode_width(uint32_t cp) -{ - if (cp > 0x10FFFF || TERM_IN_TABLE(term_nonprintable, cp)) - return -1; - if (TERM_IN_TABLE(term_zero_width, cp)) - return 0; - return TERM_IN_TABLE(term_unicode_wide, cp) ? 2 : 1; -} - -static inline bool term_unicode_extended_pictographic(uint32_t cp) -{ - return TERM_IN_TABLE(term_extended_pictographic, cp); -} - -static inline bool term_unicode_emoji_presentation(uint32_t cp) -{ - return TERM_IN_TABLE(term_emoji_presentation, cp); -} - -static inline bool term_unicode_spacing_mark(uint32_t cp) -{ - if (cp < 0x903 || ((cp - 0xABEDu) < (0x11000u - 0xABEDu)) || cp > 0x1D281) - return false; - return TERM_IN_TABLE(term_spacing_mark, cp); -} - -#undef TERM_IN_TABLE - -#endif diff --git a/include/wsap_vtcore/unicode/grapheme.h b/include/wsap_vtcore/unicode/grapheme.h new file mode 100644 index 0000000..6146239 --- /dev/null +++ b/include/wsap_vtcore/unicode/grapheme.h @@ -0,0 +1,26 @@ +#ifndef WSAP_VTCORE_UNICODE_GRAPHEME_H +#define WSAP_VTCORE_UNICODE_GRAPHEME_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#define WSAP_VTCORE_GRAPHEME_MAX_LEN 20 +#define WSAP_VTCORE_GRAPHEME_HANDLE_BASE 0x7F000000u + +static inline bool wsap_vtcore_grapheme_is_handle(uint32_t c) +{ + return c >= WSAP_VTCORE_GRAPHEME_HANDLE_BASE; +} + +static inline bool wsap_vtcore_grapheme_regional_indicator(uint32_t cp) +{ + return cp >= 0x1F1E6 && cp <= 0x1F1FF; +} + +static inline bool wsap_vtcore_grapheme_emoji_modifier(uint32_t cp) +{ + return cp >= 0x1F3FB && cp <= 0x1F3FF; +} + +#endif diff --git a/include/wsap_vtcore/unicode/unicode.h b/include/wsap_vtcore/unicode/unicode.h new file mode 100644 index 0000000..02181b4 --- /dev/null +++ b/include/wsap_vtcore/unicode/unicode.h @@ -0,0 +1,6 @@ +#ifndef WSAP_VTCORE_UNICODE_UNICODE_H +#define WSAP_VTCORE_UNICODE_UNICODE_H + +#include "width.h" + +#endif diff --git a/include/term/unicode/unicode_data.inc b/include/wsap_vtcore/unicode/unicode_data.inc index 4ab1461..35831e5 100644 --- a/include/term/unicode/unicode_data.inc +++ b/include/wsap_vtcore/unicode/unicode_data.inc @@ -1,8 +1,8 @@ /* Generated from Unicode 18.0.0 data by tools/generate_unicode.py. */ -#define TERM_UNICODE_DATA_VERSION "18.0.0" +#define WSAP_VTCORE_UNICODE_DATA_VERSION "18.0.0" -static const struct term_unicode_range term_zero_width[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_zero_width[] = { {0xAD,0xAD},{0x300,0x36F},{0x483,0x489},{0x591,0x5BD}, {0x5BF,0x5BF},{0x5C1,0x5C2},{0x5C4,0x5C5},{0x5C7,0x5C9}, {0x600,0x605},{0x610,0x61A},{0x61C,0x61C},{0x64B,0x65F}, @@ -101,11 +101,11 @@ static const struct term_unicode_range term_zero_width[] = { {0xE0020,0xE007F},{0xE0100,0xE01EF}, }; -static const struct term_unicode_range term_nonprintable[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_nonprintable[] = { {0x0,0x1F},{0x7F,0x9F},{0xD800,0xDFFF}, }; -static const struct term_unicode_range term_unicode_wide[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_unicode_wide[] = { {0x1100,0x115F},{0x231A,0x231B},{0x2329,0x232A},{0x23E9,0x23EC}, {0x23F0,0x23F0},{0x23F3,0x23F3},{0x25FD,0x25FE},{0x2614,0x2615}, {0x2630,0x2637},{0x2648,0x2653},{0x267F,0x267F},{0x268A,0x268F}, @@ -140,7 +140,7 @@ static const struct term_unicode_range term_unicode_wide[] = { {0x20000,0x2FFFD},{0x30000,0x3FFFD}, }; -static const struct term_unicode_range term_spacing_mark[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_spacing_mark[] = { {0x903,0x903},{0x93B,0x93B},{0x93E,0x940},{0x949,0x94C}, {0x94E,0x94F},{0x982,0x983},{0x9BE,0x9C0},{0x9C7,0x9C8}, {0x9CB,0x9CC},{0x9D7,0x9D7},{0xA03,0xA03},{0xA3E,0xA40}, @@ -192,7 +192,7 @@ static const struct term_unicode_range term_spacing_mark[] = { {0x1D16D,0x1D172},{0x1D250,0x1D252},{0x1D25F,0x1D25F},{0x1D280,0x1D281}, }; -static const struct term_unicode_range term_extended_pictographic[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_extended_pictographic[] = { {0xA9,0xA9},{0xAE,0xAE},{0x203C,0x203C},{0x2049,0x2049}, {0x2122,0x2122},{0x2139,0x2139},{0x2194,0x2199},{0x21A9,0x21AA}, {0x231A,0x231B},{0x2328,0x2328},{0x23CF,0x23CF},{0x23E9,0x23F3}, @@ -234,7 +234,7 @@ static const struct term_unicode_range term_extended_pictographic[] = { {0x1F947,0x1F9FF},{0x1FA58,0x1FA5F},{0x1FA6E,0x1FAFF},{0x1FC00,0x1FFFD}, }; -static const struct term_unicode_range term_emoji_presentation[] = { +static const struct wsap_vtcore_unicode_range wsap_vtcore_emoji_presentation[] = { {0x231A,0x231B},{0x23E9,0x23EC},{0x23F0,0x23F0},{0x23F3,0x23F3}, {0x25FD,0x25FE},{0x2614,0x2615},{0x2648,0x2653},{0x267F,0x267F}, {0x2693,0x2693},{0x26A1,0x26A1},{0x26AA,0x26AB},{0x26BD,0x26BE}, diff --git a/include/term/unicode/utf8.h b/include/wsap_vtcore/unicode/utf8.h index ad44465..7660e41 100644 --- a/include/term/unicode/utf8.h +++ b/include/wsap_vtcore/unicode/utf8.h @@ -1,19 +1,19 @@ -#ifndef TERM_UNICODE_UTF8_H -#define TERM_UNICODE_UTF8_H +#ifndef WSAP_VTCORE_UNICODE_UTF8_H +#define WSAP_VTCORE_UNICODE_UTF8_H #include <stdint.h> #include <stddef.h> #include <stdlib.h> #include <string.h> -#define TERM_UTF8_ACCEPT 0 -#define TERM_UTF8_REJECT 1 +#define WSAP_VTCORE_UTF8_ACCEPT 0 +#define WSAP_VTCORE_UTF8_REJECT 1 -#define TERM_UTF8_3BYTE_MIN 0x800u -#define TERM_UTF8_SURROGATE_LO 0xd800u -#define TERM_UTF8_SURROGATE_HI 0xdfffu +#define WSAP_VTCORE_UTF8_3BYTE_MIN 0x800u +#define WSAP_VTCORE_UTF8_SURROGATE_LO 0xd800u +#define WSAP_VTCORE_UTF8_SURROGATE_HI 0xdfffu -static const uint8_t term_utf8d[] = { +static const uint8_t wsap_vtcore_utf8d[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -30,19 +30,19 @@ static const uint8_t term_utf8d[] = { 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, }; -static inline uint32_t term_utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) { +static inline uint32_t wsap_vtcore_utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) { byte &= 0xff; - uint32_t type = term_utf8d[byte]; + uint32_t type = wsap_vtcore_utf8d[byte]; - *codep = (*state != TERM_UTF8_ACCEPT) ? + *codep = (*state != WSAP_VTCORE_UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte); - *state = term_utf8d[256 + *state*16 + type]; + *state = wsap_vtcore_utf8d[256 + *state*16 + type]; return *state; } -static const uint8_t term_utf8_acc_state[256] = { +static const uint8_t wsap_vtcore_utf8_acc_state[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -60,7 +60,7 @@ static const uint8_t term_utf8_acc_state[256] = { 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 6, 7, 7, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; -static const uint8_t term_utf8_acc_codep[256] = { +static const uint8_t wsap_vtcore_utf8_acc_codep[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, @@ -86,7 +86,7 @@ static const uint8_t term_utf8_acc_codep[256] = { * ends an unfinished sequence the same way. An unfinished sequence at the * end of buf gives *cp = 0 and keeps the state. */ -static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep, +static inline int wsap_vtcore_utf8_decode_ground(uint32_t *state, uint32_t *codep, const char *buf, size_t len, uint32_t *cp) { uint32_t st = *state; uint32_t cpv = *codep; @@ -97,25 +97,25 @@ static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep, do { unsigned char c = (unsigned char)buf[n]; if (c < 0x20) { - if (st != TERM_UTF8_ACCEPT) *cp = 0xFFFD; - st = TERM_UTF8_ACCEPT; + if (st != WSAP_VTCORE_UTF8_ACCEPT) *cp = 0xFFFD; + st = WSAP_VTCORE_UTF8_ACCEPT; break; } uint32_t before = st; n++; - if (st == TERM_UTF8_ACCEPT) { - cpv = term_utf8_acc_codep[c]; - st = term_utf8_acc_state[c]; + if (st == WSAP_VTCORE_UTF8_ACCEPT) { + cpv = wsap_vtcore_utf8_acc_codep[c]; + st = wsap_vtcore_utf8_acc_state[c]; } else { - uint32_t type = term_utf8d[c]; + uint32_t type = wsap_vtcore_utf8d[c]; cpv = (c & 0x3fu) | (cpv << 6); - st = term_utf8d[256 + st*16 + type]; + st = wsap_vtcore_utf8d[256 + st*16 + type]; } - if (st == TERM_UTF8_ACCEPT) { *cp = cpv; break; } - if (st == TERM_UTF8_REJECT) { - st = TERM_UTF8_ACCEPT; + if (st == WSAP_VTCORE_UTF8_ACCEPT) { *cp = cpv; break; } + if (st == WSAP_VTCORE_UTF8_REJECT) { + st = WSAP_VTCORE_UTF8_ACCEPT; *cp = 0xFFFD; - if (before != TERM_UTF8_ACCEPT) n--; + if (before != WSAP_VTCORE_UTF8_ACCEPT) n--; break; } } while ((size_t)n < len); @@ -125,7 +125,7 @@ static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep, } static inline int -term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep) +wsap_vtcore_utf8_decode_one(const char *buf, size_t len, uint32_t *codep) { const unsigned char *s = (const unsigned char *)buf; unsigned c0, c1, c2, c3; @@ -159,8 +159,8 @@ term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep) if ((c1 & 0xc0) != 0x80 || (c2 & 0xc0) != 0x80) return 0; cp = ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f); - if (cp < TERM_UTF8_3BYTE_MIN || - (cp >= TERM_UTF8_SURROGATE_LO && cp <= TERM_UTF8_SURROGATE_HI)) + if (cp < WSAP_VTCORE_UTF8_3BYTE_MIN || + (cp >= WSAP_VTCORE_UTF8_SURROGATE_LO && cp <= WSAP_VTCORE_UTF8_SURROGATE_HI)) return 0; *codep = cp; return 3; @@ -183,14 +183,14 @@ term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep) } static inline void -term_utf8_sanitize(char *dst, size_t cap, const char *src) +wsap_vtcore_utf8_sanitize(char *dst, size_t cap, const char *src) { if (!cap) return; size_t i = 0, len = strlen(src), off = 0; while (off < len && i + 1 < cap) { uint32_t cp; - int n = term_utf8_decode_one(src + off, len - off, &cp); + int n = wsap_vtcore_utf8_decode_one(src + off, len - off, &cp); if (n <= 0 || i + (size_t)n >= cap) { off++; continue; @@ -204,17 +204,17 @@ term_utf8_sanitize(char *dst, size_t cap, const char *src) /* A sanitized copy of src. Sanitizing only drops bytes, so the copy is * never longer than src. */ -static inline char *term_utf8_sanitize_dup(const char *src) +static inline char *wsap_vtcore_utf8_sanitize_dup(const char *src) { size_t cap = strlen(src) + 1; char *dst = (char *)malloc(cap); if (dst) - term_utf8_sanitize(dst, cap, src); + wsap_vtcore_utf8_sanitize(dst, cap, src); return dst; } -#define TERM_UTF8_MAX_BYTES 4 -static inline int term_utf8_encode(uint32_t cp, char *out) +#define WSAP_VTCORE_UTF8_MAX_BYTES 4 +static inline int wsap_vtcore_utf8_encode(uint32_t cp, char *out) { if (cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) cp = 0xfffd; diff --git a/include/wsap_vtcore/unicode/width.h b/include/wsap_vtcore/unicode/width.h new file mode 100644 index 0000000..21d8252 --- /dev/null +++ b/include/wsap_vtcore/unicode/width.h @@ -0,0 +1,56 @@ +#ifndef WSAP_VTCORE_UNICODE_WIDTH_H +#define WSAP_VTCORE_UNICODE_WIDTH_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +struct wsap_vtcore_unicode_range { uint32_t lo, hi; }; + +#include "unicode_data.inc" + +static inline bool wsap_vtcore_in_ranges(const struct wsap_vtcore_unicode_range *ranges, size_t count, uint32_t cp) +{ + if (count == 0 || cp < ranges[0].lo || cp > ranges[count - 1].hi) + return false; + const struct wsap_vtcore_unicode_range *base = ranges; + size_t n = count; + while (n > 1) { + size_t half = n / 2; + base = (base[half].lo <= cp) ? base + half : base; + n -= half; + } + return cp <= base->hi; +} + +#define WSAP_VTCORE_IN_TABLE(table, cp) wsap_vtcore_in_ranges(table, sizeof(table) / sizeof(table[0]), cp) + +static inline int wsap_vtcore_unicode_width(uint32_t cp) +{ + if (cp > 0x10FFFF || WSAP_VTCORE_IN_TABLE(wsap_vtcore_nonprintable, cp)) + return -1; + if (WSAP_VTCORE_IN_TABLE(wsap_vtcore_zero_width, cp)) + return 0; + return WSAP_VTCORE_IN_TABLE(wsap_vtcore_unicode_wide, cp) ? 2 : 1; +} + +static inline bool wsap_vtcore_unicode_extended_pictographic(uint32_t cp) +{ + return WSAP_VTCORE_IN_TABLE(wsap_vtcore_extended_pictographic, cp); +} + +static inline bool wsap_vtcore_unicode_emoji_presentation(uint32_t cp) +{ + return WSAP_VTCORE_IN_TABLE(wsap_vtcore_emoji_presentation, cp); +} + +static inline bool wsap_vtcore_unicode_spacing_mark(uint32_t cp) +{ + if (cp < 0x903 || ((cp - 0xABEDu) < (0x11000u - 0xABEDu)) || cp > 0x1D281) + return false; + return WSAP_VTCORE_IN_TABLE(wsap_vtcore_spacing_mark, cp); +} + +#undef WSAP_VTCORE_IN_TABLE + +#endif diff --git a/include/wsap_vtcore/wsap_vtcore.h b/include/wsap_vtcore/wsap_vtcore.h new file mode 100644 index 0000000..d72a55b --- /dev/null +++ b/include/wsap_vtcore/wsap_vtcore.h @@ -0,0 +1,492 @@ +#ifndef WSAP_VTCORE_H +#define WSAP_VTCORE_H + +/* + * Terminal emulator core. + * + * A struct wsap_vtcore parses the bytes that a program writes and keeps + * the screen, the history, and the modes. The application feeds bytes with + * wsap_vtcore_feed() and reads state with the getters below. A renderer + * never reads the terminal directly: it copies the viewport into a + * struct wsap_vtcore_snapshot and paints from that copy. + * + * All functions take the terminal as the first argument. Functions that take + * a const struct wsap_vtcore do not change what it shows. Selection, history, link, + * directory, and pointer-shape queries return owned strings; release them + * with wsap_vtcore_text_free(). + * + * Threads. Any thread can call any function. Each call that reads or changes + * a terminal enters its writer section, so calls on one terminal run one at a + * time. A thread that waits for the section sleeps. On POSIX the section is a + * mutex with priority inheritance where the platform has it. A snapshot + * belongs to one thread at a time. wsap_vtcore_free() is the last call on a terminal. + */ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +#include "wsap_vtcore_input.h" +#include "wsap_vtcore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wsap_vtcore; +struct wsap_vtcore_snapshot; + +/* A row holds at most this many cells. */ +#define WSAP_VTCORE_MAX_COLS 65535 +/* The history limit when wsap_vtcore_options.scrollback is 0. */ +#define WSAP_VTCORE_SCROLLBACK_DEFAULT 10000 +/* The largest wsap_vtcore_options.scrollback. */ +#define WSAP_VTCORE_SCROLLBACK_MAX 1000000 + +/* + * The version of this header. A host compares WSAP_VTCORE_VERSION_CODE with + * wsap_vtcore_version() to check that the library matches the header. + */ +#define WSAP_VTCORE_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch)) +#define WSAP_VTCORE_VERSION_MAJOR 0 +#define WSAP_VTCORE_VERSION_MINOR 1 +#define WSAP_VTCORE_VERSION_PATCH 0 +#define WSAP_VTCORE_VERSION_CODE WSAP_VTCORE_VERSION(WSAP_VTCORE_VERSION_MAJOR, WSAP_VTCORE_VERSION_MINOR, WSAP_VTCORE_VERSION_PATCH) + +/* + * Colors. A wsap_vtcore_color is either a direct color (alpha 0xFF, then RGB) or a + * palette slot: an index 0-255, the default foreground, or the default + * background. A slot resolves when a snapshot is painted, so a theme change + * recolors text that is already on screen. + */ +typedef uint32_t wsap_vtcore_color; + +#define WSAP_VTCORE_COLOR_SLOT 0x01000000u +/* The palette index of a slot; see struct wsap_vtcore_view.palette. */ +#define WSAP_VTCORE_COLOR_SLOT_INDEX 0x1FFu +#define WSAP_VTCORE_COLOR_FG (WSAP_VTCORE_COLOR_SLOT | 0x100u) +#define WSAP_VTCORE_COLOR_BG (WSAP_VTCORE_COLOR_SLOT | 0x101u) + +static inline wsap_vtcore_color wsap_vtcore_color_index(int n) +{ + return WSAP_VTCORE_COLOR_SLOT | ((uint32_t)n & 0xFFu); +} + +static inline wsap_vtcore_color wsap_vtcore_color_rgb(uint8_t r, uint8_t g, uint8_t b) +{ + return 0xFF000000u | (uint32_t)r << 16 | (uint32_t)g << 8 | b; +} + +static inline bool wsap_vtcore_color_is_slot(wsap_vtcore_color c) +{ + return (c >> 24) == (WSAP_VTCORE_COLOR_SLOT >> 24); +} + +/* Parse an X11 or OSC color specification ("#rgb", "rgb:r/g/b", ...). */ +WSAP_VTCORE_API bool wsap_vtcore_color_parse(const char *spec, uint32_t *argb); + +/* The colors a terminal starts with. All values are ARGB. An all-zero theme + * selects the built-in theme. */ +struct wsap_vtcore_theme { + uint32_t fg, bg, cursor; + uint32_t ansi[16]; +}; + +/* Fill theme with the built-in theme. */ +WSAP_VTCORE_API void wsap_vtcore_theme_default(struct wsap_vtcore_theme *theme); +/* Fill theme with the high-contrast theme. */ +WSAP_VTCORE_API void wsap_vtcore_theme_high_contrast(struct wsap_vtcore_theme *theme); +/* Sets one palette key: foreground, background, or color0 to color15. + * An empty value resets the key to the built-in theme. False, with no + * change, for an unknown key or a bad color. */ +WSAP_VTCORE_API bool wsap_vtcore_theme_set_key(struct wsap_vtcore_theme *p, const char *key, const char *val); + +enum wsap_vtcore_cursor_style { + WSAP_VTCORE_CURSOR_BLOCK, + WSAP_VTCORE_CURSOR_UNDERLINE, + WSAP_VTCORE_CURSOR_BAR, +}; + +/* Mouse reporting modes and encodings. The values are the DEC mode numbers. */ +enum wsap_vtcore_mouse { + WSAP_VTCORE_MOUSE_OFF = 0, + WSAP_VTCORE_MOUSE_X10 = 9, + WSAP_VTCORE_MOUSE_NORMAL = 1000, + WSAP_VTCORE_MOUSE_BUTTON = 1002, + WSAP_VTCORE_MOUSE_ANY = 1003, +}; + +enum wsap_vtcore_mouse_encoding { + WSAP_VTCORE_MOUSE_ENC_X10 = 0, + WSAP_VTCORE_MOUSE_ENC_UTF8 = 1005, + WSAP_VTCORE_MOUSE_ENC_SGR = 1006, + WSAP_VTCORE_MOUSE_ENC_URXVT = 1015, + WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS = 1016, +}; + +/* + * Callbacks. They run inside wsap_vtcore_feed() and wsap_vtcore_focus(), on the thread + * that calls those functions. A callback must not call back into the + * terminal. String arguments are valid only during the call. + */ +struct wsap_vtcore_callbacks { + void *ud; + /* Bytes the terminal sends back to the program (replies to queries). */ + void (*reply)(void *ud, const char *bytes, size_t len); + void (*title)(void *ud, const char *title); + /* + * OSC 52 clipboard callback. + * selection names the target clipboard buffer(s), commonly: + * "c" - clipboard (system clipboard) + * "p" - primary selection (X11 primary) + * "q" - secondary selection + * "s" - select selection + * "0".."7" - cut buffers 0 to 7 + * A parameter may contain multiple targets (e.g. "cp"). + * data contains decoded bytes of length len. + */ + void (*clipboard)(void *ud, const char *selection, const char *data, size_t len); + void (*notify)(void *ud, const char *title, const char *body); + void (*bell)(void *ud); + /* Parser trace lines for debugging. NULL turns tracing off. The line has no newline. */ + void (*trace)(void *ud, const char *line); +}; + +/* + * Options for wsap_vtcore_new(). An all-zero value is valid. A size component of 0 + * selects 80 columns or 24 rows. A negative component, or columns above + * WSAP_VTCORE_MAX_COLS, makes wsap_vtcore_new() fail. A scrollback below 0 or above + * WSAP_VTCORE_SCROLLBACK_MAX fails too. + * cursor_style must be a value of enum wsap_vtcore_cursor_style. + */ +struct wsap_vtcore_options { + struct wsap_vtcore_vector2i size; /* columns and rows */ + int scrollback; /* history lines; 0 selects WSAP_VTCORE_SCROLLBACK_DEFAULT */ + struct wsap_vtcore_theme theme; + enum wsap_vtcore_cursor_style cursor_style; + bool cursor_steady; /* false: the cursor blinks */ + /* + * The terminal's name. Programs read it with XTVERSION and XTGETTCAP. + * It is also the title of a notification that has none. NULL or "" + * selects "wsap_vtcore". Otherwise 1 to 63 printable ASCII bytes, or + * wsap_vtcore_new() returns NULL. wsap_vtcore_new() copies the name. + */ + const char *name; + struct wsap_vtcore_callbacks callbacks; + /* Must be zero. wsap_vtcore_new() returns NULL if any word is nonzero, so a + * later version can give a word a meaning. */ + uint32_t reserved[8]; +}; + +/* The Unicode version of the width tables, such as "18.0.0". A host can + * pass it to programs as UNICODE_VERSION. */ +WSAP_VTCORE_API const char *wsap_vtcore_unicode_version(void); +/* The WSAP_VTCORE_VERSION_CODE the library was built with. */ +WSAP_VTCORE_API unsigned wsap_vtcore_version(void); + +/* The length of the prefix of buf made of bytes in [0x20, hi). With hi + * 0x7f, it finds a run of printable ASCII in UTF-8 text, so a host can + * skip shaping for it. Any thread can call it. */ +WSAP_VTCORE_API size_t wsap_vtcore_scan_printable_span(const char *buf, size_t len, unsigned char hi); + +/* The instruction set level of the running code: "base", "avx2", "avx512", + * or "neon". On x86-64, the first wsap_vtcore_new() picks the highest level the CPU + * supports. Set WSAP_VTCORE_ISA to a lower level to force it, for tests + * and comparisons. */ +WSAP_VTCORE_API const char *wsap_vtcore_isa(void); + +/* NULL when memory runs out or an option is invalid. */ +WSAP_VTCORE_API struct wsap_vtcore *wsap_vtcore_new(const struct wsap_vtcore_options *opt); +WSAP_VTCORE_API void wsap_vtcore_free(struct wsap_vtcore *t); + +/* Hold the writer section across several calls, so that no other thread + * changes the terminal between them. The section is a mutex, and a waiting + * thread sleeps. Keep it short. The thread that holds it can call every + * function, and it can enter the section again. Each wsap_vtcore_lock() needs one + * wsap_vtcore_unlock(). */ +WSAP_VTCORE_API void wsap_vtcore_lock(struct wsap_vtcore *t); +WSAP_VTCORE_API void wsap_vtcore_unlock(struct wsap_vtcore *t); + +/* Change the size in cells. Returns false, and the terminal is unchanged, + * when a component is below 1, when cols is above WSAP_VTCORE_MAX_COLS, or when + * memory runs out. The screen reflows to the new width. */ +WSAP_VTCORE_API bool wsap_vtcore_resize(struct wsap_vtcore *t, struct wsap_vtcore_vector2i size); + +/* Replace the theme. A different theme also drops the colors that the + * program set with OSC; the same theme changes nothing. */ +WSAP_VTCORE_API void wsap_vtcore_set_theme(struct wsap_vtcore *t, const struct wsap_vtcore_theme *theme); + +/* The cursor style that DECSCUSR 0 and a reset restore. */ +WSAP_VTCORE_API void wsap_vtcore_set_cursor_default(struct wsap_vtcore *t, enum wsap_vtcore_cursor_style style, bool steady); + +/* + * Bytes from the program. + * + * WSAP_VTCORE_FEED_ONLCR: a line feed also returns the cursor to column 0, as a tty + * with OPOST and ONLCR does. Set it when the bytes did not pass through the + * tty output processing (for example the fast pipe). + */ +enum wsap_vtcore_feed_flags { + WSAP_VTCORE_FEED_ONLCR = 1u << 0, +}; + +/* + * Feed bytes from the program. Returns false, and changes nothing, when t is + * NULL, when bytes is NULL and len is not 0, or when flags has a bit that is + * not in enum wsap_vtcore_feed_flags. A len of 0 is a no-op that returns true. + */ +WSAP_VTCORE_API bool wsap_vtcore_feed(struct wsap_vtcore *t, const char *bytes, size_t len, unsigned flags); + +/* Report a focus change. The terminal replies only in focus-event mode. */ +WSAP_VTCORE_API void wsap_vtcore_focus(struct wsap_vtcore *t, bool focused); + +/* Modes that affect how the application encodes input. */ +struct wsap_vtcore_modes { + unsigned keyboard; /* kitty keyboard protocol flags */ + enum wsap_vtcore_mouse mouse; + enum wsap_vtcore_mouse_encoding mouse_encoding; + struct wsap_vtcore_vector2i grid; /* columns and rows */ + bool app_cursor; /* DECCKM */ + bool app_keypad; /* DECKPAM */ + bool backarrow_bs; /* DECBKM */ + bool bracketed_paste; + bool focus_events; + bool alternate; /* the alternate screen is active */ + bool reverse_video; /* DECSCNM */ + bool synchronized; /* mode 2026 */ +}; + +struct wsap_vtcore_cursor { + struct wsap_vtcore_vector2i pos; + enum wsap_vtcore_cursor_style style; + bool visible; + bool blink; +}; + +WSAP_VTCORE_API struct wsap_vtcore_vector2i wsap_vtcore_size(const struct wsap_vtcore *t); +WSAP_VTCORE_API struct wsap_vtcore_modes wsap_vtcore_modes(const struct wsap_vtcore *t); + +/* + * Encode an input event as the bytes the program expects. Get modes from + * wsap_vtcore_modes(). Record ev in keyboard with wsap_vtcore_keyboard_update() first. Send + * the bytes to the program yourself. + */ +WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_key( + const struct wsap_vtcore_keyboard_state *keyboard, + const struct wsap_vtcore_key_event *ev, + const struct wsap_vtcore_modes *modes, + char *buf, size_t capacity +); + +WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_mouse( + const struct wsap_vtcore_mouse_event *ev, + const struct wsap_vtcore_modes *modes, + char *buf, size_t capacity +); + +/* Bytes wsap_vtcore_input_encode_paste() adds to the text at most. */ +#define WSAP_VTCORE_PASTE_EXTRA 12 + +/* + * Encode pasted text. Drop control characters and bidi controls, so the + * program sees only what the user saw. Send a line break as CR. Add the + * bracketed-paste markers when the program asked for them. A buffer of + * len + WSAP_VTCORE_PASTE_EXTRA bytes is always large enough. Text that is empty + * after the filter gives WSAP_VTCORE_INPUT_CONSUMED. + */ +WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_paste( + const struct wsap_vtcore_modes *modes, + const char *text, size_t len, + char *buf, size_t capacity +); +/* The cursor in screen coordinates (not the viewport). */ +WSAP_VTCORE_API struct wsap_vtcore_cursor wsap_vtcore_cursor(const struct wsap_vtcore *t); +/* Owned, NUL-terminated text from OSC 7 and OSC 22. NULL when unavailable + * or allocation fails. The strings stay valid after the terminal changes + * or is freed. Release them with wsap_vtcore_text_free(). */ +WSAP_VTCORE_API char *wsap_vtcore_cwd(const struct wsap_vtcore *t); +WSAP_VTCORE_API char *wsap_vtcore_pointer_shape(const struct wsap_vtcore *t); +/* Release any owned text returned by the library. NULL is safe. */ +WSAP_VTCORE_API void wsap_vtcore_text_free(char *text); + +/* + * Viewport. The viewport shows as many rows as the screen. Offset 0 shows + * the live screen; a larger offset shows that many rows of history above it. + * The alternate screen has no history, so its offset is always 0. + */ +struct wsap_vtcore_scrollback { + int offset; /* rows between the viewport and the live screen */ + int total; /* history rows at the current width */ +}; + +WSAP_VTCORE_API struct wsap_vtcore_scrollback wsap_vtcore_scrollback(const struct wsap_vtcore *t); +/* Scroll the viewport. A positive count moves back into history. */ +WSAP_VTCORE_API void wsap_vtcore_scroll(struct wsap_vtcore *t, int lines); +WSAP_VTCORE_API void wsap_vtcore_scroll_to(struct wsap_vtcore *t, int offset); + +/* + * Selection, in viewport coordinates. A selection starts at one cell and + * extends to another; the unit widens both ends to words or whole lines. + * The terminal clears the selection when the text under it changes. + */ +enum wsap_vtcore_select_unit { + WSAP_VTCORE_SELECT_CELL, + WSAP_VTCORE_SELECT_WORD, + WSAP_VTCORE_SELECT_LINE, +}; + +/* Start a selection at cell. For WSAP_VTCORE_SELECT_CELL, right_half means the + * pointer is on the right half of the cell, so the selection starts after it. + * Returns false when memory runs out; the selection is then unchanged. */ +WSAP_VTCORE_API bool wsap_vtcore_select_start(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half, + enum wsap_vtcore_select_unit unit); +/* Extend the selection from its start to cell. Returns false when memory runs + * out; the selection is then unchanged. */ +WSAP_VTCORE_API bool wsap_vtcore_select_extend(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half); +WSAP_VTCORE_API void wsap_vtcore_select_clear(struct wsap_vtcore *t); +WSAP_VTCORE_API bool wsap_vtcore_has_selection(const struct wsap_vtcore *t); +/* Owned, NUL-terminated UTF-8 of the selection. NULL when nothing is + * selected or allocation fails; a selection of blanks may produce an empty + * string. Capture is atomic with respect to other calls on t. Release the + * result with wsap_vtcore_text_free(). */ +WSAP_VTCORE_API char *wsap_vtcore_selection_text(const struct wsap_vtcore *t); +/* Owned OSC 8 link or detected URL at a viewport cell. NULL when there is + * no link or allocation fails. Release the result with wsap_vtcore_text_free(). */ +WSAP_VTCORE_API char *wsap_vtcore_link_at(const struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell); + +/* Cell attributes share the write core's bit layout. Underline styles are + * mutually exclusive flags, not a shifted enum; use wsap_vtcore_attr_underline(). */ +enum wsap_vtcore_attr { + WSAP_VTCORE_ATTR_BOLD = 1u << 0, + WSAP_VTCORE_ATTR_ITALIC = 1u << 1, + WSAP_VTCORE_ATTR_UNDERLINE = 1u << 2, + WSAP_VTCORE_ATTR_STRIKE = 1u << 3, + WSAP_VTCORE_ATTR_OVERLINE = 1u << 4, + WSAP_VTCORE_ATTR_EMOJI = 1u << 5, /* the text requested emoji presentation */ + WSAP_VTCORE_ATTR_TEXT = 1u << 6, /* the text requested text presentation */ + WSAP_VTCORE_ATTR_FAINT = 1u << 10, + WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE = 1u << 11, + WSAP_VTCORE_ATTR_CURLY_UNDERLINE = 1u << 12, + WSAP_VTCORE_ATTR_DOTTED_UNDERLINE = 1u << 13, + WSAP_VTCORE_ATTR_DASHED_UNDERLINE = 1u << 14, + WSAP_VTCORE_ATTR_LINK = 1u << 15, +}; + +#define WSAP_VTCORE_ATTR_UNDERLINE_MASK \ + (WSAP_VTCORE_ATTR_UNDERLINE | WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE | WSAP_VTCORE_ATTR_CURLY_UNDERLINE | \ + WSAP_VTCORE_ATTR_DOTTED_UNDERLINE | WSAP_VTCORE_ATTR_DASHED_UNDERLINE) + +enum wsap_vtcore_underline { + WSAP_VTCORE_UNDERLINE_NONE, + WSAP_VTCORE_UNDERLINE_SINGLE, + WSAP_VTCORE_UNDERLINE_DOUBLE, + WSAP_VTCORE_UNDERLINE_CURLY, + WSAP_VTCORE_UNDERLINE_DOTTED, + WSAP_VTCORE_UNDERLINE_DASHED, +}; + +static inline enum wsap_vtcore_underline wsap_vtcore_attr_underline(uint16_t attrs) +{ + if (attrs & WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DOUBLE; + if (attrs & WSAP_VTCORE_ATTR_CURLY_UNDERLINE) return WSAP_VTCORE_UNDERLINE_CURLY; + if (attrs & WSAP_VTCORE_ATTR_DOTTED_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DOTTED; + if (attrs & WSAP_VTCORE_ATTR_DASHED_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DASHED; + return attrs & WSAP_VTCORE_ATTR_UNDERLINE ? WSAP_VTCORE_UNDERLINE_SINGLE : WSAP_VTCORE_UNDERLINE_NONE; +} + +/* text refers to a grapheme cluster in the snapshot; see wsap_vtcore_snapshot_cluster(). */ +#define WSAP_VTCORE_TEXT_CLUSTER 0x80000000u + +/* One cell as a snapshot shows it. */ +struct wsap_vtcore_cell { + uint32_t text; /* a code point, WSAP_VTCORE_TEXT_CLUSTER | n, or 0 for an empty cell */ + wsap_vtcore_color fg, bg; + uint16_t attrs; /* enum wsap_vtcore_attr flags; at most one underline flag */ + uint8_t width; /* 1; 2 for a wide glyph; 0 for the right half of a wide glyph */ + uint8_t reserved; +}; + +#ifdef __cplusplus +static_assert(sizeof(struct wsap_vtcore_cell) == 16, "four cells fill one 64-byte line"); +#else +_Static_assert(sizeof(struct wsap_vtcore_cell) == 16, "four cells fill one 64-byte line"); +#endif + +/* + * Snapshot: a copy of the viewport for a renderer. It holds no pointer into + * the terminal, so it stays valid while the terminal changes. One terminal + * may have several snapshots, for example a window and a tab preview. + */ +WSAP_VTCORE_API struct wsap_vtcore_snapshot *wsap_vtcore_snapshot_new(void); +WSAP_VTCORE_API void wsap_vtcore_snapshot_free(struct wsap_vtcore_snapshot *s); + +/* Copy the viewport of t into s. Keep rows with unchanged content keys. + * Update the history view index and refine counts for visible wide lines. + * Return false when memory runs out. The snapshot then keeps its previous content. */ +WSAP_VTCORE_API bool wsap_vtcore_snapshot_update(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t); + +/* Palette entries of struct wsap_vtcore_view.palette after the 256 indexed colors. */ +enum { + WSAP_VTCORE_PALETTE_FG = 256, + WSAP_VTCORE_PALETTE_BG = 257, + WSAP_VTCORE_PALETTE_CURSOR = 258, + WSAP_VTCORE_PALETTE_SIZE = 259, +}; + +struct wsap_vtcore_view { + struct wsap_vtcore_vector2i size; + struct wsap_vtcore_cursor cursor; /* viewport coordinates; not visible when scrolled away */ + int scroll_offset; + /* Rows the content moved up since the previous update, when that movement + * explains the change; otherwise 0. */ + int scrolled; + bool reverse_video; + /* Changes when any part of the view changes. */ + uint64_t version; + /* Changes when a palette entry changes. */ + uint64_t palette_version; + const uint32_t *palette; /* WSAP_VTCORE_PALETTE_SIZE ARGB entries */ +}; + +/* The view of s, NULL for a NULL s. The view and view->palette keep their + * address until wsap_vtcore_snapshot_free(); their contents change on each update. */ +WSAP_VTCORE_API const struct wsap_vtcore_view *wsap_vtcore_snapshot_view(const struct wsap_vtcore_snapshot *s); +/* The cells of viewport row y: view->size.x entries. NULL when y is outside + * the viewport or s is NULL. An update can move the cells, so the pointer is + * valid only until the next wsap_vtcore_snapshot_update() or wsap_vtcore_snapshot_free() of s. */ +WSAP_VTCORE_API const struct wsap_vtcore_cell *wsap_vtcore_snapshot_row(const struct wsap_vtcore_snapshot *s, int y); +/* An identity for the content of row y. Two rows with the same key hold the + * same cells, also when the content moved to another row. 0 when y is outside + * the viewport or s is NULL. */ +WSAP_VTCORE_API uint64_t wsap_vtcore_snapshot_row_key(const struct wsap_vtcore_snapshot *s, int y); + +/* Number of rows in history above the screen. 0 if alternate screen or no history. */ +WSAP_VTCORE_API int wsap_vtcore_history_rows(const struct wsap_vtcore *t); +/* Owned, NUL-terminated UTF-8 of up to max_rows history rows before the + * current viewport. Join soft-wrapped rows and end closed lines with a + * newline. Does not change the selection. No history or max_rows <= 0 gives + * an empty string; NULL means allocation failed or t is NULL. Release the + * result with wsap_vtcore_text_free(). */ +WSAP_VTCORE_API char *wsap_vtcore_history_text(struct wsap_vtcore *t, int max_rows); +/* The selected columns of viewport row y, end exclusive. An empty span when y + * is outside the viewport or s is NULL. */ +WSAP_VTCORE_API struct wsap_vtcore_span wsap_vtcore_snapshot_row_selection(const struct wsap_vtcore_snapshot *s, int y); + +/* The code points of a cluster cell. Returns the number of code points and + * writes at most cap of them. Writes nothing when cps is NULL or cap is 0. + * Returns 0 when s is NULL. */ +WSAP_VTCORE_API int wsap_vtcore_snapshot_cluster(const struct wsap_vtcore_snapshot *s, uint32_t text, uint32_t *cps, int cap); + +/* The ARGB value of a color in a view. */ +static inline uint32_t wsap_vtcore_view_color(const struct wsap_vtcore_view *v, wsap_vtcore_color c) +{ + if (!wsap_vtcore_color_is_slot(c)) + return c; + return v->palette[c & WSAP_VTCORE_COLOR_SLOT_INDEX]; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/wsap_vtcore/wsap_vtcore_input.h b/include/wsap_vtcore/wsap_vtcore_input.h new file mode 100644 index 0000000..337a292 --- /dev/null +++ b/include/wsap_vtcore/wsap_vtcore_input.h @@ -0,0 +1,202 @@ +#ifndef WSAP_VTCORE_INPUT_H +#define WSAP_VTCORE_INPUT_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include "wsap_vtcore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum wsap_vtcore_key { + WSAP_VTCORE_KEY_NONE = 0, + + WSAP_VTCORE_KEY_RETURN, + WSAP_VTCORE_KEY_BACKSPACE, + WSAP_VTCORE_KEY_TAB, + WSAP_VTCORE_KEY_ESCAPE, + + WSAP_VTCORE_KEY_UP, + WSAP_VTCORE_KEY_DOWN, + WSAP_VTCORE_KEY_RIGHT, + WSAP_VTCORE_KEY_LEFT, + WSAP_VTCORE_KEY_HOME, + WSAP_VTCORE_KEY_END, + WSAP_VTCORE_KEY_PAGE_UP, + WSAP_VTCORE_KEY_PAGE_DOWN, + WSAP_VTCORE_KEY_INSERT, + WSAP_VTCORE_KEY_DELETE, + + WSAP_VTCORE_KEY_F1, WSAP_VTCORE_KEY_F2, WSAP_VTCORE_KEY_F3, WSAP_VTCORE_KEY_F4, WSAP_VTCORE_KEY_F5, + WSAP_VTCORE_KEY_F6, WSAP_VTCORE_KEY_F7, WSAP_VTCORE_KEY_F8, WSAP_VTCORE_KEY_F9, WSAP_VTCORE_KEY_F10, + WSAP_VTCORE_KEY_F11, WSAP_VTCORE_KEY_F12, WSAP_VTCORE_KEY_F13, WSAP_VTCORE_KEY_F14, WSAP_VTCORE_KEY_F15, + WSAP_VTCORE_KEY_F16, WSAP_VTCORE_KEY_F17, WSAP_VTCORE_KEY_F18, WSAP_VTCORE_KEY_F19, WSAP_VTCORE_KEY_F20, + WSAP_VTCORE_KEY_F21, WSAP_VTCORE_KEY_F22, WSAP_VTCORE_KEY_F23, WSAP_VTCORE_KEY_F24, WSAP_VTCORE_KEY_F25, + WSAP_VTCORE_KEY_F26, WSAP_VTCORE_KEY_F27, WSAP_VTCORE_KEY_F28, WSAP_VTCORE_KEY_F29, WSAP_VTCORE_KEY_F30, + WSAP_VTCORE_KEY_F31, WSAP_VTCORE_KEY_F32, WSAP_VTCORE_KEY_F33, WSAP_VTCORE_KEY_F34, WSAP_VTCORE_KEY_F35, + + WSAP_VTCORE_KEY_KP_0, WSAP_VTCORE_KEY_KP_1, WSAP_VTCORE_KEY_KP_2, WSAP_VTCORE_KEY_KP_3, WSAP_VTCORE_KEY_KP_4, + WSAP_VTCORE_KEY_KP_5, WSAP_VTCORE_KEY_KP_6, WSAP_VTCORE_KEY_KP_7, WSAP_VTCORE_KEY_KP_8, WSAP_VTCORE_KEY_KP_9, + WSAP_VTCORE_KEY_KP_DECIMAL, + WSAP_VTCORE_KEY_KP_ENTER, + WSAP_VTCORE_KEY_KP_ADD, + WSAP_VTCORE_KEY_KP_SUBTRACT, + WSAP_VTCORE_KEY_KP_MULTIPLY, + WSAP_VTCORE_KEY_KP_DIVIDE, + WSAP_VTCORE_KEY_KP_EQUAL, + WSAP_VTCORE_KEY_KP_SEPARATOR, + WSAP_VTCORE_KEY_KP_LEFT, + WSAP_VTCORE_KEY_KP_RIGHT, + WSAP_VTCORE_KEY_KP_UP, + WSAP_VTCORE_KEY_KP_DOWN, + WSAP_VTCORE_KEY_KP_PAGE_UP, + WSAP_VTCORE_KEY_KP_PAGE_DOWN, + WSAP_VTCORE_KEY_KP_HOME, + WSAP_VTCORE_KEY_KP_END, + WSAP_VTCORE_KEY_KP_INSERT, + WSAP_VTCORE_KEY_KP_DELETE, + WSAP_VTCORE_KEY_KP_BEGIN, + + WSAP_VTCORE_KEY_CAPS_LOCK, + WSAP_VTCORE_KEY_SCROLL_LOCK, + WSAP_VTCORE_KEY_NUM_LOCK, + WSAP_VTCORE_KEY_PRINT_SCREEN, + WSAP_VTCORE_KEY_PAUSE, + WSAP_VTCORE_KEY_MENU, + + WSAP_VTCORE_KEY_MEDIA_PLAY, + WSAP_VTCORE_KEY_MEDIA_PAUSE, + WSAP_VTCORE_KEY_MEDIA_STOP, + WSAP_VTCORE_KEY_MEDIA_FORWARD, + WSAP_VTCORE_KEY_MEDIA_REWIND, + WSAP_VTCORE_KEY_MEDIA_NEXT, + WSAP_VTCORE_KEY_MEDIA_PREV, + WSAP_VTCORE_KEY_MEDIA_RECORD, + WSAP_VTCORE_KEY_VOLUME_DOWN, + WSAP_VTCORE_KEY_VOLUME_UP, + WSAP_VTCORE_KEY_MUTE, + + WSAP_VTCORE_KEY_LSHIFT, + WSAP_VTCORE_KEY_LCTRL, + WSAP_VTCORE_KEY_LALT, + WSAP_VTCORE_KEY_LSUPER, + WSAP_VTCORE_KEY_LHYPER, + WSAP_VTCORE_KEY_LMETA, + WSAP_VTCORE_KEY_RSHIFT, + WSAP_VTCORE_KEY_RCTRL, + WSAP_VTCORE_KEY_RALT, + WSAP_VTCORE_KEY_RSUPER, + WSAP_VTCORE_KEY_RHYPER, + WSAP_VTCORE_KEY_RMETA, + WSAP_VTCORE_KEY_ISO_LEVEL3_SHIFT, + WSAP_VTCORE_KEY_ISO_LEVEL5_SHIFT, + + WSAP_VTCORE_KEY_COUNT +}; + +enum wsap_vtcore_mod { + WSAP_VTCORE_MOD_SHIFT = 1, + WSAP_VTCORE_MOD_ALT = 2, + WSAP_VTCORE_MOD_CTRL = 4, + WSAP_VTCORE_MOD_SUPER = 8, + WSAP_VTCORE_MOD_HYPER = 16, + WSAP_VTCORE_MOD_META = 32, + WSAP_VTCORE_MOD_CAPS = 64, + WSAP_VTCORE_MOD_NUM = 128, +}; + +enum wsap_vtcore_key_action { + WSAP_VTCORE_KEY_PRESS = 1, + WSAP_VTCORE_KEY_REPEAT = 2, + WSAP_VTCORE_KEY_RELEASE = 3, +}; + +enum wsap_vtcore_mouse_button { + WSAP_VTCORE_MOUSE_BUTTON_PRIMARY = 0, + WSAP_VTCORE_MOUSE_BUTTON_MIDDLE, + WSAP_VTCORE_MOUSE_BUTTON_SECONDARY, + WSAP_VTCORE_MOUSE_BUTTON_NONE, + /* Extra buttons 8 through 11 in xterm mouse reporting (encoded as 128..131). */ + WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1, + WSAP_VTCORE_MOUSE_BUTTON_EXTRA_2, + WSAP_VTCORE_MOUSE_BUTTON_EXTRA_3, + WSAP_VTCORE_MOUSE_BUTTON_EXTRA_4, + WSAP_VTCORE_MOUSE_WHEEL_UP = 16, + WSAP_VTCORE_MOUSE_WHEEL_DOWN, + WSAP_VTCORE_MOUSE_WHEEL_LEFT, + WSAP_VTCORE_MOUSE_WHEEL_RIGHT, +}; + +enum wsap_vtcore_mouse_event_kind { + WSAP_VTCORE_MOUSE_PRESS = 0, + WSAP_VTCORE_MOUSE_RELEASE, + WSAP_VTCORE_MOUSE_MOTION, + WSAP_VTCORE_MOUSE_SCROLL, + WSAP_VTCORE_MOUSE_LEAVE, +}; + +struct wsap_vtcore_key_event { + enum wsap_vtcore_key_action action; + uint16_t key; /* enum wsap_vtcore_key; WSAP_VTCORE_KEY_NONE for a text key */ + uint16_t keypad; /* the WSAP_VTCORE_KEY_KP_* key when the key is on the keypad */ + unsigned mods; /* enum wsap_vtcore_mod */ + uint32_t codepoint; /* the code point of the key without modifiers */ + uint32_t shifted; /* the code point of the key with Shift */ + uint32_t base; /* the code point of the key in the US layout */ + uint32_t text; /* the code point the key types, or 0 */ + bool text_deferred; /* an input method sends the text later */ +}; + +struct wsap_vtcore_mouse_event { + struct wsap_vtcore_vector2i pos; /* Grid cell coordinates (col, row) */ + struct wsap_vtcore_vector2i pixel; /* Absolute pixel position in terminal grid */ + /* + * Button identifier: + * - Press and release: the button that changed state (WSAP_VTCORE_MOUSE_BUTTON_*). + * - Motion: the held button for drag events, or WSAP_VTCORE_MOUSE_BUTTON_NONE for hover. + * - Scroll: the wheel direction (WSAP_VTCORE_MOUSE_WHEEL_*). + */ + int button; + unsigned mods; + int scroll_lines; + float scroll_delta; + enum wsap_vtcore_mouse_event_kind kind; +}; + +/* The keys that are down. An all-zero value has no keys down. */ +struct wsap_vtcore_keyboard_state { + uint64_t down[(WSAP_VTCORE_KEY_COUNT + 63) / 64]; +}; + +/* Record a press, repeat, or release in s. */ +WSAP_VTCORE_API void wsap_vtcore_keyboard_update(struct wsap_vtcore_keyboard_state *s, const struct wsap_vtcore_key_event *ev); +WSAP_VTCORE_API bool wsap_vtcore_keyboard_key_down(const struct wsap_vtcore_keyboard_state *s, enum wsap_vtcore_key key); + +/* Kitty keyboard protocol flags, as in wsap_vtcore_modes.keyboard. */ +enum wsap_vtcore_keyboard_flag { + WSAP_VTCORE_KEYBOARD_DISAMBIGUATE = 1, + WSAP_VTCORE_KEYBOARD_EVENT_TYPES = 2, + WSAP_VTCORE_KEYBOARD_ALTERNATE_KEYS = 4, + WSAP_VTCORE_KEYBOARD_ALL_KEYS = 8, + WSAP_VTCORE_KEYBOARD_ASSOCIATED_TEXT = 16, +}; + +enum wsap_vtcore_input_status { + WSAP_VTCORE_INPUT_UNHANDLED = 0, /* the terminal does not use the event */ + WSAP_VTCORE_INPUT_CONSUMED, /* the terminal uses the event but sends nothing */ + WSAP_VTCORE_INPUT_BYTES, /* send the len bytes in buf to the program */ + WSAP_VTCORE_INPUT_BUFFER_FULL, /* buf is too small; len is 0 */ +}; + +struct wsap_vtcore_input_result { + size_t len; + enum wsap_vtcore_input_status status; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* WSAP_VTCORE_INPUT_H */ diff --git a/include/term/term_types.h b/include/wsap_vtcore/wsap_vtcore_types.h index 78be371..0944da3 100644 --- a/include/term/term_types.h +++ b/include/wsap_vtcore/wsap_vtcore_types.h @@ -1,14 +1,14 @@ -#ifndef TERM_TYPES_H -#define TERM_TYPES_H +#ifndef WSAP_VTCORE_TYPES_H +#define WSAP_VTCORE_TYPES_H /* Marks the public functions. The library builds with hidden symbols, so * only these are visible outside a shared build. A host can define it * first, for example as __declspec(dllimport). */ -#ifndef TERM_API +#ifndef WSAP_VTCORE_API #if defined(__GNUC__) || defined(__clang__) -#define TERM_API __attribute__((visibility("default"))) +#define WSAP_VTCORE_API __attribute__((visibility("default"))) #else -#define TERM_API +#define WSAP_VTCORE_API #endif #endif @@ -16,11 +16,11 @@ extern "C" { #endif -struct term_vector2i { +struct wsap_vtcore_vector2i { int x, y; }; -struct term_span { +struct wsap_vtcore_span { int begin; int end; }; diff --git a/meson.build b/meson.build index e25bf13..61eb606 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('term', 'c', +project('wsap_vtcore', 'c', version: '0.1.0', license: 'MIT', license_files: 'LICENSE', @@ -22,54 +22,54 @@ if get_option('arch_flag') != '' endif # A host sees include/ only. The sources also find the public headers -# without the term/ prefix. -term_inc = include_directories('include') -term_private_inc = include_directories('src', 'include/term') +# without the wsap_vtcore/ prefix. +wsap_vtcore_inc = include_directories('include') +wsap_vtcore_private_inc = include_directories('src', 'include/wsap_vtcore') subdir('src') -term_dep = declare_dependency( - include_directories: term_inc, - link_with: term_lib.get_static_lib(), +wsap_vtcore_dep = declare_dependency( + include_directories: wsap_vtcore_inc, + link_with: wsap_vtcore_lib.get_static_lib(), dependencies: [m_dep, thread_dep], ) -meson.override_dependency('term', term_dep) +meson.override_dependency('wsap_vtcore', wsap_vtcore_dep) -# The private headers too. Only the term tests and benchmarks use it. -term_internal_dep = declare_dependency( - include_directories: [term_inc, term_private_inc], - link_with: term_lib.get_static_lib(), +# The private headers too. Only the wsap_vtcore tests and benchmarks use it. +wsap_vtcore_internal_dep = declare_dependency( + include_directories: [wsap_vtcore_inc, wsap_vtcore_private_inc], + link_with: wsap_vtcore_lib.get_static_lib(), dependencies: [m_dep, thread_dep], ) -# The short forms of term.h that the term tests use. A host project can use +# The short forms of wsap_vtcore.h that the tests use. A host project can use # them in its own tests. -term_test_dep = declare_dependency( +wsap_vtcore_test_dep = declare_dependency( include_directories: include_directories('tests/helpers'), - dependencies: term_dep, + dependencies: wsap_vtcore_dep, ) -meson.override_dependency('term-test', term_test_dep) +meson.override_dependency('wsap_vtcore-test', wsap_vtcore_test_dep) install_headers( - 'include/term/term.h', - 'include/term/term_input.h', - 'include/term/term_types.h', - subdir: 'term', + 'include/wsap_vtcore/wsap_vtcore.h', + 'include/wsap_vtcore/wsap_vtcore_input.h', + 'include/wsap_vtcore/wsap_vtcore_types.h', + subdir: 'wsap_vtcore', ) install_headers( - 'include/term/unicode/grapheme.h', - 'include/term/unicode/unicode.h', - 'include/term/unicode/unicode_data.inc', - 'include/term/unicode/utf8.h', - 'include/term/unicode/width.h', - subdir: 'term/unicode', + 'include/wsap_vtcore/unicode/grapheme.h', + 'include/wsap_vtcore/unicode/unicode.h', + 'include/wsap_vtcore/unicode/unicode_data.inc', + 'include/wsap_vtcore/unicode/utf8.h', + 'include/wsap_vtcore/unicode/width.h', + subdir: 'wsap_vtcore/unicode', ) pkg = import('pkgconfig') pkg.generate( - term_lib.get_shared_lib(), - name: 'term', + wsap_vtcore_lib.get_shared_lib(), + name: 'wsap_vtcore', description: 'Headless terminal emulator core library', version: meson.project_version(), subdirs: ['.'], diff --git a/meson.options b/meson.options index 3a339a3..a290918 100644 --- a/meson.options +++ b/meson.options @@ -8,7 +8,7 @@ option( 'tests', type: 'boolean', value: true, - description: 'Build and register the term tests and benchmarks', + description: 'Build and register the wsap_vtcore tests and benchmarks', ) option( 'write_fuzz_seeds', @@ -1,33 +1,33 @@ -#ifndef TERM_CELL_H -#define TERM_CELL_H +#ifndef WSAP_VTCORE_CELL_H +#define WSAP_VTCORE_CELL_H /* * The cell layout that the terminal stores. Only src/term uses it. A - * snapshot converts these cells to the public struct term_cell. + * snapshot converts these cells to the public struct wsap_vtcore_cell. */ -#include "term.h" +#include "wsap_vtcore.h" enum cell_flags { - CELL_BOLD = TERM_ATTR_BOLD, - CELL_ITALIC = TERM_ATTR_ITALIC, - CELL_UNDERLINE = TERM_ATTR_UNDERLINE, - CELL_STRIKE = TERM_ATTR_STRIKE, - CELL_OVERLINE = TERM_ATTR_OVERLINE, - CELL_EMOJI = TERM_ATTR_EMOJI, - CELL_TEXT = TERM_ATTR_TEXT, + CELL_BOLD = WSAP_VTCORE_ATTR_BOLD, + CELL_ITALIC = WSAP_VTCORE_ATTR_ITALIC, + CELL_UNDERLINE = WSAP_VTCORE_ATTR_UNDERLINE, + CELL_STRIKE = WSAP_VTCORE_ATTR_STRIKE, + CELL_OVERLINE = WSAP_VTCORE_ATTR_OVERLINE, + CELL_EMOJI = WSAP_VTCORE_ATTR_EMOJI, + CELL_TEXT = WSAP_VTCORE_ATTR_TEXT, CELL_WIDE = 1 << 7, CELL_TRAIL = 1 << 8, CELL_WRAP_PAD = 1 << 9, - CELL_FAINT = TERM_ATTR_FAINT, - CELL_DOUBLE_UNDERLINE = TERM_ATTR_DOUBLE_UNDERLINE, - CELL_CURLY_UNDERLINE = TERM_ATTR_CURLY_UNDERLINE, - CELL_DOTTED_UNDERLINE = TERM_ATTR_DOTTED_UNDERLINE, - CELL_DASHED_UNDERLINE = TERM_ATTR_DASHED_UNDERLINE, - CELL_LINK = TERM_ATTR_LINK, + CELL_FAINT = WSAP_VTCORE_ATTR_FAINT, + CELL_DOUBLE_UNDERLINE = WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE, + CELL_CURLY_UNDERLINE = WSAP_VTCORE_ATTR_CURLY_UNDERLINE, + CELL_DOTTED_UNDERLINE = WSAP_VTCORE_ATTR_DOTTED_UNDERLINE, + CELL_DASHED_UNDERLINE = WSAP_VTCORE_ATTR_DASHED_UNDERLINE, + CELL_LINK = WSAP_VTCORE_ATTR_LINK, }; -#define CELL_ANY_UNDERLINE TERM_ATTR_UNDERLINE_MASK +#define CELL_ANY_UNDERLINE WSAP_VTCORE_ATTR_UNDERLINE_MASK /* c is a code point or a grapheme handle. pad holds the OSC 8 link id. */ struct cell { diff --git a/src/compat.h b/src/compat.h index 6c3302f..0b4559e 100644 --- a/src/compat.h +++ b/src/compat.h @@ -1,10 +1,10 @@ -#ifndef TERM_COMPAT_H -#define TERM_COMPAT_H +#ifndef WSAP_VTCORE_COMPAT_H +#define WSAP_VTCORE_COMPAT_H /* * Compiler and libc differences, kept in one place. GCC and Clang use their * builtins. MSVC uses its intrinsics. Any other compiler, and any build with - * TERM_NO_COMPILER_BUILTINS, uses plain C. Plain C gives the same results, + * WSAP_VTCORE_NO_COMPILER_BUILTINS, uses plain C. Plain C gives the same results, * only slower. */ @@ -28,68 +28,68 @@ #endif #if defined(__GNUC__) || defined(__clang__) -#define TERM_COMPILER_GNU 1 +#define WSAP_VTCORE_COMPILER_GNU 1 #elif defined(_MSC_VER) -#define TERM_COMPILER_MSVC 1 +#define WSAP_VTCORE_COMPILER_MSVC 1 #include <intrin.h> #endif -#if !defined(TERM_NO_COMPILER_BUILTINS) && defined(TERM_COMPILER_GNU) -#define TERM_HAVE_BUILTINS 1 -#elif !defined(TERM_NO_COMPILER_BUILTINS) && defined(TERM_COMPILER_MSVC) -#define TERM_HAVE_MSVC_BITOPS 1 +#if !defined(WSAP_VTCORE_NO_COMPILER_BUILTINS) && defined(WSAP_VTCORE_COMPILER_GNU) +#define WSAP_VTCORE_HAVE_BUILTINS 1 +#elif !defined(WSAP_VTCORE_NO_COMPILER_BUILTINS) && defined(WSAP_VTCORE_COMPILER_MSVC) +#define WSAP_VTCORE_HAVE_MSVC_BITOPS 1 #endif -#if defined(TERM_COMPILER_GNU) -#define TERM_HOT __attribute__((hot)) -#define TERM_NOINLINE __attribute__((noinline)) -#define TERM_ALWAYS_INLINE __attribute__((always_inline)) -#define TERM_MAYBE_UNUSED __attribute__((unused)) -#elif defined(TERM_COMPILER_MSVC) -#define TERM_HOT -#define TERM_NOINLINE __declspec(noinline) -#define TERM_ALWAYS_INLINE __forceinline -#define TERM_MAYBE_UNUSED +#if defined(WSAP_VTCORE_COMPILER_GNU) +#define WSAP_VTCORE_HOT __attribute__((hot)) +#define WSAP_VTCORE_NOINLINE __attribute__((noinline)) +#define WSAP_VTCORE_ALWAYS_INLINE __attribute__((always_inline)) +#define WSAP_VTCORE_MAYBE_UNUSED __attribute__((unused)) +#elif defined(WSAP_VTCORE_COMPILER_MSVC) +#define WSAP_VTCORE_HOT +#define WSAP_VTCORE_NOINLINE __declspec(noinline) +#define WSAP_VTCORE_ALWAYS_INLINE __forceinline +#define WSAP_VTCORE_MAYBE_UNUSED #else -#define TERM_HOT -#define TERM_NOINLINE -#define TERM_ALWAYS_INLINE -#define TERM_MAYBE_UNUSED +#define WSAP_VTCORE_HOT +#define WSAP_VTCORE_NOINLINE +#define WSAP_VTCORE_ALWAYS_INLINE +#define WSAP_VTCORE_MAYBE_UNUSED #endif -#if defined(TERM_HAVE_BUILTINS) -#define TERM_EXPECT(x, v) __builtin_expect((x), (v)) +#if defined(WSAP_VTCORE_HAVE_BUILTINS) +#define WSAP_VTCORE_EXPECT(x, v) __builtin_expect((x), (v)) #else -#define TERM_EXPECT(x, v) (x) +#define WSAP_VTCORE_EXPECT(x, v) (x) #endif -/* term_ctz32(0) is 32, term_clz32(0) is 32, term_ctz64(0) is 64, and - * term_clz64(0) is 64 on every path. */ -#if defined(TERM_HAVE_BUILTINS) +/* wsap_vtcore_ctz32(0) is 32, wsap_vtcore_clz32(0) is 32, wsap_vtcore_ctz64(0) is 64, and + * wsap_vtcore_clz64(0) is 64 on every path. */ +#if defined(WSAP_VTCORE_HAVE_BUILTINS) -static inline int term_ctz32(uint32_t x) { return x ? __builtin_ctz(x) : 32; } -static inline int term_clz32(uint32_t x) { return x ? __builtin_clz(x) : 32; } -static inline int term_popcount32(uint32_t x) { return __builtin_popcount(x); } -static inline int term_ctz64(uint64_t x) { return x ? __builtin_ctzll(x) : 64; } -static inline int term_clz64(uint64_t x) { return x ? __builtin_clzll(x) : 64; } -static inline int term_popcount64(uint64_t x) { return __builtin_popcountll(x); } +static inline int wsap_vtcore_ctz32(uint32_t x) { return x ? __builtin_ctz(x) : 32; } +static inline int wsap_vtcore_clz32(uint32_t x) { return x ? __builtin_clz(x) : 32; } +static inline int wsap_vtcore_popcount32(uint32_t x) { return __builtin_popcount(x); } +static inline int wsap_vtcore_ctz64(uint64_t x) { return x ? __builtin_ctzll(x) : 64; } +static inline int wsap_vtcore_clz64(uint64_t x) { return x ? __builtin_clzll(x) : 64; } +static inline int wsap_vtcore_popcount64(uint64_t x) { return __builtin_popcountll(x); } #else -#if defined(TERM_HAVE_MSVC_BITOPS) -static inline int term_ctz32(uint32_t x) +#if defined(WSAP_VTCORE_HAVE_MSVC_BITOPS) +static inline int wsap_vtcore_ctz32(uint32_t x) { unsigned long i; return _BitScanForward(&i, x) ? (int)i : 32; } -static inline int term_clz32(uint32_t x) +static inline int wsap_vtcore_clz32(uint32_t x) { unsigned long i; return _BitScanReverse(&i, x) ? 31 - (int)i : 32; } -static inline int term_popcount32(uint32_t x) { return (int)__popcnt(x); } +static inline int wsap_vtcore_popcount32(uint32_t x) { return (int)__popcnt(x); } #else -static inline int term_ctz32(uint32_t x) +static inline int wsap_vtcore_ctz32(uint32_t x) { if (!x) return 32; @@ -99,7 +99,7 @@ static inline int term_ctz32(uint32_t x) }; return (int)de_bruijn[((uint32_t)((x & -x) * 0x077CB531U)) >> 27]; } -static inline int term_clz32(uint32_t x) +static inline int wsap_vtcore_clz32(uint32_t x) { if (!x) return 32; @@ -111,7 +111,7 @@ static inline int term_clz32(uint32_t x) if (!(x & 0x80000000u)) { n += 1; } return n; } -static inline int term_popcount32(uint32_t x) +static inline int wsap_vtcore_popcount32(uint32_t x) { x = x - ((x >> 1) & 0x55555555u); x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u); @@ -120,75 +120,75 @@ static inline int term_popcount32(uint32_t x) #endif /* Without builtins, the 64-bit forms are built from the 32-bit ones. */ -static inline int term_ctz64(uint64_t x) +static inline int wsap_vtcore_ctz64(uint64_t x) { uint32_t lo = (uint32_t)x; - return lo ? term_ctz32(lo) : 32 + term_ctz32((uint32_t)(x >> 32)); + return lo ? wsap_vtcore_ctz32(lo) : 32 + wsap_vtcore_ctz32((uint32_t)(x >> 32)); } -static inline int term_clz64(uint64_t x) +static inline int wsap_vtcore_clz64(uint64_t x) { uint32_t hi = (uint32_t)(x >> 32); - return hi ? term_clz32(hi) : 32 + term_clz32((uint32_t)x); + return hi ? wsap_vtcore_clz32(hi) : 32 + wsap_vtcore_clz32((uint32_t)x); } -static inline int term_popcount64(uint64_t x) +static inline int wsap_vtcore_popcount64(uint64_t x) { - return term_popcount32((uint32_t)x) + term_popcount32((uint32_t)(x >> 32)); + return wsap_vtcore_popcount32((uint32_t)x) + wsap_vtcore_popcount32((uint32_t)(x >> 32)); } #endif /* Smallest power of two >= x, branchlessly via CLZ. Returns UINT32_MAX on overflow. */ -static inline uint32_t term_next_pow2_32(uint32_t x) +static inline uint32_t wsap_vtcore_next_pow2_32(uint32_t x) { uint32_t v = x <= 1 ? 1 : x - 1; - int lz = term_clz32(v); + int lz = wsap_vtcore_clz32(v); uint32_t res = UINT32_C(1) << ((32 - lz) & 31); return (x <= 1) ? 1 : (lz == 0 ? UINT32_MAX : res); } /* Smallest power of two >= x, branchlessly via CLZ. Returns UINT64_MAX on overflow. */ -static inline uint64_t term_next_pow2_64(uint64_t x) +static inline uint64_t wsap_vtcore_next_pow2_64(uint64_t x) { uint64_t v = x <= 1 ? 1 : x - 1; - int lz = term_clz64(v); + int lz = wsap_vtcore_clz64(v); uint64_t res = UINT64_C(1) << ((64 - lz) & 63); return (x <= 1) ? 1 : (lz == 0 ? UINT64_MAX : res); } /* Grows cap by doubling until >= need, branchlessly. * If cap >= need, returns cap. Otherwise returns next power of two >= need. */ -static inline uint32_t term_grow_cap32(uint32_t cap, uint32_t need) +static inline uint32_t wsap_vtcore_grow_cap32(uint32_t cap, uint32_t need) { - return cap >= need ? cap : term_next_pow2_32(need); + return cap >= need ? cap : wsap_vtcore_next_pow2_32(need); } -static inline uint64_t term_grow_cap64(uint64_t cap, uint64_t need) +static inline uint64_t wsap_vtcore_grow_cap64(uint64_t cap, uint64_t need) { - return cap >= need ? cap : term_next_pow2_64(need); + return cap >= need ? cap : wsap_vtcore_next_pow2_64(need); } -static inline size_t term_grow_cap(size_t cap, size_t need) +static inline size_t wsap_vtcore_grow_cap(size_t cap, size_t need) { #if SIZE_MAX > UINT32_MAX - return (size_t)term_grow_cap64(cap, need); + return (size_t)wsap_vtcore_grow_cap64(cap, need); #else - return (size_t)term_grow_cap32((uint32_t)cap, (uint32_t)need); + return (size_t)wsap_vtcore_grow_cap32((uint32_t)cap, (uint32_t)need); #endif } /* A spin-wait hint. Compilers without one get a no-op. */ -static inline void term_cpu_relax(void) +static inline void wsap_vtcore_cpu_relax(void) { -#if defined(TERM_COMPILER_GNU) -#if defined(TERM_HAVE_BUILTINS) && defined(__x86_64__) +#if defined(WSAP_VTCORE_COMPILER_GNU) +#if defined(WSAP_VTCORE_HAVE_BUILTINS) && defined(__x86_64__) __builtin_ia32_pause(); #elif defined(__aarch64__) __asm__ __volatile__("yield"); #endif -#elif defined(TERM_COMPILER_MSVC) +#elif defined(WSAP_VTCORE_COMPILER_MSVC) #if defined(_M_X64) || defined(_M_IX86) _mm_pause(); #elif defined(_M_ARM64) @@ -199,11 +199,11 @@ static inline void term_cpu_relax(void) /* The writer lock. POSIX uses a mutex with priority inheritance where the * platform has it, so a waiter lifts the thread that holds the lock. Windows - * uses an SRWLOCK. Neither nests, so term_write_begin() counts re-entry. */ + * uses an SRWLOCK. Neither nests, so wsap_vtcore_write_begin() counts re-entry. */ #if defined(_WIN32) -typedef SRWLOCK term_mutex; +typedef SRWLOCK wsap_vtcore_mutex; #else -typedef pthread_mutex_t term_mutex; +typedef pthread_mutex_t wsap_vtcore_mutex; /* Strict C11 can hide PTHREAD_PRIO_INHERIT in pthread.h, as zig's aarch64 * glibc headers do. Every POSIX system that has the option uses 1 for it. */ #if !defined(PTHREAD_PRIO_INHERIT) @@ -212,7 +212,7 @@ typedef pthread_mutex_t term_mutex; #endif /* Returns false when the lock cannot be made. */ -static inline bool term_mutex_init(term_mutex *m) +static inline bool wsap_vtcore_mutex_init(wsap_vtcore_mutex *m) { #if defined(_WIN32) InitializeSRWLock(m); @@ -231,7 +231,7 @@ static inline bool term_mutex_init(term_mutex *m) } /* A normal mutex fails only when it is broken, so the result is ignored. */ -static inline void term_mutex_lock(term_mutex *m) +static inline void wsap_vtcore_mutex_lock(wsap_vtcore_mutex *m) { #if defined(_WIN32) AcquireSRWLockExclusive(m); @@ -240,7 +240,7 @@ static inline void term_mutex_lock(term_mutex *m) #endif } -static inline void term_mutex_unlock(term_mutex *m) +static inline void wsap_vtcore_mutex_unlock(wsap_vtcore_mutex *m) { #if defined(_WIN32) ReleaseSRWLockExclusive(m); @@ -250,7 +250,7 @@ static inline void term_mutex_unlock(term_mutex *m) } /* An SRWLOCK has no destroy. */ -static inline void term_mutex_destroy(term_mutex *m) +static inline void wsap_vtcore_mutex_destroy(wsap_vtcore_mutex *m) { #if defined(_WIN32) (void)m; @@ -260,7 +260,7 @@ static inline void term_mutex_destroy(term_mutex *m) } /* strdup is POSIX, so the core copies strings itself. */ -static inline char *term_strdup(const char *s) +static inline char *wsap_vtcore_strdup(const char *s) { size_t n = strlen(s) + 1; char *copy = malloc(n); @@ -270,7 +270,7 @@ static inline char *term_strdup(const char *s) } /* ASCII-only prefix test, as strncasecmp() does in the C locale. */ -static inline bool term_has_prefix_ci(const char *s, const char *prefix) +static inline bool wsap_vtcore_has_prefix_ci(const char *s, const char *prefix) { for (; *prefix; prefix++, s++) { unsigned char a = (unsigned char)*s; @@ -285,9 +285,9 @@ static inline bool term_has_prefix_ci(const char *s, const char *prefix) /* Allocates size bytes that start on an align-byte boundary. align must be a * power of two. The raw pointer is stored just before the block, so - * term_aligned_free() can release it. C11 aligned_alloc() and POSIX + * wsap_vtcore_aligned_free() can release it. C11 aligned_alloc() and POSIX * posix_memalign() are not on every toolchain. */ -static inline void *term_aligned_alloc(size_t align, size_t size) +static inline void *wsap_vtcore_aligned_alloc(size_t align, size_t size) { if (size > SIZE_MAX - align - sizeof(void *)) return NULL; @@ -299,7 +299,7 @@ static inline void *term_aligned_alloc(size_t align, size_t size) return (void *)p; } -static inline void term_aligned_free(void *p) +static inline void wsap_vtcore_aligned_free(void *p) { if (p) free(((void **)p)[-1]); @@ -16,13 +16,13 @@ static uint16_t cluster_presentation(const uint32_t *cps, int len) { if (len <= 1) return 0; - bool pictographic = term_unicode_extended_pictographic(cps[0]); + bool pictographic = wsap_vtcore_unicode_extended_pictographic(cps[0]); if (len == 2) { uint32_t c1 = cps[1]; if (c1 == 0xFE0F) return CELL_EMOJI; if (c1 == 0xFE0E) return CELL_TEXT; - if (c1 == 0x20E3 || term_grapheme_regional_indicator(c1) || - (pictographic && (c1 == 0x200D || term_grapheme_emoji_modifier(c1) || + if (c1 == 0x20E3 || wsap_vtcore_grapheme_regional_indicator(c1) || + (pictographic && (c1 == 0x200D || wsap_vtcore_grapheme_emoji_modifier(c1) || (c1 >= 0xE0020 && c1 <= 0xE007F)))) return CELL_EMOJI; return 0; @@ -33,40 +33,40 @@ static uint16_t cluster_presentation(const uint32_t *cps, int len) return CELL_EMOJI; if (cps[i] == 0xFE0E) return CELL_TEXT; - if (cps[i] == 0x20E3 || term_grapheme_regional_indicator(cps[i]) || - (pictographic && (cps[i] == 0x200D || term_grapheme_emoji_modifier(cps[i]) || + if (cps[i] == 0x20E3 || wsap_vtcore_grapheme_regional_indicator(cps[i]) || + (pictographic && (cps[i] == 0x200D || wsap_vtcore_grapheme_emoji_modifier(cps[i]) || (cps[i] >= 0xE0020 && cps[i] <= 0xE007F)))) emoji = true; } return emoji ? CELL_EMOJI : 0; } -void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags) +void wsap_vtcore_sc_print_glyph(struct wsap_vtcore *t, uint32_t cp, int width, uint16_t flags) { uint32_t base = cp; - if (TERM_EXPECT(term_grapheme_is_handle(cp), 0)) { - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; - int len = term_gstore_expand(t->gstore, cp, cps, TERM_GRAPHEME_MAX_LEN); + if (WSAP_VTCORE_EXPECT(wsap_vtcore_grapheme_is_handle(cp), 0)) { + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int len = wsap_vtcore_gstore_expand(t->gstore, cp, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); base = cps[0]; flags = (flags & ~(CELL_EMOJI | CELL_TEXT)) | cluster_presentation(cps, len); } - if (TERM_EXPECT(width <= 0, 0)) - width = term_text_class(base); + if (WSAP_VTCORE_EXPECT(width <= 0, 0)) + width = wsap_vtcore_text_class(base); if (width == 2 || (flags & CELL_EMOJI)) width = 2; else width = 1; - if (TERM_EXPECT(flags & CELL_TEXT, 0)) + if (WSAP_VTCORE_EXPECT(flags & CELL_TEXT, 0)) width = 1; - if (TERM_EXPECT(width == 1 && !t->pending_wrap && !t->insert_mode && + if (WSAP_VTCORE_EXPECT(width == 1 && !t->pending_wrap && !t->insert_mode && !t->lr_margin_mode && t->cursor_x < t->cols, 1)) { - struct srow *srow = term_row(t, t->cursor_y); + struct srow *srow = wsap_vtcore_row(t, t->cursor_y); int cx = t->cursor_x; int len = srow->len; - if (TERM_EXPECT(srow->kind == ROW_CELLS && cx <= len, 1)) { + if (WSAP_VTCORE_EXPECT(srow->kind == ROW_CELLS && cx <= len, 1)) { struct cell *row = srow->cells; - if (TERM_EXPECT(!((cx < len && (row[cx].flags & CELL_TRAIL)) || + if (WSAP_VTCORE_EXPECT(!((cx < len && (row[cx].flags & CELL_TRAIL)) || (cx + 1 < len && (row[cx + 1].flags & CELL_TRAIL))), 1)) { row[cx] = (struct cell){cp, t->inverse ? t->cur_bg : t->cur_fg, @@ -88,8 +88,8 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags) } } - if (TERM_EXPECT(t->pending_wrap, 0)) { - row_set_wrapped(term_row(t, t->cursor_y), true); + if (WSAP_VTCORE_EXPECT(t->pending_wrap, 0)) { + row_set_wrapped(wsap_vtcore_row(t, t->cursor_y), true); t->cursor_x = t->lr_margin_mode ? t->left_margin : 0; sc_linefeed(t, 1); t->pending_wrap = false; @@ -102,10 +102,10 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags) int cols = t->cols; int right = t->lr_margin_mode ? t->right_margin : cols - 1; - if (TERM_EXPECT(width == 2 && cols > 1 && cx == right && t->autowrap, 0)) { - term_row_fill_gap(srow, cx); + if (WSAP_VTCORE_EXPECT(width == 2 && cols > 1 && cx == right && t->autowrap, 0)) { + wsap_vtcore_row_fill_gap(srow, cx); clear_wide_edges(row, cx, right + 1, srow->len); - row[cx] = (struct cell){ ' ', TERM_COLOR_FG, TERM_COLOR_BG, CELL_WRAP_PAD, 0 }; + row[cx] = (struct cell){ ' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, CELL_WRAP_PAD, 0 }; srow->len = (uint16_t)cols; srow->version++; row_set_wrapped(srow, true); @@ -125,10 +125,10 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags) } else { flags &= ~CELL_WIDE; } - term_row_fill_gap(srow, cx); - if (TERM_EXPECT(t->insert_mode, 0)) { + wsap_vtcore_row_fill_gap(srow, cx); + if (WSAP_VTCORE_EXPECT(t->insert_mode, 0)) { if (cx == srow->len) - row[cx] = (struct cell){ ' ', TERM_COLOR_FG, TERM_COLOR_BG, 0, 0 }; + row[cx] = (struct cell){ ' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, 0, 0 }; int move = right + 1 - cx - span; if (move > 0) memmove(&row[cx + span], &row[cx], (size_t)move * sizeof(struct cell)); @@ -155,7 +155,7 @@ void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags) } } -static inline struct cell *last_written_cell(struct term *t) +static inline struct cell *last_written_cell(struct wsap_vtcore *t) { int right = (t->lr_margin_mode && t->cursor_x <= t->right_margin) ? t->right_margin : t->cols - 1; @@ -163,7 +163,7 @@ static inline struct cell *last_written_cell(struct term *t) if (t->lr_margin_mode && x < t->left_margin) return NULL; - struct srow *srow = term_row(t, t->cursor_y); + struct srow *srow = wsap_vtcore_row(t, t->cursor_y); if (x < 0 || x >= srow->len) return NULL; int p = phys_row(t, t->cursor_y); @@ -173,19 +173,19 @@ static inline struct cell *last_written_cell(struct term *t) return &row[x]; } -bool term_sc_extend_cluster(struct term *t, uint32_t cp, int klass) +bool wsap_vtcore_sc_extend_cluster(struct wsap_vtcore *t, uint32_t cp, int klass) { if (!can_extend_cluster(t->last_char, cp, klass)) return false; struct cell *prev = last_written_cell(t); - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; - int len = prev && prev->c > ' ' ? term_gstore_expand(t->gstore, prev->c, cps, TERM_GRAPHEME_MAX_LEN) : 0; + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int len = prev && prev->c > ' ' ? wsap_vtcore_gstore_expand(t->gstore, prev->c, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN) : 0; if (!len) return joins_cluster(cp, klass); if (!cluster_joins(cps, len, cp, klass)) return false; - if (len >= TERM_GRAPHEME_MAX_LEN) + if (len >= WSAP_VTCORE_GRAPHEME_MAX_LEN) return true; cps[len++] = cp; @@ -196,15 +196,15 @@ bool term_sc_extend_cluster(struct term *t, uint32_t cp, int klass) int span = (cell.flags & CELL_WIDE) && x + 1 < t->cols ? 2 : 1; struct srow *srow = &t->scr.slot[p]; if (srow->len == x + span) { - fill_cells(prev, span, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(prev, span, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); srow->len = (uint16_t)x; } else { fill_cells(prev, span, cell.fg, cell.bg); } t->cursor_x = x; t->pending_wrap = false; - t->last_char = term_gstore_intern(t->gstore, cps, len); - term_sc_print_glyph(t, t->last_char, -1, + t->last_char = wsap_vtcore_gstore_intern(t->gstore, cps, len); + wsap_vtcore_sc_print_glyph(t, t->last_char, -1, cell.flags & ~(CELL_WIDE | CELL_EMOJI | CELL_TEXT)); prev = last_written_cell(t); @@ -221,22 +221,22 @@ bool term_sc_extend_cluster(struct term *t, uint32_t cp, int klass) } /* n blank default rows scroll off the top, after the screen rows. */ -static void push_blank_lines(struct term *t, size_t n) +static void push_blank_lines(struct wsap_vtcore *t, size_t n) { if (screen_has_history(t)) { - term_hist_push_blank(&t->hist, n); + wsap_vtcore_hist_push_blank(&t->hist, n); } else { t->scr.top_id += n; t->scr.top_seg = 0; } } -static void scroll_up_bce(struct term *t, size_t count) +static void scroll_up_bce(struct wsap_vtcore *t, size_t count) { size_t rows = (size_t)t->rows; if (t->alternate || count <= rows) { for (size_t i = count < rows ? count : rows; i > 0; i--) - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); return; } size_t rem = count - rows; @@ -244,7 +244,7 @@ static void scroll_up_bce(struct term *t, size_t count) /* Rows past the history limit would leave again at once. */ size_t keep = screen_has_history(t) ? t->hist.line_limit : 0; for (size_t i = rows + (rem < keep ? rem : keep); i > 0; i--) - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); return; } bool skip = screen_has_history(t) && rem >= t->hist.line_limit; @@ -260,7 +260,7 @@ static void scroll_up_bce(struct term *t, size_t count) push_blank_lines(t, count); } else { for (size_t i = 0; i < rows; i++) - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); push_blank_lines(t, rem); } if (t->prompt_y > 0) @@ -269,12 +269,12 @@ static void scroll_up_bce(struct term *t, size_t count) t->full_gen++; } -void term_sc_linefeed_slow(struct term *t, size_t n) +void wsap_vtcore_sc_linefeed_slow(struct wsap_vtcore *t, size_t n) { if (n == 0) return; t->pending_wrap = false; - term_row(t, t->cursor_y)->version++; + wsap_vtcore_row(t, t->cursor_y)->version++; if (t->cursor_y > t->scroll_bottom) { if (t->cursor_y + (int)n < t->rows) @@ -292,23 +292,23 @@ void term_sc_linefeed_slow(struct term *t, size_t n) size_t scroll = (size_t)(t->cursor_y + (int)n - t->scroll_bottom); t->cursor_y = t->scroll_bottom; - if (TERM_EXPECT(t->scroll_top == 0 && t->scroll_bottom == t->rows - 1, 1)) { - if (TERM_EXPECT(scroll == 1, 1)) - term_screen_scroll_up(t); + if (WSAP_VTCORE_EXPECT(t->scroll_top == 0 && t->scroll_bottom == t->rows - 1, 1)) { + if (WSAP_VTCORE_EXPECT(scroll == 1, 1)) + wsap_vtcore_screen_scroll_up(t); else scroll_up_bce(t, scroll); } else if (t->scroll_top > 0 || t->alternate) { int height = t->scroll_bottom - t->scroll_top + 1; if (height <= 0) height = 1; int count = scroll > (size_t)height ? height : (int)scroll; - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, count, false, false); + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, count, false, false); } else { int height = t->scroll_bottom - t->scroll_top + 1; if (height <= 0) height = 1; if (scroll <= (size_t)height) { - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, (int)scroll, false, true); + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, (int)scroll, false, true); } else { - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, height, false, true); + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, height, false, true); size_t rem = scroll - (size_t)height; if (using_default_colors(t)) { push_blank_lines(t, rem); @@ -319,7 +319,7 @@ void term_sc_linefeed_slow(struct term *t, size_t n) rem = cap; while (rem > 0) { int chunk = rem > (size_t)height ? height : (int)rem; - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, chunk, false, true); + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, chunk, false, true); rem -= (size_t)chunk; } } @@ -327,7 +327,7 @@ void term_sc_linefeed_slow(struct term *t, size_t n) } } -void term_sc_tab(struct term *t, int n) +void wsap_vtcore_sc_tab(struct wsap_vtcore *t, int n) { int dir = n >= 0 ? 1 : -1; int count = n >= 0 ? n : -n; @@ -341,7 +341,7 @@ void term_sc_tab(struct term *t, int n) t->cursor_x = prev > 0 ? prev : 0; } t->pending_wrap = false; - struct srow *cur = term_row(t, t->cursor_y); + struct srow *cur = wsap_vtcore_row(t, t->cursor_y); if (cur) cur->version++; return; } @@ -352,7 +352,7 @@ void term_sc_tab(struct term *t, int n) t->cursor_x = x < 0 ? 0 : x >= t->cols ? t->cols - 1 : x; } t->pending_wrap = false; - struct srow *cur = term_row(t, t->cursor_y); + struct srow *cur = wsap_vtcore_row(t, t->cursor_y); if (cur) cur->version++; } @@ -361,8 +361,8 @@ void term_sc_tab(struct term *t, int n) static inline void sgr_cell_reset(struct cell *cell) { - cell->fg = TERM_COLOR_FG; - cell->bg = TERM_COLOR_BG; + cell->fg = WSAP_VTCORE_COLOR_FG; + cell->bg = WSAP_VTCORE_COLOR_BG; cell->flags &= (uint16_t)~CELL_SGR_FLAGS; } @@ -370,7 +370,7 @@ static inline void sgr_cell_underline(struct cell *cell, int style) { if (style < 0 || style > 5) style = 1; cell->flags = (uint16_t)((cell->flags & ~CELL_ANY_UNDERLINE) | - term_ul_flags[style]); + wsap_vtcore_ul_flags[style]); } static void apply_sgr_to_cell(struct cell *cell, const struct csi *csi, int first) @@ -406,42 +406,42 @@ static void apply_sgr_to_cell(struct cell *cell, const struct csi *csi, int firs i += sgr_extended_color(csi->params, csi->nparams, csi->subparams, i, &color, &ok); if (ok) cell->fg = color; break; - case 39: cell->fg = TERM_COLOR_FG; break; + case 39: cell->fg = WSAP_VTCORE_COLOR_FG; break; case 48: i += sgr_extended_color(csi->params, csi->nparams, csi->subparams, i, &color, &ok); if (ok) cell->bg = color; break; - case 49: cell->bg = TERM_COLOR_BG; break; + case 49: cell->bg = WSAP_VTCORE_COLOR_BG; break; case 53: cell->flags |= CELL_OVERLINE; break; case 55: cell->flags &= (uint16_t)~CELL_OVERLINE; break; case 58: i += sgr_extended_color(csi->params, csi->nparams, csi->subparams, i, &color, &ok); break; default: - if ((unsigned)(v - 30) < 8) cell->fg = term_color_index(v - 30); - else if ((unsigned)(v - 40) < 8) cell->bg = term_color_index(v - 40); - else if ((unsigned)(v - 90) < 8) cell->fg = term_color_index(v - 90 + 8); - else if ((unsigned)(v - 100) < 8) cell->bg = term_color_index(v - 100 + 8); + if ((unsigned)(v - 30) < 8) cell->fg = wsap_vtcore_color_index(v - 30); + else if ((unsigned)(v - 40) < 8) cell->bg = wsap_vtcore_color_index(v - 40); + else if ((unsigned)(v - 90) < 8) cell->fg = wsap_vtcore_color_index(v - 90 + 8); + else if ((unsigned)(v - 100) < 8) cell->bg = wsap_vtcore_color_index(v - 100 + 8); break; } } } -static void deccara_row(struct term *t, int y, int x0, int x1, const struct csi *csi) +static void deccara_row(struct wsap_vtcore *t, int y, int x0, int x1, const struct csi *csi) { int p = phys_row(t, y); struct cell *row = row_cells(t, p); - struct srow *srow = term_row(t, y); + struct srow *srow = wsap_vtcore_row(t, y); int len = srow->len; if (x0 > 0 && x0 < len && (row[x0].flags & CELL_TRAIL)) x0--; if (x1 + 1 < t->cols && x1 < len && (row[x1].flags & CELL_WIDE)) x1++; - term_row_fill_gap(srow, x1 + 1); + wsap_vtcore_row_fill_gap(srow, x1 + 1); for (int x = x0; x <= x1; x++) apply_sgr_to_cell(&row[x], csi, 4); srow->version++; } -void term_sc_deccara(struct term *t, const struct csi *csi) +void wsap_vtcore_sc_deccara(struct wsap_vtcore *t, const struct csi *csi) { int top = csi->params[0] > 0 ? csi->params[0] - 1 : 0; int left = csi->nparams > 1 && csi->params[1] > 0 ? csi->params[1] - 1 : 0; @@ -462,9 +462,9 @@ void term_sc_deccara(struct term *t, const struct csi *csi) } } -void term_sc_decaln(struct term *t) +void wsap_vtcore_sc_decaln(struct wsap_vtcore *t) { - struct cell fill = { .c = 'E', .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }; + struct cell fill = { .c = 'E', .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }; struct cell *row0 = NULL; for (int y = 0; y < t->rows; y++) { int p = phys_row(t, y); @@ -484,45 +484,45 @@ void term_sc_decaln(struct term *t) sc_move(t, 0, 0); } -void term_sc_reset(struct term *t) +void wsap_vtcore_sc_reset(struct wsap_vtcore *t) { t->cursor_x = t->cursor_y = 0; - t->saved = term_saved_cursor_initial(); + t->saved = wsap_vtcore_saved_cursor_initial(); t->prompt_y = -1; t->has_prompt = false; t->graphics = t->pending_wrap = false; t->last_char = 0; t->charsets[0] = t->charsets[1] = 'B'; t->charset_active = 0; - term_tabs_clear(t); - term_tabs_default(t); - term_screen_erase_all(t); + wsap_vtcore_tabs_clear(t); + wsap_vtcore_tabs_default(t); + wsap_vtcore_screen_erase_all(t); t->full_gen++; } -void term_sc_set_cursor_style(struct term *t, int ps) +void wsap_vtcore_sc_set_cursor_style(struct wsap_vtcore *t, int ps) { if (ps == 0) { t->cursor_style = t->default_cursor_style; t->cursor_blink = t->default_cursor_blink; } else if (ps >= 1 && ps <= 6) { - t->cursor_style = ps < 3 ? TERM_CURSOR_BLOCK - : ps < 5 ? TERM_CURSOR_UNDERLINE : TERM_CURSOR_BAR; + t->cursor_style = ps < 3 ? WSAP_VTCORE_CURSOR_BLOCK + : ps < 5 ? WSAP_VTCORE_CURSOR_UNDERLINE : WSAP_VTCORE_CURSOR_BAR; t->cursor_blink = (ps & 1); } - term_row(t, t->cursor_y)->version++; + wsap_vtcore_row(t, t->cursor_y)->version++; } static inline bool next_byte_wraps(const char *buf, size_t len, size_t pos, uint32_t last) { if (pos >= len) return false; uint32_t cp; - if (!term_utf8_decode_one(buf + pos, len - pos, &cp)) return false; - int w = term_text_class(cp); + if (!wsap_vtcore_utf8_decode_one(buf + pos, len - pos, &cp)) return false; + int w = wsap_vtcore_text_class(cp); return w > 0 && !can_extend_cluster(last, cp, w); } -static void flush_orig_rows(struct term *t, struct screen *s, +static void flush_orig_rows(struct wsap_vtcore *t, struct screen *s, int *orig_y, int *orig_rem, int count) { int y = *orig_y; @@ -556,8 +556,8 @@ static void flush_orig_rows(struct term *t, struct screen *s, } } if (lines) { - term_hist_push_ascii_lf(&t->hist, (const char *)base, ends, lines); - if (t->view.anchor.active) term_hist_view_note_push(&t->view, &t->hist, t->cols); + wsap_vtcore_hist_push_ascii_lf(&t->hist, (const char *)base, ends, lines); + if (t->view.anchor.active) wsap_vtcore_hist_view_note_push(&t->view, &t->hist, t->cols); y = closed; continue; } @@ -578,15 +578,15 @@ static void flush_orig_rows(struct term *t, struct screen *s, }; } if (n) { - term_hist_push_ascii_lines(&t->hist, q, n, NULL); - if (t->view.anchor.active) term_hist_view_note_push(&t->view, &t->hist, t->cols); + wsap_vtcore_hist_push_ascii_lines(&t->hist, q, n, NULL); + if (t->view.anchor.active) wsap_vtcore_hist_view_note_push(&t->view, &t->hist, t->cols); y += n; - } else term_screen_push_row(t, screen_get_row(s, y++)); + } else wsap_vtcore_screen_push_row(t, screen_get_row(s, y++)); } } struct stream_emit_ctx { - struct term *term; + struct wsap_vtcore *term; struct screen *screen; struct hist_ascii_line *q; const struct pen_attr *attr; @@ -603,7 +603,7 @@ static void flush_stream_queue(struct stream_emit_ctx *ctx) if (ctx->orig_rem > 0) flush_orig_rows(ctx->term, ctx->screen, &ctx->orig_y, &ctx->orig_rem, ctx->orig_rem); int flush_n = ctx->q_count - ctx->q_cap; - term_hist_push_ascii_lines(&ctx->term->hist, ctx->q, flush_n, ctx->attr); + wsap_vtcore_hist_push_ascii_lines(&ctx->term->hist, ctx->q, flush_n, ctx->attr); if (ctx->q_cap > 0) { if (flush_n >= ctx->q_cap) memcpy(ctx->q, ctx->q + flush_n, (size_t)ctx->q_cap * sizeof(ctx->q[0])); @@ -617,14 +617,14 @@ static void flush_stream_queue(struct stream_emit_ctx *ctx) static inline void emit_stream_bulk_wrapped(struct stream_emit_ctx *ctx, const char *src, int bulk_lines) { - struct term *t = ctx->term; + struct wsap_vtcore *t = ctx->term; struct screen *s = ctx->screen; int cols = ctx->cols; - if (TERM_EXPECT(t->pending_wrap, 0)) { + if (WSAP_VTCORE_EXPECT(t->pending_wrap, 0)) { row_set_wrapped(screen_get_row(s, s->rows - 1), true); t->pending_wrap = false; t->cursor_x = 0; - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); } if (bulk_lines < ctx->q_cap) { const char *p = src; @@ -640,13 +640,13 @@ static inline void emit_stream_bulk_wrapped(struct stream_emit_ctx *ctx, if (ctx->orig_rem > 0) flush_orig_rows(t, s, &ctx->orig_y, &ctx->orig_rem, ctx->orig_rem); if (ctx->q_count > 0) { - term_hist_push_ascii_lines(&t->hist, ctx->q, ctx->q_count, ctx->attr); + wsap_vtcore_hist_push_ascii_lines(&t->hist, ctx->q, ctx->q_count, ctx->attr); ctx->flushed_scrolled += (size_t)ctx->q_count; ctx->q_count = 0; } int hist_rows = bulk_lines - ctx->q_cap; if (hist_rows > 0) { - term_hist_push_ascii(&t->hist, src, hist_rows * cols, ctx->attr, true); + wsap_vtcore_hist_push_ascii(&t->hist, src, hist_rows * cols, ctx->attr, true); ctx->flushed_scrolled += (size_t)hist_rows; } const char *sp = src + (size_t)hist_rows * (size_t)cols; @@ -655,31 +655,31 @@ static inline void emit_stream_bulk_wrapped(struct stream_emit_ctx *ctx, ctx->q_count = ctx->q_cap; } -static inline TERM_ALWAYS_INLINE void emit_stream_row_fast(struct stream_emit_ctx *ctx, +static inline WSAP_VTCORE_ALWAYS_INLINE void emit_stream_row_fast(struct stream_emit_ctx *ctx, const char *row_ptr, int row_len, bool row_wrapped) { - if (TERM_EXPECT(ctx->q_count == 256, 0)) + if (WSAP_VTCORE_EXPECT(ctx->q_count == 256, 0)) flush_stream_queue(ctx); ctx->q[ctx->q_count++] = (struct hist_ascii_line){ row_ptr, (uint16_t)row_len, (uint8_t)row_wrapped }; } -static inline TERM_ALWAYS_INLINE void emit_stream_row(struct stream_emit_ctx *ctx, +static inline WSAP_VTCORE_ALWAYS_INLINE void emit_stream_row(struct stream_emit_ctx *ctx, const char *row_ptr, int row_len, bool row_wrapped) { - if (TERM_EXPECT(ctx->term->pending_wrap, 0)) { + if (WSAP_VTCORE_EXPECT(ctx->term->pending_wrap, 0)) { row_set_wrapped(screen_get_row(ctx->screen, ctx->screen->rows - 1), true); ctx->term->pending_wrap = false; ctx->term->cursor_x = 0; - term_screen_scroll_up(ctx->term); + wsap_vtcore_screen_scroll_up(ctx->term); } emit_stream_row_fast(ctx, row_ptr, row_len, row_wrapped); } -static TERM_NOINLINE size_t stream_ascii_wrapped(struct term *t, const char *buf, size_t len) +static WSAP_VTCORE_NOINLINE size_t stream_ascii_wrapped(struct wsap_vtcore *t, const char *buf, size_t len) { int limit = len > INT32_MAX ? INT32_MAX : (int)len; int run = scan_ascii_run(buf, limit); @@ -700,7 +700,7 @@ static TERM_NOINLINE size_t stream_ascii_wrapped(struct term *t, const char *buf int orig_y = 0, orig_rem = old_rows; flush_orig_rows(t, s, &orig_y, &orig_rem, old_count); int extra = count - (keep - orig_rem); - if (extra) term_hist_push_ascii(&t->hist, buf, extra * cols, NULL, true); + if (extra) wsap_vtcore_hist_push_ascii(&t->hist, buf, extra * cols, NULL, true); s->top = (s->top + scrolls % rows) % rows; const char *src = buf + extra * cols; uint8_t *copy_dst = NULL; @@ -740,10 +740,10 @@ static TERM_NOINLINE size_t stream_ascii_wrapped(struct term *t, const char *buf return (size_t)count * cols; } -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) /* Cut *count at the first line longer than half a history page. Check * whole blocks of 32 lines. Return the line where the check stopped. */ -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static int long_lines_avx512(const uint16_t *ends, int *count) { int j = 0; @@ -753,7 +753,7 @@ static int long_lines_avx512(const uint16_t *ends, int *count) uint32_t bad = _mm512_cmpgt_epu16_mask(_mm512_sub_epi16(end, start), _mm512_set1_epi16(HIST_PAGE_USABLE / 2)); if (bad) { - *count = j + term_ctz32(bad); + *count = j + wsap_vtcore_ctz32(bad); break; } } @@ -761,7 +761,7 @@ static int long_lines_avx512(const uint16_t *ends, int *count) } #endif -static TERM_NOINLINE size_t stream_ascii_lf(struct term *t, const char *buf, size_t len) +static WSAP_VTCORE_NOINLINE size_t stream_ascii_lf(struct wsap_vtcore *t, const char *buf, size_t len) { int limit = len < UINT16_MAX ? (int)len : UINT16_MAX; size_t need = ((size_t)limit + 65) * sizeof(uint16_t); @@ -774,8 +774,8 @@ static TERM_NOINLINE size_t stream_ascii_lf(struct term *t, const char *buf, siz uint16_t *ends = t->ascii_ends.data; int count = scan_ascii_lf(buf, limit, ends); int j = 0; -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) j = long_lines_avx512(ends, &count); #endif for (; j < count; j++) { @@ -809,9 +809,9 @@ static TERM_NOINLINE size_t stream_ascii_lf(struct term *t, const char *buf, siz t->ascii_tail.cap = tail_bytes; } memcpy(tail_data, buf + source_start, tail_bytes); - term_hist_push_ascii_lf(&t->hist, buf, ends, first); + wsap_vtcore_hist_push_ascii_lf(&t->hist, buf, ends, first); if (skip) - term_hist_push_ascii(&t->hist, buf + ends[first], skip, NULL, true); + wsap_vtcore_hist_push_ascii(&t->hist, buf + ends[first], skip, NULL, true); uint32_t last = t->last_char; for (int j = count; j > 0; j--) { if (ends[j] - ends[j - 1] > 1) { @@ -851,8 +851,8 @@ static TERM_NOINLINE size_t stream_ascii_lf(struct term *t, const char *buf, siz /* Bit i of the result is set when buf[i] is not printable ASCII. *nl gets * the line feeds. Both cover 64 bytes. */ -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline uint64_t line_masks_avx512(const char *buf, uint64_t *nl) { __m512i v = _mm512_loadu_si512((const void *)buf); @@ -862,8 +862,8 @@ static inline uint64_t line_masks_avx512(const char *buf, uint64_t *nl) } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline uint64_t line_masks_avx2(const char *buf, uint64_t *nl) { uint64_t lf = 0, controls = 0; @@ -883,16 +883,16 @@ static inline uint64_t line_masks_avx2(const char *buf, uint64_t *nl) static inline uint64_t line_masks(const char *buf, uint64_t *nl) { -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return line_masks_avx2(buf, nl); #endif uint64_t lf = 0, controls = 0; #if defined(__aarch64__) for (int b = 0; b < 64; b += 16) { uint8x16_t v = vld1q_u8((const uint8_t *)buf + b); - lf |= (uint64_t)term_lane_bits(vceqq_u8(v, vdupq_n_u8('\n'))) << b; - controls |= (uint64_t)term_lane_bits(vcgeq_u8( + lf |= (uint64_t)wsap_vtcore_lane_bits(vceqq_u8(v, vdupq_n_u8('\n'))) << b; + controls |= (uint64_t)wsap_vtcore_lane_bits(vcgeq_u8( vsubq_u8(v, vdupq_n_u8(0x20)), vdupq_n_u8(0x7f - 0x20))) << b; } #else @@ -916,7 +916,7 @@ static void stream_queue_finish(struct stream_emit_ctx *ctx) if (loop_scrolled == 0) return; - struct term *t = ctx->term; + struct wsap_vtcore *t = ctx->term; struct screen *s = ctx->screen; int rows = s->rows; @@ -936,7 +936,7 @@ static void stream_queue_finish(struct stream_emit_ctx *ctx) int flush_n = k; if (flush_n > 0) { - term_hist_push_ascii_lines(&t->hist, ctx->q, flush_n, ctx->attr); + wsap_vtcore_hist_push_ascii_lines(&t->hist, ctx->q, flush_n, ctx->attr); } int skip_rows = tail_rows - needed; @@ -944,7 +944,7 @@ static void stream_queue_finish(struct stream_emit_ctx *ctx) struct hist_ascii_line pr = ctx->q[k]; int skip_bytes = skip_rows * cols; if (skip_bytes > (int)pr.len) skip_bytes = (int)pr.len; - term_hist_push_ascii(&t->hist, pr.ptr, skip_bytes, ctx->attr, true); + wsap_vtcore_hist_push_ascii(&t->hist, pr.ptr, skip_bytes, ctx->attr, true); } if (ctx->orig_rem == 0) { @@ -1042,20 +1042,20 @@ static void stream_queue_finish(struct stream_emit_ctx *ctx) /* One body for every level. isa is a constant in each copy below, so each * copy keeps only its own kernels. */ -static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, const char *buf, +static inline WSAP_VTCORE_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct wsap_vtcore *t, const char *buf, size_t len, int isa) { (void)isa; struct screen *s = &t->scr; int rows = s->rows; - if (TERM_EXPECT(rows > 256, 0)) + if (WSAP_VTCORE_EXPECT(rows > 256, 0)) return 0; size_t i = 0; int cols = t->cols; - uint32_t flags = term_flags_pad(t); + uint32_t flags = wsap_vtcore_flags_pad(t); bool autowrap = t->autowrap; - bool lnm = term_lnm(t); + bool lnm = wsap_vtcore_lnm(t); int last_char = (int)t->last_char; struct pen_attr attr = { @@ -1088,8 +1088,8 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co size_t scan = i; while (scan + 64 <= len) { uint64_t nl, controls; -#if defined(TERM_KERNEL_AVX512) - if (isa == TERM_ISA_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (isa == WSAP_VTCORE_ISA_AVX512) controls = line_masks_avx512(buf + scan, &nl); else #endif @@ -1097,7 +1097,7 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co if (controls != nl) break; while (nl) { - size_t end = scan + (size_t)term_ctz64(nl); + size_t end = scan + (size_t)wsap_vtcore_ctz64(nl); if (!autowrap && end - i > (size_t)cols) goto narrow_done; if (end > i) @@ -1116,8 +1116,8 @@ static inline TERM_ALWAYS_INLINE size_t bulk_ascii_lines_body(struct term *t, co narrow_done: if (i >= len) break; -#if defined(TERM_KERNEL_AVX512) - if (isa == TERM_ISA_AVX512 && TERM_EXPECT(!lnm && !t->pending_wrap, 1)) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (isa == WSAP_VTCORE_ISA_AVX512 && WSAP_VTCORE_EXPECT(!lnm && !t->pending_wrap, 1)) { while (i + 64 <= len) { uint64_t nl; uint64_t mask = line_masks_avx512(buf + i, &nl); @@ -1165,7 +1165,7 @@ narrow_done: for (int line = 0; line < 3 && consumed < 64; line++) { uint64_t rest = mask >> consumed; if (!rest) break; - int run = term_ctz64(rest); + int run = wsap_vtcore_ctz64(rest); if (run > cols) break; int pos = consumed + run; int eol = buf[i + pos] == '\n' && lnm ? 1 : @@ -1189,13 +1189,13 @@ narrow_done: int limit = len - i > (size_t)cols ? cols : (int)(len - i); int run = scan_ascii_run(buf + i, limit); int eol = 0; - if (TERM_EXPECT(i + run + 1 < len && buf[i + run] == '\r' && buf[i + run + 1] == '\n', 1)) { + if (WSAP_VTCORE_EXPECT(i + run + 1 < len && buf[i + run] == '\r' && buf[i + run + 1] == '\n', 1)) { eol = 2; } else if (i + run < len && buf[i + run] == '\n' && lnm) { eol = 1; } - if (TERM_EXPECT(eol > 0, 1)) { + if (WSAP_VTCORE_EXPECT(eol > 0, 1)) { if (run > 0) last_char = (unsigned char)buf[i + run - 1]; emit_stream_row(&ctx, buf + i, run, false); @@ -1228,7 +1228,7 @@ narrow_done: emit_stream_row(&ctx, buf + i, run, true); i += (size_t)run; } -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) done: #endif if (i == 0) @@ -1244,30 +1244,30 @@ done: return i; } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 -static TERM_NOINLINE size_t bulk_ascii_lines_avx512(struct term *t, const char *buf, size_t len) +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 +static WSAP_VTCORE_NOINLINE size_t bulk_ascii_lines_avx512(struct wsap_vtcore *t, const char *buf, size_t len) { - return bulk_ascii_lines_body(t, buf, len, TERM_ISA_AVX512); + return bulk_ascii_lines_body(t, buf, len, WSAP_VTCORE_ISA_AVX512); } #endif -static TERM_NOINLINE size_t bulk_ascii_lines_base(struct term *t, const char *buf, size_t len) +static WSAP_VTCORE_NOINLINE size_t bulk_ascii_lines_base(struct wsap_vtcore *t, const char *buf, size_t len) { - return bulk_ascii_lines_body(t, buf, len, TERM_ISA_BASE); + return bulk_ascii_lines_body(t, buf, len, WSAP_VTCORE_ISA_BASE); } -size_t term_sc_bulk_ascii_lines(struct term *t, const char *buf, size_t len) +size_t wsap_vtcore_sc_bulk_ascii_lines(struct wsap_vtcore *t, const char *buf, size_t len) { - if (TERM_EXPECT(t->scr.rows > 256, 0)) return 0; - if (len >= 1024 && t->autowrap && using_default_colors(t) && !term_flags_pad(t)) { + if (WSAP_VTCORE_EXPECT(t->scr.rows > 256, 0)) return 0; + if (len >= 1024 && t->autowrap && using_default_colors(t) && !wsap_vtcore_flags_pad(t)) { size_t done = 0; - if (!term_lnm(t)) done = stream_ascii_wrapped(t, buf, len); + if (!wsap_vtcore_lnm(t)) done = stream_ascii_wrapped(t, buf, len); else if (!t->pending_wrap) done = stream_ascii_lf(t, buf, len); if (done) return done; } -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return bulk_ascii_lines_avx512(t, buf, len); #endif return bulk_ascii_lines_base(t, buf, len); @@ -18,28 +18,28 @@ struct span { }; /* Begin writing a span of cells. Settle cursor row, repair left edge. */ -static inline struct span sc_span_begin(struct term *t, int want); +static inline struct span sc_span_begin(struct wsap_vtcore *t, int want); /* Finish writing a span of cells. Repair right edge, raise len, bump gen. */ -static inline void sc_span_end(struct term *t, struct span *s, int cols, +static inline void sc_span_end(struct wsap_vtcore *t, struct span *s, int cols, uint8_t row_flags, uint32_t last); /* Print ASCII characters through span and SIMD chunking. */ -static inline void sc_print_ascii(struct term *t, const char *s, int n); +static inline void sc_print_ascii(struct wsap_vtcore *t, const char *s, int n); /* Print one glyph (single codepoint or cluster handle). */ -void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags); +void wsap_vtcore_sc_print_glyph(struct wsap_vtcore *t, uint32_t cp, int width, uint16_t flags); -static inline void sc_print_cell(struct term *t, uint32_t cp, int width, uint16_t flags) +static inline void sc_print_cell(struct wsap_vtcore *t, uint32_t cp, int width, uint16_t flags) { - if (TERM_EXPECT(width == 1 && !t->pending_wrap && !t->insert_mode && + if (WSAP_VTCORE_EXPECT(width == 1 && !t->pending_wrap && !t->insert_mode && !t->lr_margin_mode && t->cursor_x < t->cols, 1)) { - struct srow *srow = term_row(t, t->cursor_y); + struct srow *srow = wsap_vtcore_row(t, t->cursor_y); int cx = t->cursor_x; int len = srow->len; - if (TERM_EXPECT(srow->kind == ROW_CELLS && cx <= len, 1)) { + if (WSAP_VTCORE_EXPECT(srow->kind == ROW_CELLS && cx <= len, 1)) { struct cell *row = srow->cells; - if (TERM_EXPECT(!((cx < len && (row[cx].flags & CELL_TRAIL)) || + if (WSAP_VTCORE_EXPECT(!((cx < len && (row[cx].flags & CELL_TRAIL)) || (cx + 1 < len && (row[cx + 1].flags & CELL_TRAIL))), 1)) { row[cx] = (struct cell){cp, t->inverse ? t->cur_bg : t->cur_fg, @@ -60,43 +60,43 @@ static inline void sc_print_cell(struct term *t, uint32_t cp, int width, uint16_ } } } - term_sc_print_glyph(t, cp, width, flags); + wsap_vtcore_sc_print_glyph(t, cp, width, flags); } /* Extend the last printed glyph into a grapheme cluster. */ -bool term_sc_extend_cluster(struct term *t, uint32_t cp, int klass); +bool wsap_vtcore_sc_extend_cluster(struct wsap_vtcore *t, uint32_t cp, int klass); /* Multi-line or region-constrained line feed helper. */ -void term_sc_linefeed_slow(struct term *t, size_t n); +void wsap_vtcore_sc_linefeed_slow(struct wsap_vtcore *t, size_t n); /* Line feed: move down or scroll with BCE. */ -static inline void sc_linefeed(struct term *t, size_t n) +static inline void sc_linefeed(struct wsap_vtcore *t, size_t n) { - if (TERM_EXPECT(n == 1 && t->scroll_top == 0 && + if (WSAP_VTCORE_EXPECT(n == 1 && t->scroll_top == 0 && t->scroll_bottom == t->rows - 1, 1)) { t->pending_wrap = false; - term_row(t, t->cursor_y)->version++; - if (TERM_EXPECT(t->cursor_y == t->rows - 1, 1)) - term_screen_scroll_up(t); + wsap_vtcore_row(t, t->cursor_y)->version++; + if (WSAP_VTCORE_EXPECT(t->cursor_y == t->rows - 1, 1)) + wsap_vtcore_screen_scroll_up(t); else t->cursor_y++; return; } - term_sc_linefeed_slow(t, n); + wsap_vtcore_sc_linefeed_slow(t, n); } /* Carriage return: move cursor to left margin. */ -static inline void sc_cr(struct term *t) +static inline void sc_cr(struct wsap_vtcore *t) { t->pending_wrap = false; if (t->cursor_x != 0) { t->cursor_x = 0; - term_row(t, t->cursor_y)->version++; + wsap_vtcore_row(t, t->cursor_y)->version++; } } /* Move cursor to (x, y), margin-aware. */ -static inline void sc_move(struct term *t, int x, int y) +static inline void sc_move(struct wsap_vtcore *t, int x, int y) { t->pending_wrap = false; if (x < 0) x = 0; @@ -109,16 +109,16 @@ static inline void sc_move(struct term *t, int x, int y) return; t->cursor_x = x; t->cursor_y = y; - term_row(t, old_y)->version++; + wsap_vtcore_row(t, old_y)->version++; if (y != old_y) - term_row(t, y)->version++; + wsap_vtcore_row(t, y)->version++; } /* Advance cursor by n tab stops. */ -void term_sc_tab(struct term *t, int n); +void wsap_vtcore_sc_tab(struct wsap_vtcore *t, int n); /* Erase cells in span [from, to) on physical row y. */ -static inline void sc_erase_span(struct term *t, int y, int from, int to) +static inline void sc_erase_span(struct wsap_vtcore *t, int y, int from, int to) { t->pending_wrap = false; if (to > t->cols) to = t->cols; @@ -128,50 +128,50 @@ static inline void sc_erase_span(struct term *t, int y, int from, int to) } /* Restore saved cursor state and position. */ -static inline void sc_restore_cursor(struct term *t, const struct term_saved_cursor *s) +static inline void sc_restore_cursor(struct wsap_vtcore *t, const struct wsap_vtcore_saved_cursor *s) { - term_cursor_apply(t, s); + wsap_vtcore_cursor_apply(t, s); sc_move(t, s->x, s->y); t->pending_wrap = s->pending_wrap; } /* Change attributes in a rectangular or stream area (DECCARA). */ -void term_sc_deccara(struct term *t, const struct csi *csi); +void wsap_vtcore_sc_deccara(struct wsap_vtcore *t, const struct csi *csi); /* Screen alignment pattern (DECALN). */ -void term_sc_decaln(struct term *t); +void wsap_vtcore_sc_decaln(struct wsap_vtcore *t); /* Reset screen and cursor state for full reset (RIS). */ -void term_sc_reset(struct term *t); +void wsap_vtcore_sc_reset(struct wsap_vtcore *t); /* Set cursor style (DECSCUSR). */ -void term_sc_set_cursor_style(struct term *t, int ps); +void wsap_vtcore_sc_set_cursor_style(struct wsap_vtcore *t, int ps); /* Bulk streaming of ASCII lines with raw rows and skip-ahead. */ -size_t term_sc_bulk_ascii_lines(struct term *t, const char *buf, size_t len); +size_t wsap_vtcore_sc_bulk_ascii_lines(struct wsap_vtcore *t, const char *buf, size_t len); /* Fast CSI parser. */ -int term_try_fast_csi(struct term *t, const char *buf, size_t rem); +int wsap_vtcore_try_fast_csi(struct wsap_vtcore *t, const char *buf, size_t rem); -static inline struct span sc_span_begin(struct term *t, int want) +static inline struct span sc_span_begin(struct wsap_vtcore *t, int want) { (void)want; - if (TERM_EXPECT(t->pending_wrap, 0)) { - row_set_wrapped(term_row(t, t->cursor_y), true); + if (WSAP_VTCORE_EXPECT(t->pending_wrap, 0)) { + row_set_wrapped(wsap_vtcore_row(t, t->cursor_y), true); t->cursor_x = t->lr_margin_mode ? t->left_margin : 0; sc_linefeed(t, 1); t->pending_wrap = false; } - struct srow *row = term_row(t, t->cursor_y); - if (TERM_EXPECT(row->kind != ROW_CELLS, 0)) + struct srow *row = wsap_vtcore_row(t, t->cursor_y); + if (WSAP_VTCORE_EXPECT(row->kind != ROW_CELLS, 0)) srow_settle(row, t->cols); int cx = t->cursor_x; - term_row_fill_gap(row, cx); + wsap_vtcore_row_fill_gap(row, cx); int len = row->len; - if (TERM_EXPECT(cx < len && (row->cells[cx].flags & CELL_TRAIL), 0)) + if (WSAP_VTCORE_EXPECT(cx < len && (row->cells[cx].flags & CELL_TRAIL), 0)) fill_cells(row->cells + cx - 1, 1, row->cells[cx - 1].fg, row->cells[cx - 1].bg); - int right = TERM_EXPECT(t->lr_margin_mode, 0) ? t->right_margin : t->cols - 1; + int right = WSAP_VTCORE_EXPECT(t->lr_margin_mode, 0) ? t->right_margin : t->cols - 1; int avail = right + 1 > cx ? right + 1 - cx : 0; return (struct span){ .row = row, @@ -182,21 +182,21 @@ static inline struct span sc_span_begin(struct term *t, int want) }; } -static inline void sc_span_end(struct term *t, struct span *s, int cols, +static inline void sc_span_end(struct wsap_vtcore *t, struct span *s, int cols, uint8_t row_flags, uint32_t last) { struct srow *row = s->row; int end_x = s->x + cols; - if (TERM_EXPECT(end_x < s->old_len && (row->cells[end_x].flags & CELL_TRAIL), 0)) + if (WSAP_VTCORE_EXPECT(end_x < s->old_len && (row->cells[end_x].flags & CELL_TRAIL), 0)) fill_cells(row->cells + end_x, 1, row->cells[end_x].fg, row->cells[end_x].bg); if (end_x > s->old_len) row->len = (uint16_t)end_x; - if (TERM_EXPECT(row_flags != 0, 0)) + if (WSAP_VTCORE_EXPECT(row_flags != 0, 0)) row->flags |= row_flags; row->version++; t->last_char = last; - if (TERM_EXPECT(cols < s->avail, 1)) { + if (WSAP_VTCORE_EXPECT(cols < s->avail, 1)) { t->cursor_x = end_x; t->pending_wrap = false; } else { @@ -206,7 +206,7 @@ static inline void sc_span_end(struct term *t, struct span *s, int cols, } /* Move the cursor after cols columns written at x, of avail. */ -static inline void sc_text_advance(struct term *t, int x, int cols, int avail) +static inline void sc_text_advance(struct wsap_vtcore *t, int x, int cols, int avail) { if (cols < avail) { t->cursor_x = x + cols; @@ -219,12 +219,12 @@ static inline void sc_text_advance(struct term *t, int x, int cols, int avail) /* Append ASCII at the cursor, with the pen, * when the cursor row takes text. Return the bytes taken. */ -static inline int sc_text_ascii(struct term *t, const char *s, int n, struct text_pen pen) +static inline int sc_text_ascii(struct wsap_vtcore *t, const char *s, int n, struct text_pen pen) { - if (TERM_EXPECT(t->insert_mode || t->lr_margin_mode, 0)) + if (WSAP_VTCORE_EXPECT(t->insert_mode || t->lr_margin_mode, 0)) return 0; if (t->pending_wrap) { - row_set_wrapped(term_row(t, t->cursor_y), true); + row_set_wrapped(wsap_vtcore_row(t, t->cursor_y), true); t->cursor_x = 0; sc_linefeed(t, 1); t->pending_wrap = false; @@ -242,16 +242,16 @@ static inline int sc_text_ascii(struct term *t, const char *s, int n, struct tex return take; } -static inline void sc_print_ascii(struct term *t, const char *s, int n) +static inline void sc_print_ascii(struct wsap_vtcore *t, const char *s, int n) { - struct text_pen pen = term_text_pen(t); + struct text_pen pen = wsap_vtcore_text_pen(t); for (int k; n > 0 && (k = sc_text_ascii(t, s, n, pen)) > 0; s += k, n -= k) {} while (n > 0) { struct span span = sc_span_begin(t, n); int take = n < span.avail ? n : span.avail; - if (TERM_EXPECT(take <= 0, 0)) { + if (WSAP_VTCORE_EXPECT(take <= 0, 0)) { t->pending_wrap = t->autowrap; if (!t->autowrap) break; @@ -262,33 +262,33 @@ static inline void sc_print_ascii(struct term *t, const char *s, int n) } put_ascii_chunk(span.cells, s, take, pen.fg, pen.bg, pen.sl); sc_span_end(t, &span, take, 0, (unsigned char)s[take - 1]); - if (TERM_EXPECT(n <= take, 1)) break; + if (WSAP_VTCORE_EXPECT(n <= take, 1)) break; s += take; n -= take; } } /* Write a short ASCII span without settling an already writable row. */ -static inline bool sc_ascii_fast(struct term *t, const char *s, int n, +static inline bool sc_ascii_fast(struct wsap_vtcore *t, const char *s, int n, struct text_pen pen) { int cx = t->cursor_x; - if (TERM_EXPECT(t->pending_wrap || t->insert_mode || + if (WSAP_VTCORE_EXPECT(t->pending_wrap || t->insert_mode || t->lr_margin_mode || t->inverse || n <= 0 || n > t->cols - cx, 0)) return false; - struct srow *row = term_row(t, t->cursor_y); + struct srow *row = wsap_vtcore_row(t, t->cursor_y); if (row->kind == ROW_TEXT || (row->len == 0 && cx == 0)) { if (sc_text_ascii(t, s, n, pen) == n) return true; if (row->kind == ROW_TEXT) return false; } - if (TERM_EXPECT(row->kind != ROW_CELLS || cx > row->len, 0)) + if (WSAP_VTCORE_EXPECT(row->kind != ROW_CELLS || cx > row->len, 0)) return false; int len = row->len; struct cell *cells = row->cells; - if (TERM_EXPECT((cx < len && (cells[cx].flags & CELL_TRAIL)) || + if (WSAP_VTCORE_EXPECT((cx < len && (cells[cx].flags & CELL_TRAIL)) || (cx + n < len && (cells[cx + n].flags & CELL_TRAIL)), 0)) return false; put_ascii_chunk(cells + cx, s, n, pen.fg, pen.bg, pen.sl); @@ -308,18 +308,18 @@ static inline bool sc_ascii_fast(struct term *t, const char *s, int n, } /* Fast inline check for 1-character write (fg-char fast path). */ -static inline bool sc_put1_fast(struct term *t, char ch, struct text_pen pen) +static inline bool sc_put1_fast(struct wsap_vtcore *t, char ch, struct text_pen pen) { int cx = t->cursor_x; int cols = t->cols; - if (TERM_EXPECT(t->pending_wrap | t->insert_mode | t->lr_margin_mode | t->inverse, 0)) + if (WSAP_VTCORE_EXPECT(t->pending_wrap | t->insert_mode | t->lr_margin_mode | t->inverse, 0)) return false; - if (TERM_EXPECT(cx >= cols, 0)) + if (WSAP_VTCORE_EXPECT(cx >= cols, 0)) return false; - struct srow *row = term_row(t, t->cursor_y); + struct srow *row = wsap_vtcore_row(t, t->cursor_y); if (row->kind == ROW_TEXT) { struct text_row *tr = &row->text; - if (TERM_EXPECT(cx != tr->cells || !tr->cells || cx + 1 == cols, 0)) + if (WSAP_VTCORE_EXPECT(cx != tr->cells || !tr->cells || cx + 1 == cols, 0)) return sc_text_ascii(t, &ch, 1, pen) == 1; /* One character in the middle of a text row. */ tr->text[tr->text_len++] = (uint8_t)ch; @@ -339,10 +339,10 @@ static inline bool sc_put1_fast(struct term *t, char ch, struct text_pen pen) return true; } int len = row->len; - if (TERM_EXPECT(cx > len, 0)) + if (WSAP_VTCORE_EXPECT(cx > len, 0)) return false; struct cell *cells = row->cells; - if (TERM_EXPECT((cx < len && (cells[cx].flags & CELL_TRAIL)) || + if (WSAP_VTCORE_EXPECT((cx < len && (cells[cx].flags & CELL_TRAIL)) || (cx + 1 < len && (cells[cx + 1].flags & CELL_TRAIL)), 0)) return false; @@ -353,7 +353,7 @@ static inline bool sc_put1_fast(struct term *t, char ch, struct text_pen pen) if (cx > len) row->len = (uint16_t)cx; row->version++; - if (TERM_EXPECT(cx < cols, 1)) { + if (WSAP_VTCORE_EXPECT(cx < cols, 1)) { t->cursor_x = cx; } else { t->cursor_x = cols - 1; diff --git a/src/escape.c b/src/escape.c index dceb7a6..d5f61eb 100644 --- a/src/escape.c +++ b/src/escape.c @@ -11,27 +11,27 @@ #include <string.h> #include <stdio.h> -static int sgr_color_param(const struct term *t, char *buf, size_t sz, int base, uint32_t c) +static int sgr_color_param(const struct wsap_vtcore *t, char *buf, size_t sz, int base, uint32_t c) { - if (term_color_is_slot(c) && (c & 0x1FFu) < 256) { + if (wsap_vtcore_color_is_slot(c) && (c & 0x1FFu) < 256) { int i = (int)(c & 0xFFu); /* The underline color has no short form. */ if (i < 16 && base != 50) return snprintf(buf, sz, ";%d", i < 8 ? base + i : base + 60 + i - 8); return snprintf(buf, sz, ";%d:5:%d", base + 8, i); } - if (term_color_is_slot(c)) - c = t->palette.colors[c & TERM_COLOR_SLOT_INDEX]; + if (wsap_vtcore_color_is_slot(c)) + c = t->palette.colors[c & WSAP_VTCORE_COLOR_SLOT_INDEX]; return snprintf(buf, sz, ";%d:2:%d:%d:%d", base + 8, (int)((c >> 16) & 0xff), (int)((c >> 8) & 0xff), (int)(c & 0xff)); } -static int sgr_serialize(const struct term *t, char *buf, size_t sz) +static int sgr_serialize(const struct wsap_vtcore *t, char *buf, size_t sz) { int n = 0; if (!(t->bold || t->faint || t->italic || t->underline || t->strike || - t->overline || t->inverse || t->cur_fg != TERM_COLOR_FG || - t->cur_bg != TERM_COLOR_BG || t->cur_ul)) + t->overline || t->inverse || t->cur_fg != WSAP_VTCORE_COLOR_FG || + t->cur_bg != WSAP_VTCORE_COLOR_BG || t->cur_ul)) return 0; #define SGR_ADD(expr) \ do { \ @@ -47,8 +47,8 @@ static int sgr_serialize(const struct term *t, char *buf, size_t sz) if (t->inverse) SGR_ADD(snprintf(buf + n, sz - (size_t)n, ";7")); if (t->strike) SGR_ADD(snprintf(buf + n, sz - (size_t)n, ";9")); if (t->overline) SGR_ADD(snprintf(buf + n, sz - (size_t)n, ";53")); - if (t->cur_fg != TERM_COLOR_FG) SGR_ADD(sgr_color_param(t, buf + n, sz - (size_t)n, 30, t->cur_fg)); - if (t->cur_bg != TERM_COLOR_BG) SGR_ADD(sgr_color_param(t, buf + n, sz - (size_t)n, 40, t->cur_bg)); + if (t->cur_fg != WSAP_VTCORE_COLOR_FG) SGR_ADD(sgr_color_param(t, buf + n, sz - (size_t)n, 30, t->cur_fg)); + if (t->cur_bg != WSAP_VTCORE_COLOR_BG) SGR_ADD(sgr_color_param(t, buf + n, sz - (size_t)n, 40, t->cur_bg)); if (t->cur_ul) SGR_ADD(sgr_color_param(t, buf + n, sz - (size_t)n, 50, t->cur_ul)); #undef SGR_ADD return n; @@ -105,7 +105,7 @@ static int tcap_cmp(const void *k, const void *e) return strcmp(key, elem->name); } -static const char *term_tcap(const struct term *t, const char *name) +static const char *wsap_vtcore_tcap(const struct wsap_vtcore *t, const char *name) { static const struct tcap_entry caps[] = { { "Co", "16777216" }, { "RGB", "8/8/8" }, @@ -193,7 +193,7 @@ static void resp_put(struct resp_buf *r, const char *s, size_t n) if (r->failed) return; if (r->len + n + 1 > r->cap) { - size_t cap = term_grow_cap(r->cap ? r->cap : 256, r->len + n + 1); + size_t cap = wsap_vtcore_grow_cap(r->cap ? r->cap : 256, r->len + n + 1); char *p = realloc(r->s, cap); if (!p) { r->failed = true; @@ -207,7 +207,7 @@ static void resp_put(struct resp_buf *r, const char *s, size_t n) r->s[r->len] = '\0'; } -static void dcs_xtgettcap(struct term *t, const char *buf, int len) +static void dcs_xtgettcap(struct wsap_vtcore *t, const char *buf, int len) { static const char hex[] = "0123456789abcdef"; struct resp_buf r = {0}; @@ -226,7 +226,7 @@ static void dcs_xtgettcap(struct term *t, const char *buf, int len) if (n < 0) break; name[n] = 0; - const char *cap = term_tcap(t, name); + const char *cap = wsap_vtcore_tcap(t, name); if (first && r.s) { r.s[2] = cap ? '1' : '0'; first = false; } resp_put(&r, buf + i, (size_t)span); if (!cap) break; @@ -266,7 +266,7 @@ static int dcs_param_chr(const char **p, const char *end) return v; } -static void restore_deccir(struct term *t, const char *p, const char *end) +static void restore_deccir(struct wsap_vtcore *t, const char *p, const char *end) { int row = dcs_param_int(&p, end); if (row <= 0 || row > t->rows) return; @@ -300,9 +300,9 @@ static void restore_deccir(struct term *t, const char *p, const char *end) t->graphics = t->charsets[t->charset_active] == '0'; } -static void restore_dectabsr(struct term *t, const char *p, const char *end) +static void restore_dectabsr(struct wsap_vtcore *t, const char *p, const char *end) { - term_tabs_clear(t); + wsap_vtcore_tabs_clear(t); t->custom_tabs = true; int stop = 0, any = 0; for (; p < end; p++) { @@ -319,18 +319,18 @@ static void restore_dectabsr(struct term *t, const char *p, const char *end) if (any && --stop >= 0 && stop < t->tabs_cap) t->tabs[stop] = 1; } -/* Grows the DCS string to hold extra more bytes, up to TERM_OSC_MAX. +/* Grows the DCS string to hold extra more bytes, up to WSAP_VTCORE_OSC_MAX. * False when nothing more fits. */ -static bool dcs_reserve(struct term *t, size_t extra) +static bool dcs_reserve(struct wsap_vtcore *t, size_t extra) { size_t need = (size_t)t->dcs_len + extra; if (need <= t->dcs_cap) return true; - if (t->dcs_cap >= TERM_OSC_MAX) + if (t->dcs_cap >= WSAP_VTCORE_OSC_MAX) return false; - size_t cap = term_grow_cap(t->dcs_cap ? t->dcs_cap : 256, need); - if (cap > TERM_OSC_MAX) - cap = TERM_OSC_MAX; + size_t cap = wsap_vtcore_grow_cap(t->dcs_cap ? t->dcs_cap : 256, need); + if (cap > WSAP_VTCORE_OSC_MAX) + cap = WSAP_VTCORE_OSC_MAX; char *p = realloc(t->dcs_buf, cap); if (!p) return false; @@ -339,9 +339,9 @@ static bool dcs_reserve(struct term *t, size_t extra) return need <= cap; } -static void dcs_dispatch(struct term *t) +static void dcs_dispatch(struct wsap_vtcore *t) { - if (term_str_was_truncated(t)) + if (wsap_vtcore_str_was_truncated(t)) return; const char *buf = t->dcs_buf; int len = t->dcs_len; @@ -370,8 +370,8 @@ static void dcs_dispatch(struct term *t) const char *spec = buf + 2; int slen = len - 2, p; if (slen == 2 && spec[0] == ' ' && spec[1] == 'q') { - int shape = t->cursor_style == TERM_CURSOR_BLOCK ? (t->cursor_blink ? 1 : 2) - : t->cursor_style == TERM_CURSOR_UNDERLINE ? (t->cursor_blink ? 3 : 4) + int shape = t->cursor_style == WSAP_VTCORE_CURSOR_BLOCK ? (t->cursor_blink ? 1 : 2) + : t->cursor_style == WSAP_VTCORE_CURSOR_UNDERLINE ? (t->cursor_blink ? 3 : 4) : (t->cursor_blink ? 5 : 6); p = snprintf(resp, sizeof(resp), "\033P1$r%d q\033\\", shape); } else if (slen == 1 && spec[0] == 'm') { @@ -421,7 +421,7 @@ static void dcs_dispatch(struct term *t) } } -static void soft_reset(struct term *t) +static void soft_reset(struct wsap_vtcore *t) { t->application_cursor = t->application_keypad = t->backarrow_sends_bs = false; t->insert_mode = t->origin_mode = t->reverse_video = t->lnm = false; @@ -439,14 +439,14 @@ static void soft_reset(struct term *t) reset_sgr(t); } -static inline void sgr_set_slot(struct term *t, int code, uint32_t c) +static inline void sgr_set_slot(struct wsap_vtcore *t, int code, uint32_t c) { if (code == 38) t->cur_fg = c; else if (code == 48) t->cur_bg = c; else t->cur_ul = c; } -static inline void handle_sgr(struct term *t, const struct csi *csi) +static inline void handle_sgr(struct wsap_vtcore *t, const struct csi *csi) { if (csi->nparams == 0) { reset_sgr(t); @@ -456,20 +456,20 @@ static inline void handle_sgr(struct term *t, const struct csi *csi) if (csi->nparams == 1 && !csi->subparams) { int p = csi->params[0]; if (p == 0) { reset_sgr(t); return; } - if ((unsigned)(p - 30) < 8) { t->cur_fg = term_color_index(p - 30); return; } - if ((unsigned)(p - 40) < 8) { t->cur_bg = term_color_index(p - 40); return; } - if ((unsigned)(p - 90) < 8) { t->cur_fg = term_color_index(p - 90 + 8); return; } - if ((unsigned)(p - 100) < 8) { t->cur_bg = term_color_index(p - 100 + 8); return; } + if ((unsigned)(p - 30) < 8) { t->cur_fg = wsap_vtcore_color_index(p - 30); return; } + if ((unsigned)(p - 40) < 8) { t->cur_bg = wsap_vtcore_color_index(p - 40); return; } + if ((unsigned)(p - 90) < 8) { t->cur_fg = wsap_vtcore_color_index(p - 90 + 8); return; } + if ((unsigned)(p - 100) < 8) { t->cur_bg = wsap_vtcore_color_index(p - 100 + 8); return; } if (p == 1) { t->bold = true; return; } - if (p == 39) { t->cur_fg = TERM_COLOR_FG; return; } - if (p == 49) { t->cur_bg = TERM_COLOR_BG; return; } + if (p == 39) { t->cur_fg = WSAP_VTCORE_COLOR_FG; return; } + if (p == 49) { t->cur_bg = WSAP_VTCORE_COLOR_BG; return; } } if (!csi->subparams) { if (csi->nparams == 5 && csi->params[1] == 2 && (csi->params[0] == 38 || csi->params[0] == 48)) { sgr_set_slot(t, csi->params[0], - term_rgb(csi->params[2], csi->params[3], csi->params[4])); + wsap_vtcore_rgb(csi->params[2], csi->params[3], csi->params[4])); return; } @@ -477,16 +477,16 @@ static inline void handle_sgr(struct term *t, const struct csi *csi) (csi->params[0] == 38 || csi->params[0] == 48) && csi->params[5] == (csi->params[0] == 38 ? 48 : 38)) { sgr_set_slot(t, csi->params[0], - term_rgb(csi->params[2], csi->params[3], csi->params[4])); + wsap_vtcore_rgb(csi->params[2], csi->params[3], csi->params[4])); sgr_set_slot(t, csi->params[5], - term_rgb(csi->params[7], csi->params[8], csi->params[9])); + wsap_vtcore_rgb(csi->params[7], csi->params[8], csi->params[9])); return; } if (csi->nparams == 3 && csi->params[1] == 5 && (csi->params[0] == 38 || csi->params[0] == 48) && (unsigned)csi->params[2] < 256) { - sgr_set_slot(t, csi->params[0], term_color_index(csi->params[2])); + sgr_set_slot(t, csi->params[0], wsap_vtcore_color_index(csi->params[2])); return; } @@ -494,13 +494,13 @@ static inline void handle_sgr(struct term *t, const struct csi *csi) (csi->params[0] == 38 || csi->params[0] == 48) && csi->params[3] == (csi->params[0] == 38 ? 48 : 38) && (unsigned)csi->params[2] < 256 && (unsigned)csi->params[5] < 256) { - sgr_set_slot(t, csi->params[0], term_color_index(csi->params[2])); - sgr_set_slot(t, csi->params[3], term_color_index(csi->params[5])); + sgr_set_slot(t, csi->params[0], wsap_vtcore_color_index(csi->params[2])); + sgr_set_slot(t, csi->params[3], wsap_vtcore_color_index(csi->params[5])); return; } } - struct term_pen pen = { + struct wsap_vtcore_pen pen = { .fg = t->cur_fg, .bg = t->cur_bg, .ul = t->cur_ul, .underline = t->underline, .bold = t->bold, .faint = t->faint, .italic = t->italic, @@ -519,7 +519,7 @@ static inline void handle_sgr(struct term *t, const struct csi *csi) t->inverse = pen.inverse; } -#define TERM_PRIV_MODE_FIELDS(X) \ +#define WSAP_VTCORE_PRIV_MODE_FIELDS(X) \ X(1, application_cursor) \ X(12, cursor_blink) \ X(25, cursor_visible) \ @@ -528,16 +528,16 @@ static inline void handle_sgr(struct term *t, const struct csi *csi) X(2004, bracketed_paste) \ X(2026, synchronized_output) -#define TERM_ANSI_MODE_FIELDS(X) \ +#define WSAP_VTCORE_ANSI_MODE_FIELDS(X) \ X(4, insert_mode) \ X(20, lnm) -static int mode_get(const struct term *t, int mode, bool priv) +static int mode_get(const struct wsap_vtcore *t, int mode, bool priv) { if (priv) { switch (mode) { #define MODE_FIELD_GET(n, f) case n: return t->f; - TERM_PRIV_MODE_FIELDS(MODE_FIELD_GET) + WSAP_VTCORE_PRIV_MODE_FIELDS(MODE_FIELD_GET) #undef MODE_FIELD_GET case 5: return t->reverse_video; case 6: return t->origin_mode; @@ -552,30 +552,30 @@ static int mode_get(const struct term *t, int mode, bool priv) } switch (mode) { #define MODE_FIELD_GET(n, f) case n: return t->f; - TERM_ANSI_MODE_FIELDS(MODE_FIELD_GET) + WSAP_VTCORE_ANSI_MODE_FIELDS(MODE_FIELD_GET) #undef MODE_FIELD_GET } return -1; } -static int cursor_top(const struct term *t) { return t->origin_mode ? t->scroll_top : 0; } -static int cursor_bottom(const struct term *t) { return t->origin_mode ? t->scroll_bottom : t->rows - 1; } -static int cursor_left(const struct term *t) { return t->origin_mode && t->lr_margin_mode ? t->left_margin : 0; } -static int cursor_right(const struct term *t) { return t->origin_mode && t->lr_margin_mode ? t->right_margin : t->cols - 1; } +static int cursor_top(const struct wsap_vtcore *t) { return t->origin_mode ? t->scroll_top : 0; } +static int cursor_bottom(const struct wsap_vtcore *t) { return t->origin_mode ? t->scroll_bottom : t->rows - 1; } +static int cursor_left(const struct wsap_vtcore *t) { return t->origin_mode && t->lr_margin_mode ? t->left_margin : 0; } +static int cursor_right(const struct wsap_vtcore *t) { return t->origin_mode && t->lr_margin_mode ? t->right_margin : t->cols - 1; } -static void mode_set(struct term *t, int mode, bool enabled, bool priv) +static void mode_set(struct wsap_vtcore *t, int mode, bool enabled, bool priv) { if (!priv) { switch (mode) { #define MODE_FIELD_SET(n, f) case n: t->f = enabled; break; - TERM_ANSI_MODE_FIELDS(MODE_FIELD_SET) + WSAP_VTCORE_ANSI_MODE_FIELDS(MODE_FIELD_SET) #undef MODE_FIELD_SET } return; } switch (mode) { #define MODE_FIELD_SET(n, f) case n: t->f = enabled; return; - TERM_PRIV_MODE_FIELDS(MODE_FIELD_SET) + WSAP_VTCORE_PRIV_MODE_FIELDS(MODE_FIELD_SET) #undef MODE_FIELD_SET default: break; } @@ -591,10 +591,10 @@ static void mode_set(struct term *t, int mode, bool enabled, bool priv) t->autowrap = enabled; t->pending_wrap = false; } else if (mode == 1048) { - if (enabled) t->saved = term_cursor_save(t); + if (enabled) t->saved = wsap_vtcore_cursor_save(t); else sc_restore_cursor(t, &t->saved); } else if (mode == 47 || mode == 1047 || mode == 1049) { - term_screen_set_alternate(t, enabled); + wsap_vtcore_screen_set_alternate(t, enabled); } else if (mode_is_mouse(mode)) { t->mouse_mode = enabled ? mode : 0; } else if (mode == 69) { @@ -608,7 +608,7 @@ static void mode_set(struct term *t, int mode, bool enabled, bool priv) /* Vertical moves stop at a margin when they start inside the scroll * region (xterm, DEC STD 070). */ -static inline void move_v(struct term *t, int n, bool col0) +static inline void move_v(struct wsap_vtcore *t, int n, bool col0) { int top = t->cursor_y >= t->scroll_top ? t->scroll_top : 0; int bottom = t->cursor_y <= t->scroll_bottom ? t->scroll_bottom : t->rows - 1; @@ -616,7 +616,7 @@ static inline void move_v(struct term *t, int n, bool col0) : (n < bottom - t->cursor_y ? t->cursor_y + n : bottom); sc_move(t, col0 ? cursor_left(t) : t->cursor_x, y); } -static inline void move_h(struct term *t, int n, bool margin_aware) +static inline void move_h(struct wsap_vtcore *t, int n, bool margin_aware) { int right = margin_aware ? cursor_right(t) : t->cols - 1; int x = n < 0 ? (t->cursor_x >= -n ? t->cursor_x + n : 0) @@ -624,15 +624,15 @@ static inline void move_h(struct term *t, int n, bool margin_aware) sc_move(t, x, t->cursor_y); } -static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct csi *csi) +static inline WSAP_VTCORE_ALWAYS_INLINE void dispatch_csi(struct wsap_vtcore *t, const struct csi *csi) { - if (TERM_EXPECT(csi->final == 'm', 1)) { - if (TERM_EXPECT(!csi->prefix && !csi->intermediate, 1)) + if (WSAP_VTCORE_EXPECT(csi->final == 'm', 1)) { + if (WSAP_VTCORE_EXPECT(!csi->prefix && !csi->intermediate, 1)) handle_sgr(t, csi); return; } - if (TERM_EXPECT(csi->final == 'H' || csi->final == 'f', 0)) { - if (TERM_EXPECT(!csi->prefix && !csi->intermediate && !csi->subparams, 1)) { + if (WSAP_VTCORE_EXPECT(csi->final == 'H' || csi->final == 'f', 0)) { + if (WSAP_VTCORE_EXPECT(!csi->prefix && !csi->intermediate && !csi->subparams, 1)) { int64_t r = (int64_t)(csi->params[0] > 0 ? csi->params[0] - 1 : 0) + cursor_top(t); if (r > cursor_bottom(t)) r = cursor_bottom(t); int64_t c = (int64_t)(csi->nparams > 1 && csi->params[1] > 0 ? csi->params[1] - 1 : 0) + cursor_left(t); @@ -668,7 +668,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct switch (csi->final) { case 'r': { if (csi->intermediate == '$') { - term_sc_deccara(t, csi); + wsap_vtcore_sc_deccara(t, csi); break; } if (csi->prefix || csi->intermediate) break; @@ -684,7 +684,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct case 'L': case 'M': if (csi->prefix || t->cursor_y < t->scroll_top || t->cursor_y > t->scroll_bottom) break; - term_screen_scroll_region(t, t->cursor_y, t->scroll_bottom, + wsap_vtcore_screen_scroll_region(t, t->cursor_y, t->scroll_bottom, csi_count(csi), csi->final == 'L', false); /* IL and DL move the cursor to the left margin (xterm). */ sc_move(t, t->lr_margin_mode ? t->left_margin : 0, t->cursor_y); @@ -692,7 +692,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct case 'S': case 'T': if (csi->prefix || csi->nparams > 1) break; - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, csi_count(csi), csi->final == 'T', true); break; case 'd': { @@ -702,7 +702,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct break; } case 'b': - term_text_repeat(t, csi_count(csi)); + wsap_vtcore_text_repeat(t, csi_count(csi)); break; case 'A': move_v(t, -csi_count(csi), false); break; case 'B': move_v(t, csi_count(csi), false); break; @@ -727,25 +727,25 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct sc_move(t, t->origin_mode ? left : 0, cursor_top(t)); } } else if (!csi->prefix) { - t->saved = term_cursor_save(t); + t->saved = wsap_vtcore_cursor_save(t); } break; case 'I': case 'Z': - term_sc_tab(t, csi->final == 'I' ? csi_count(csi) : -csi_count(csi)); + wsap_vtcore_sc_tab(t, csi->final == 'I' ? csi_count(csi) : -csi_count(csi)); break; case 'g': if (csi->params[0] == 0) { t->tabs[t->cursor_x] = 0; t->custom_tabs = true; } else if (csi->params[0] == 3) { - term_tabs_clear(t); + wsap_vtcore_tabs_clear(t); } break; case 'W': if (csi->prefix == '?' && csi->params[0] == 5) { - term_tabs_clear(t); - term_tabs_default(t); + wsap_vtcore_tabs_clear(t); + wsap_vtcore_tabs_default(t); } break; case 'n': @@ -759,7 +759,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct } break; case 'J': - term_screen_erase(t, csi->params[0]); + wsap_vtcore_screen_erase(t, csi->params[0]); break; case 'X': { int n = csi_count(csi); @@ -772,13 +772,13 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct t->decsace = (uint8_t)csi->params[0]; break; case 'K': - term_screen_erase_line(t, csi->params[0]); + wsap_vtcore_screen_erase_line(t, csi->params[0]); break; case 'P': - term_screen_delete_chars(t, csi_count(csi)); + wsap_vtcore_screen_delete_chars(t, csi_count(csi)); break; case '@': - term_screen_insert_chars(t, csi_count(csi)); + wsap_vtcore_screen_insert_chars(t, csi_count(csi)); break; case 'c': { if (csi->prefix == '>') @@ -838,7 +838,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct snprintf(resp, sizeof(resp), "\033P>|%s\033\\", t->name); send_response(t, resp); } else if (!csi->prefix && csi->intermediate == ' ') { - term_sc_set_cursor_style(t, csi->nparams > 0 ? csi->params[0] : 0); + wsap_vtcore_sc_set_cursor_style(t, csi->nparams > 0 ? csi->params[0] : 0); } break; } @@ -861,7 +861,7 @@ static inline TERM_ALWAYS_INLINE void dispatch_csi(struct term *t, const struct } /* Formats one trace line and hands it to the host's trace callback. */ -static void esc_tracef(const struct term *t, const char *fmt, ...) +static void esc_tracef(const struct wsap_vtcore *t, const char *fmt, ...) { char line[512]; va_list ap; @@ -875,7 +875,7 @@ static void esc_tracef(const struct term *t, const char *fmt, ...) #define ESC_TRACE(t, ...) \ do { if ((t)->cb.trace) esc_tracef((t), __VA_ARGS__); } while (0) -static void dispatch_esc(struct term *t, unsigned char ch) +static void dispatch_esc(struct wsap_vtcore *t, unsigned char ch) { t->state = ST_GROUND; switch (ch) { @@ -890,9 +890,9 @@ static void dispatch_esc(struct term *t, unsigned char ch) t->custom_tabs = true; break; case 'c': - if (t->alternate) term_screen_set_alternate(t, false); + if (t->alternate) wsap_vtcore_screen_set_alternate(t, false); soft_reset(t); - term_sc_reset(t); + wsap_vtcore_sc_reset(t); break; case '[': ESC_TRACE(t, "ESC[ → ST_CSI"); @@ -939,12 +939,12 @@ static void dispatch_esc(struct term *t, unsigned char ch) break; case 'M': if (t->cursor_y == t->scroll_top) - term_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, 1, true, false); + wsap_vtcore_screen_scroll_region(t, t->scroll_top, t->scroll_bottom, 1, true, false); else sc_move(t, t->cursor_x, t->cursor_y > 0 ? t->cursor_y - 1 : 0); break; case '7': - t->saved = term_cursor_save(t); + t->saved = wsap_vtcore_cursor_save(t); break; case '8': sc_restore_cursor(t, &t->saved); @@ -954,7 +954,7 @@ static void dispatch_esc(struct term *t, unsigned char ch) } } -void term_escape_byte(struct term *t, unsigned char ch) +void wsap_vtcore_escape_byte(struct wsap_vtcore *t, unsigned char ch) { if (ch >= 0x80 && t->state != ST_OSC && t->state != ST_DCS && t->state != ST_IGNORE) { @@ -962,7 +962,7 @@ void term_escape_byte(struct term *t, unsigned char ch) t->osc_len = 0; t->dcs_len = 0; t->state = ST_GROUND; - term_text_ground(t, ch); + wsap_vtcore_text_ground(t, ch); return; } switch (t->state) { @@ -970,7 +970,7 @@ void term_escape_byte(struct term *t, unsigned char ch) ESC_TRACE(t, " ESC+0x%02x('%c')", ch, ch >= 0x20 && ch < 0x7f ? ch : '.'); if (ch < 0x20) { t->state = ST_GROUND; - term_text_ground(t, ch); + wsap_vtcore_text_ground(t, ch); } else { dispatch_esc(t, ch); } @@ -985,7 +985,7 @@ void term_escape_byte(struct term *t, unsigned char ch) } else if (ch < 0x20) { /* Other C0 controls run inside the sequence (ECMA-48 5.5, * xterm). */ - term_text_ground(t, ch); + wsap_vtcore_text_ground(t, ch); } break; case ST_CHARSET: @@ -997,15 +997,15 @@ void term_escape_byte(struct term *t, unsigned char ch) break; case ST_DOCS: if (ch != 'G' && ch != '@' && ch != '/') - term_text_ground(t, '%'); + wsap_vtcore_text_ground(t, '%'); t->state = ST_GROUND; if (ch != 'G' && ch != '@' && ch != '/') - term_text_ground(t, ch); + wsap_vtcore_text_ground(t, ch); break; case ST_DECALN: t->state = ST_GROUND; if (ch == '8') - term_sc_decaln(t); + wsap_vtcore_sc_decaln(t); break; case ST_IGNORE: if (ch == 0x07 || ch == 0x18 || ch == 0x1a) @@ -1018,21 +1018,21 @@ void term_escape_byte(struct term *t, unsigned char ch) t->state = ST_GROUND; else { t->state = ST_ESC; - term_escape_byte(t, ch); + wsap_vtcore_escape_byte(t, ch); } break; case ST_OSC: if (ch == 0x07) { - term_osc_finish(t); + wsap_vtcore_osc_finish(t); t->state = ST_GROUND; } else if (ch == 0x1b) { t->state = ST_STR_ESC; } else if (ch < 0x20) { t->osc_len = 0; t->state = ST_GROUND; - term_text_ground(t, ch); - } else if (term_osc_room(t) || term_osc_grow(t)) { - *term_osc_tail(t) = (char)ch; + wsap_vtcore_text_ground(t, ch); + } else if (wsap_vtcore_osc_room(t) || wsap_vtcore_osc_grow(t)) { + *wsap_vtcore_osc_tail(t) = (char)ch; t->osc_len++; } else { t->str_truncated = true; @@ -1048,7 +1048,7 @@ void term_escape_byte(struct term *t, unsigned char ch) } else if (ch < 0x20) { t->dcs_len = 0; t->state = ST_GROUND; - term_text_ground(t, ch); + wsap_vtcore_text_ground(t, ch); } else if (dcs_reserve(t, 1)) { t->dcs_buf[t->dcs_len++] = (char)ch; } else { @@ -1063,18 +1063,18 @@ void term_escape_byte(struct term *t, unsigned char ch) } else { t->dcs_len = 0; t->state = ST_ESC; - term_escape_byte(t, ch); + wsap_vtcore_escape_byte(t, ch); } break; case ST_STR_ESC: if (ch == '\\') { - term_osc_finish(t); + wsap_vtcore_osc_finish(t); t->state = ST_GROUND; } else { t->osc_len = 0; t->dcs_len = 0; t->state = ST_ESC; - term_escape_byte(t, ch); + wsap_vtcore_escape_byte(t, ch); } break; default: @@ -1082,24 +1082,24 @@ void term_escape_byte(struct term *t, unsigned char ch) } } -size_t term_escape_str(struct term *t, const char *buf, size_t len) +size_t wsap_vtcore_escape_str(struct wsap_vtcore *t, const char *buf, size_t len) { if (t->state == ST_IGNORE) { size_t take = scan_printable_span(buf, len, 0x80); if (take < len) - term_escape_byte(t, (unsigned char)buf[take++]); + wsap_vtcore_escape_byte(t, (unsigned char)buf[take++]); return take; } int is_osc = t->state == ST_OSC; size_t take = scan_printable_span(buf, len, 0x80); if (is_osc) { - size_t room = term_osc_room(t); - if (take > room && term_osc_grow(t)) - room = term_osc_room(t); + size_t room = wsap_vtcore_osc_room(t); + if (take > room && wsap_vtcore_osc_grow(t)) + room = wsap_vtcore_osc_room(t); if (room) { if (take > room) take = room; - memcpy(term_osc_tail(t), buf, take); + memcpy(wsap_vtcore_osc_tail(t), buf, take); t->osc_len += (int)take; } else { t->str_truncated = true; @@ -1117,16 +1117,16 @@ size_t term_escape_str(struct term *t, const char *buf, size_t len) } } if (take < len) - term_escape_byte(t, (unsigned char)buf[take++]); + wsap_vtcore_escape_byte(t, (unsigned char)buf[take++]); return take; } -size_t term_escape_csi(struct term *t, const char *buf, size_t len) +size_t wsap_vtcore_escape_csi(struct wsap_vtcore *t, const char *buf, size_t len) { size_t consumed; enum csi_result result = csi_read(&t->csi_parser, buf, len, &consumed); if (result == CSI_CONTROL) { - term_escape_byte(t, (unsigned char)buf[consumed++]); + wsap_vtcore_escape_byte(t, (unsigned char)buf[consumed++]); } else if (result == CSI_DISPATCH || result == CSI_DISCARD) { if (t->cb.trace) { const struct csi *c = &t->csi_parser.csi; @@ -1148,7 +1148,7 @@ size_t term_escape_csi(struct term *t, const char *buf, size_t len) return consumed; } -void term_escape_begin(struct term *t) +void wsap_vtcore_escape_begin(struct wsap_vtcore *t) { ESC_TRACE(t, "0x1b → ST_ESC"); t->state = ST_ESC; diff --git a/src/escape.h b/src/escape.h index a66d02c..cf58c75 100644 --- a/src/escape.h +++ b/src/escape.h @@ -1,10 +1,10 @@ -#ifndef TERM_ESCAPE_H -#define TERM_ESCAPE_H +#ifndef WSAP_VTCORE_ESCAPE_H +#define WSAP_VTCORE_ESCAPE_H #include "internal.h" -void term_escape_begin(struct term *t); -void term_escape_byte(struct term *t, unsigned char ch); -size_t term_escape_str(struct term *t, const char *buf, size_t len); -size_t term_escape_csi(struct term *t, const char *buf, size_t len); +void wsap_vtcore_escape_begin(struct wsap_vtcore *t); +void wsap_vtcore_escape_byte(struct wsap_vtcore *t, unsigned char ch); +size_t wsap_vtcore_escape_str(struct wsap_vtcore *t, const char *buf, size_t len); +size_t wsap_vtcore_escape_csi(struct wsap_vtcore *t, const char *buf, size_t len); #endif diff --git a/src/fastcsi.c b/src/fastcsi.c index 2e0f004..6f9d926 100644 --- a/src/fastcsi.c +++ b/src/fastcsi.c @@ -9,7 +9,7 @@ #include <stdint.h> #include <string.h> -TERM_ALWAYS_INLINE +WSAP_VTCORE_ALWAYS_INLINE static inline const char *parse_byte_delim(const char *s, const char *end, char delim, uint32_t *val) { if (s >= end) return NULL; @@ -45,7 +45,7 @@ static inline const char *parse_color_sequence(const char *p, const char *end, u if (!s) return NULL; s = parse_byte_delim(s, end, 'm', &b); if (!s) return NULL; - *color = term_rgb((int)r, (int)g, (int)b); + *color = wsap_vtcore_rgb((int)r, (int)g, (int)b); return s; } @@ -54,12 +54,12 @@ static const char *parse_256color(const char *p, const char *end, uint32_t *colo uint32_t v; const char *s = parse_byte_delim(p + 2, end, 'm', &v); if (!s) return NULL; - *color = term_color_index(v); + *color = wsap_vtcore_color_index(v); return s; } -TERM_NOINLINE -int term_try_fast_csi(struct term *t, const char *buf, size_t rem) +WSAP_VTCORE_NOINLINE +int wsap_vtcore_try_fast_csi(struct wsap_vtcore *t, const char *buf, size_t rem) { const char *end = buf + rem; const char *p = buf; @@ -94,11 +94,11 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) } if (p < end && (unsigned char)*p >= 0x20 && (unsigned char)*p < 0x7f) { char ch = *p++; - if (TERM_EXPECT(!flags_ok, 0)) { - flags_pad = term_flags_pad(t); + if (WSAP_VTCORE_EXPECT(!flags_ok, 0)) { + flags_pad = wsap_vtcore_flags_pad(t); flags_ok = true; } - if (TERM_EXPECT(!sc_put1_fast(t, ch, (struct text_pen){ fg, bg, flags_pad }), 0)) { + if (WSAP_VTCORE_EXPECT(!sc_put1_fast(t, ch, (struct text_pen){ fg, bg, flags_pad }), 0)) { t->cur_fg = fg; t->cur_bg = bg; sc_print_ascii(t, &ch, 1); @@ -116,20 +116,20 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) /* Recompute instead of zeroing. The cached flags carry the link * id, and reset_sgr leaves cur_link set, so zeroing here would * drop the hyperlink from every cell written after the reset. */ - flags_pad = term_flags_pad(t); + flags_pad = wsap_vtcore_flags_pad(t); flags_ok = true; p += p[0] == 'm' ? 1 : 2; } else if (p[0] == 'J' || (p[0] >= '0' && p[0] <= '3' && p + 1 < end && p[1] == 'J')) { t->cur_fg = fg; t->cur_bg = bg; - term_screen_erase(t, p[0] == 'J' ? 0 : p[0] - '0'); + wsap_vtcore_screen_erase(t, p[0] == 'J' ? 0 : p[0] - '0'); p += p[0] == 'J' ? 1 : 2; } else if (p[0] == 'K' || (p[0] >= '0' && p[0] <= '2' && p + 1 < end && p[1] == 'K')) { t->cur_fg = fg; t->cur_bg = bg; - term_screen_erase_line(t, p[0] == 'K' ? 0 : p[0] - '0'); + wsap_vtcore_screen_erase_line(t, p[0] == 'K' ? 0 : p[0] - '0'); p += p[0] == 'K' ? 1 : 2; } else if (!t->origin_mode && !t->lr_margin_mode && ((*p >= '0' && *p <= '9') || *p == ';' || @@ -166,7 +166,7 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) case 'E': ny += n; nx = 0; goto vmove; case 'F': ny -= n; nx = 0; goto vmove; vmove: - if (TERM_EXPECT(t->scroll_top != 0 || t->scroll_bottom != rows - 1, 0)) { + if (WSAP_VTCORE_EXPECT(t->scroll_top != 0 || t->scroll_bottom != rows - 1, 0)) { p = esc; goto done; } @@ -200,16 +200,16 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) case 24: t->underline = 0; break; case 27: t->inverse = false; break; case 29: t->strike = false; break; - case 39: fg = TERM_COLOR_FG; break; - case 49: bg = TERM_COLOR_BG; break; + case 39: fg = WSAP_VTCORE_COLOR_FG; break; + case 49: bg = WSAP_VTCORE_COLOR_BG; break; case 53: t->overline = true; break; case 55: t->overline = false; break; case 59: t->cur_ul = 0; break; default: - if ((unsigned)(v - 30) < 8) fg = term_color_index(v - 30); - else if ((unsigned)(v - 40) < 8) bg = term_color_index(v - 40); - else if ((unsigned)(v - 90) < 8) fg = term_color_index(v - 90 + 8); - else if ((unsigned)(v - 100) < 8) bg = term_color_index(v - 100 + 8); + if ((unsigned)(v - 30) < 8) fg = wsap_vtcore_color_index(v - 30); + else if ((unsigned)(v - 40) < 8) bg = wsap_vtcore_color_index(v - 40); + else if ((unsigned)(v - 90) < 8) fg = wsap_vtcore_color_index(v - 90 + 8); + else if ((unsigned)(v - 100) < 8) bg = wsap_vtcore_color_index(v - 100 + 8); break; } flags_ok = false; @@ -236,25 +236,25 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) uint32_t *slot = v == 38 ? &fg : v == 48 ? &bg : &t->cur_ul; if (j + 2 < nparams && pv[j + 1] == 5) { if (pv[j + 2] >= 0 && pv[j + 2] <= 255) - *slot = term_color_index(pv[j + 2]); + *slot = wsap_vtcore_color_index(pv[j + 2]); j += 2; } else if (j + 1 < nparams && pv[j + 1] == 2 && j + 4 < nparams) { - *slot = term_rgb(pv[j + 2], pv[j + 3], pv[j + 4]); + *slot = wsap_vtcore_rgb(pv[j + 2], pv[j + 3], pv[j + 4]); j += 4; } break; } - case 39: fg = TERM_COLOR_FG; break; - case 49: bg = TERM_COLOR_BG; break; + case 39: fg = WSAP_VTCORE_COLOR_FG; break; + case 49: bg = WSAP_VTCORE_COLOR_BG; break; case 53: t->overline = true; break; case 55: t->overline = false; break; case 59: t->cur_ul = 0; break; default: - if ((unsigned)(v - 30) < 8) fg = term_color_index(v - 30); - else if ((unsigned)(v - 40) < 8) bg = term_color_index(v - 40); - else if ((unsigned)(v - 90) < 8) fg = term_color_index(v - 90 + 8); - else if ((unsigned)(v - 100) < 8) bg = term_color_index(v - 100 + 8); + if ((unsigned)(v - 30) < 8) fg = wsap_vtcore_color_index(v - 30); + else if ((unsigned)(v - 40) < 8) bg = wsap_vtcore_color_index(v - 40); + else if ((unsigned)(v - 90) < 8) fg = wsap_vtcore_color_index(v - 90 + 8); + else if ((unsigned)(v - 100) < 8) bg = wsap_vtcore_color_index(v - 100 + 8); break; } } @@ -265,13 +265,13 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) case 'J': t->cur_fg = fg; t->cur_bg = bg; - term_screen_erase(t, pv[0]); + wsap_vtcore_screen_erase(t, pv[0]); p = q + 1; break; case 'K': t->cur_fg = fg; t->cur_bg = bg; - term_screen_erase_line(t, pv[0]); + wsap_vtcore_screen_erase_line(t, pv[0]); p = q + 1; break; case 'X': @@ -284,19 +284,19 @@ int term_try_fast_csi(struct term *t, const char *buf, size_t rem) case 'P': t->cur_fg = fg; t->cur_bg = bg; - term_screen_delete_chars(t, n); + wsap_vtcore_screen_delete_chars(t, n); p = q + 1; break; case '@': t->cur_fg = fg; t->cur_bg = bg; - term_screen_insert_chars(t, n); + wsap_vtcore_screen_insert_chars(t, n); p = q + 1; break; case 's': t->cur_fg = fg; t->cur_bg = bg; - t->saved = term_cursor_save(t); + t->saved = wsap_vtcore_cursor_save(t); p = q + 1; break; case 'u': @@ -325,8 +325,8 @@ tail: int avail = cols - t->cursor_x; int limit = end - p < (ptrdiff_t)avail ? (int)(end - p) : avail; int run = scan_ascii_run(p, limit); - if (TERM_EXPECT(!flags_ok, 0)) { - flags_pad = term_flags_pad(t); + if (WSAP_VTCORE_EXPECT(!flags_ok, 0)) { + flags_pad = wsap_vtcore_flags_pad(t); flags_ok = true; } if (!sc_ascii_fast(t, p, run, (struct text_pen){ fg, bg, flags_pad })) @@ -346,7 +346,7 @@ tail: if (p < end && *p == '\n') { t->cur_fg = fg; t->cur_bg = bg; - if (term_lnm(t)) sc_cr(t); + if (wsap_vtcore_lnm(t)) sc_cr(t); sc_linefeed(t, 1); p++; goto tail; diff --git a/src/gstore.c b/src/gstore.c index 813ea7d..a94af32 100644 --- a/src/gstore.c +++ b/src/gstore.c @@ -29,7 +29,7 @@ struct gslot { }; struct gstore { - struct term *term; + struct wsap_vtcore *term; uint32_t *arena; size_t arena_len; size_t arena_cap; @@ -68,15 +68,15 @@ static inline bool gentry_matches(const struct gstore *g, const struct gentry *e return !memcmp(&g->arena[e->offset], &cps[2], (size_t)(n - 2) * sizeof(*cps)); } -int term_gstore_expand(const struct gstore *g, uint32_t handle, uint32_t *cps, int cap) +int wsap_vtcore_gstore_expand(const struct gstore *g, uint32_t handle, uint32_t *cps, int cap) { if (cap <= 0) return 0; - if (!g || !term_grapheme_is_handle(handle)) { + if (!g || !wsap_vtcore_grapheme_is_handle(handle)) { cps[0] = handle; return 1; } - uint32_t idx = handle - TERM_GRAPHEME_HANDLE_BASE; + uint32_t idx = handle - WSAP_VTCORE_GRAPHEME_HANDLE_BASE; if (idx >= g->entries_count || !g->entries[idx].allocated) { cps[0] = 0xFFFD; return 1; @@ -124,8 +124,8 @@ static bool grow_slots(struct gstore *g) struct gentry *e = &g->entries[i]; if (!e->allocated) continue; - uint32_t cps_buf[TERM_GRAPHEME_MAX_LEN]; - int n = term_gstore_expand(g, TERM_GRAPHEME_HANDLE_BASE + i, cps_buf, TERM_GRAPHEME_MAX_LEN); + uint32_t cps_buf[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int n = wsap_vtcore_gstore_expand(g, WSAP_VTCORE_GRAPHEME_HANDLE_BASE + i, cps_buf, WSAP_VTCORE_GRAPHEME_MAX_LEN); uint64_t h = hash_cps(cps_buf, n); uint32_t h32 = (uint32_t)h ? (uint32_t)h : 1; gstore_insert_slot(g, h32, i); @@ -147,14 +147,14 @@ static uint32_t gstore_find(const struct gstore *g, const uint32_t *cps, int n, uint32_t e_idx = slot->entry_idx - 1; const struct gentry *e = &g->entries[e_idx]; if (e->allocated && gentry_matches(g, e, cps, n)) - return TERM_GRAPHEME_HANDLE_BASE + e_idx; + return WSAP_VTCORE_GRAPHEME_HANDLE_BASE + e_idx; } idx = (idx + 1) & mask; } return 0; } -struct gstore *term_gstore_new(struct term *t) +struct gstore *wsap_vtcore_gstore_new(struct wsap_vtcore *t) { struct gstore *g = calloc(1, sizeof(*g)); if (!g) @@ -164,7 +164,7 @@ struct gstore *term_gstore_new(struct term *t) return g; } -void term_gstore_free(struct gstore *g) +void wsap_vtcore_gstore_free(struct gstore *g) { if (!g) return; @@ -174,28 +174,28 @@ void term_gstore_free(struct gstore *g) free(g); } -uint32_t term_gstore_count(const struct gstore *g) +uint32_t wsap_vtcore_gstore_count(const struct gstore *g) { return g ? g->live_count : 0; } -void term_gstore_pin(struct gstore *g) +void wsap_vtcore_gstore_pin(struct gstore *g) { if (g) g->pin_depth++; } -void term_gstore_unpin(struct gstore *g) +void wsap_vtcore_gstore_unpin(struct gstore *g) { if (g && g->pin_depth > 0) g->pin_depth--; } -void term_gstore_mark(struct gstore *g, uint32_t handle) +void wsap_vtcore_gstore_mark(struct gstore *g, uint32_t handle) { - if (!g || !term_grapheme_is_handle(handle)) + if (!g || !wsap_vtcore_grapheme_is_handle(handle)) return; - uint32_t idx = handle - TERM_GRAPHEME_HANDLE_BASE; + uint32_t idx = handle - WSAP_VTCORE_GRAPHEME_HANDLE_BASE; if (idx < g->entries_count && g->entries[idx].allocated) g->entries[idx].mark = true; } @@ -204,19 +204,19 @@ static void sweep_mark_row(struct gstore *g, const struct cell *cells, int len) { for (int x = 0; x < len; x++) { uint32_t c = cells[x].c; - if (term_grapheme_is_handle(c)) - term_gstore_mark(g, c); + if (wsap_vtcore_grapheme_is_handle(c)) + wsap_vtcore_gstore_mark(g, c); } } -void term_gstore_sweep(struct gstore *g, struct term *t) +void wsap_vtcore_gstore_sweep(struct gstore *g, struct wsap_vtcore *t) { if (!g) return; if (t) { - if (term_grapheme_is_handle(t->last_char)) - term_gstore_mark(g, t->last_char); + if (wsap_vtcore_grapheme_is_handle(t->last_char)) + wsap_vtcore_gstore_mark(g, t->last_char); struct screen *s = &t->scr; for (int y = 0; y < s->rows; y++) { @@ -266,8 +266,8 @@ void term_gstore_sweep(struct gstore *g, struct term *t) live++; e->mark = false; if (g->slots) { - uint32_t cps_buf[TERM_GRAPHEME_MAX_LEN]; - int n = term_gstore_expand(g, TERM_GRAPHEME_HANDLE_BASE + i, cps_buf, TERM_GRAPHEME_MAX_LEN); + uint32_t cps_buf[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int n = wsap_vtcore_gstore_expand(g, WSAP_VTCORE_GRAPHEME_HANDLE_BASE + i, cps_buf, WSAP_VTCORE_GRAPHEME_MAX_LEN); uint64_t h = hash_cps(cps_buf, n); uint32_t h32 = (uint32_t)h ? (uint32_t)h : 1; gstore_insert_slot(g, h32, i); @@ -294,14 +294,14 @@ void term_gstore_sweep(struct gstore *g, struct term *t) g->sweep_threshold = 1024; } -uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n) +uint32_t wsap_vtcore_gstore_intern(struct gstore *g, const uint32_t *cps, int n) { if (!g || n <= 0) return 0; if (n == 1) return cps[0]; - if (n > TERM_GRAPHEME_MAX_LEN) - n = TERM_GRAPHEME_MAX_LEN; + if (n > WSAP_VTCORE_GRAPHEME_MAX_LEN) + n = WSAP_VTCORE_GRAPHEME_MAX_LEN; uint64_t h = hash_cps(cps, n); uint32_t h32 = (uint32_t)h ? (uint32_t)h : 1; @@ -313,7 +313,7 @@ uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n) if (g->term && g->pin_depth == 0 && (g->live_count >= g->sweep_threshold || g->live_count >= GSTORE_MAX_ENTRIES)) { - term_gstore_sweep(g, g->term); + wsap_vtcore_gstore_sweep(g, g->term); existing = gstore_find(g, cps, n, h32); if (existing) return existing; @@ -355,7 +355,7 @@ uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n) if (n > 2) { size_t extra = (size_t)(n - 2); if (g->arena_len + extra > g->arena_cap) { - size_t new_cap = term_grow_cap(g->arena_cap ? g->arena_cap * 2 : 512, + size_t new_cap = wsap_vtcore_grow_cap(g->arena_cap ? g->arena_cap * 2 : 512, g->arena_len + extra); uint32_t *next = realloc(g->arena, new_cap * sizeof(*next)); if (!next) { @@ -375,5 +375,5 @@ uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n) gstore_insert_slot(g, h32, entry_idx); g->live_count++; - return TERM_GRAPHEME_HANDLE_BASE + entry_idx; + return WSAP_VTCORE_GRAPHEME_HANDLE_BASE + entry_idx; } diff --git a/src/gstore.h b/src/gstore.h index 0cedd30..e4610ce 100644 --- a/src/gstore.h +++ b/src/gstore.h @@ -6,31 +6,31 @@ #include <stdint.h> struct gstore; -struct term; +struct wsap_vtcore; /* Create a grapheme store for a terminal. */ -struct gstore *term_gstore_new(struct term *t); +struct gstore *wsap_vtcore_gstore_new(struct wsap_vtcore *t); /* Free the grapheme store and its memory. */ -void term_gstore_free(struct gstore *g); +void wsap_vtcore_gstore_free(struct gstore *g); /* Store a cluster of code points. Return its handle. */ -uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n); +uint32_t wsap_vtcore_gstore_intern(struct gstore *g, const uint32_t *cps, int n); /* Expand a handle to its code points. Return the count. */ -int term_gstore_expand(const struct gstore *g, uint32_t handle, uint32_t *cps, int cap); +int wsap_vtcore_gstore_expand(const struct gstore *g, uint32_t handle, uint32_t *cps, int cap); /* Mark reachable clusters and free unused ones. */ -void term_gstore_sweep(struct gstore *g, struct term *t); +void wsap_vtcore_gstore_sweep(struct gstore *g, struct wsap_vtcore *t); /* Mark one cluster handle as reachable. */ -void term_gstore_mark(struct gstore *g, uint32_t handle); +void wsap_vtcore_gstore_mark(struct gstore *g, uint32_t handle); /* Return the count of active clusters in the store. */ -uint32_t term_gstore_count(const struct gstore *g); +uint32_t wsap_vtcore_gstore_count(const struct gstore *g); /* Suppress automatic GC sweeps while temporary cell buffers hold handles. */ -void term_gstore_pin(struct gstore *g); -void term_gstore_unpin(struct gstore *g); +void wsap_vtcore_gstore_pin(struct gstore *g); +void wsap_vtcore_gstore_unpin(struct gstore *g); #endif @@ -42,7 +42,7 @@ #define ROWS_UNKNOWN 255 /* Bytes one cell can need, except a cluster. */ #define CELL_BYTES 5 -#define CLUSTER_BYTES (2 + TERM_GRAPHEME_MAX_LEN * 4) +#define CLUSTER_BYTES (2 + WSAP_VTCORE_GRAPHEME_MAX_LEN * 4) /* ---- Parts and pages ---- */ @@ -62,24 +62,24 @@ static inline struct hline *open_part(const struct hist *h) } /* Grow the ring so n more parts fit. The caller checks the fast path first. */ -static TERM_NOINLINE bool ring_grow(struct hist *h, uint64_t n) +static WSAP_VTCORE_NOINLINE bool ring_grow(struct hist *h, uint64_t n) { uint64_t cap = h->ring ? (uint64_t)h->ring_mask + 1 : 65536; if (cap < 65536) cap = 65536; - cap = term_grow_cap64(cap, h->head - h->tail + n); - struct hline *ring = term_aligned_alloc(64, (size_t)cap * sizeof(*ring)); + cap = wsap_vtcore_grow_cap64(cap, h->head - h->tail + n); + struct hline *ring = wsap_vtcore_aligned_alloc(64, (size_t)cap * sizeof(*ring)); if (!ring) return false; struct hist_block *blocks = calloc((size_t)cap / 16, sizeof(*blocks)); if (!blocks) { - term_aligned_free(ring); + wsap_vtcore_aligned_free(ring); return false; } uint32_t *exact = h->exact_rows ? calloc((size_t)cap, sizeof(*exact)) : NULL; if (h->exact_rows && !exact) { free(blocks); - term_aligned_free(ring); + wsap_vtcore_aligned_free(ring); return false; } for (uint64_t s = h->tail; s < h->head; s++) { @@ -89,7 +89,7 @@ static TERM_NOINLINE bool ring_grow(struct hist *h, uint64_t n) } free(h->exact_rows); h->exact_rows = exact; - term_aligned_free(h->ring); + wsap_vtcore_aligned_free(h->ring); free(h->blocks); h->blocks = blocks; h->ring = ring; @@ -101,7 +101,7 @@ static TERM_NOINLINE bool ring_grow(struct hist *h, uint64_t n) * keep it inline and leave only the rehash to a call. */ static inline bool ring_fit(struct hist *h, uint64_t n) { - if (TERM_EXPECT(h->ring && h->head - h->tail + n <= (uint64_t)h->ring_mask + 1, 1)) + if (WSAP_VTCORE_EXPECT(h->ring && h->head - h->tail + n <= (uint64_t)h->ring_mask + 1, 1)) return true; return ring_grow(h, n); } @@ -182,7 +182,7 @@ static inline bool line_valid(const struct hist *h, uint64_t id) return id >= h->base_id && id < h->base_id + h->lines; } -static TERM_ALWAYS_INLINE inline void page_drop_ref(struct hist *h, uint32_t pg) +static WSAP_VTCORE_ALWAYS_INLINE inline void page_drop_ref(struct hist *h, uint32_t pg) { if (--h->page_parts[pg] == 0) { if (pg == h->cur_page) @@ -196,7 +196,7 @@ static TERM_ALWAYS_INLINE inline void page_drop_ref(struct hist *h, uint32_t pg) static void rows_uncount(struct hist *h, uint64_t id) { if (id < h->rows_id) - h->counted_rows -= term_hist_line_estimate(h, id, h->wrap_cols); + h->counted_rows -= wsap_vtcore_hist_line_estimate(h, id, h->wrap_cols); } static void line_gone(struct hist *h) @@ -244,7 +244,7 @@ static bool evict_part(struct hist *h) return true; } -static TERM_NOINLINE void evict_line_parts(struct hist *h) +static WSAP_VTCORE_NOINLINE void evict_line_parts(struct hist *h) { uint64_t end = line_end(h, h->tail); if (part(h, end - 1)->flags & HLINE_OPEN) @@ -272,8 +272,8 @@ static inline void page_drop_n(struct hist *h, uint32_t pg, uint32_t n) } } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline bool same_page_narrow_rows_avx512(const struct hline *p, uint32_t page) { const __m512i pg = _mm512_set1_epi32((int)(page << 16)); @@ -289,8 +289,8 @@ static inline bool same_page_narrow_rows_avx512(const struct hline *p, uint32_t } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline bool same_page_narrow_rows_avx2(const struct hline *p, uint32_t page) { const __m256i pg = _mm256_set1_epi32((int)(page << 16)); @@ -309,12 +309,12 @@ static inline bool same_page_narrow_rows_avx2(const struct hline *p, uint32_t pa /* Check 16 narrow rows. Each descriptor has four words. */ static inline bool same_page_narrow_rows(const struct hline *p, uint32_t page) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return same_page_narrow_rows_avx512(p, page); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return same_page_narrow_rows_avx2(p, page); #endif #if defined(__aarch64__) @@ -336,8 +336,8 @@ static inline bool same_page_narrow_rows(const struct hline *p, uint32_t page) #endif } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline bool same_page_rows_64(const struct hline *p, uint32_t page, uint32_t *text_count, uint32_t *row_count) { @@ -352,7 +352,7 @@ static inline bool same_page_rows_64(const struct hline *p, uint32_t page, for (int i = 0; i < 64; i += 4) { __m512i v = _mm512_loadu_si512((const void *)(p + i)); __mmask16 empty = _mm512_cmpeq_epi32_mask(v, no_text) & 0x1111; - blanks += term_popcount32(empty); + blanks += wsap_vtcore_popcount32(empty); tag_fail |= (_mm512_test_epi32_mask(v, open) | _mm512_cmpeq_epi32_mask(_mm512_and_si512(v, unknown), unknown)) & 0x8888; pg_fail |= (uint16_t)(~(_mm512_cmpeq_epi32_mask(_mm512_and_si512(v, mask), pg) | empty) & 0x1111); @@ -400,8 +400,8 @@ static uint64_t evict_simple_run(struct hist *h, uint64_t k) continue; } } -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512() && (tail & 63) == 0 && n + 64 <= k && tail + 64 <= head && +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512() && (tail & 63) == 0 && n + 64 <= k && tail + 64 <= head && ((tail & rmask) + 64 <= rmask + 1)) { const struct hline *f = &ring[tail & rmask]; @@ -463,7 +463,7 @@ static uint64_t evict_simple_run(struct hist *h, uint64_t k) uint32_t or_all = t0 | t1 | t2 | t3 | t4 | t5 | t6 | t7 | t8 | t9 | t10 | t11 | t12 | t13 | t14 | t15; - if (TERM_EXPECT((or_all & 0x0030ffff) == 0 && + if (WSAP_VTCORE_EXPECT((or_all & 0x0030ffff) == 0 && (t0 >> 24) != 255 && (t1 >> 24) != 255 && (t2 >> 24) != 255 && (t3 >> 24) != 255 && (t4 >> 24) != 255 && (t5 >> 24) != 255 && (t6 >> 24) != 255 && (t7 >> 24) != 255 && (t8 >> 24) != 255 && (t9 >> 24) != 255 && (t10 >> 24) != 255 && (t11 >> 24) != 255 && @@ -568,16 +568,16 @@ static inline void evict_for(struct hist *h, uint64_t n) } /* Drop the oldest line with all its parts. It is never the open line. */ -static inline TERM_ALWAYS_INLINE void evict_line(struct hist *h) +static inline WSAP_VTCORE_ALWAYS_INLINE void evict_line(struct hist *h) { if (h->tail == h->head) return; const struct hline *f = part(h, h->tail); - if (TERM_EXPECT(!(f->flags & HLINE_OPEN) && + if (WSAP_VTCORE_EXPECT(!(f->flags & HLINE_OPEN) && (h->tail + 1 == h->head || !(part(h, h->tail + 1)->flags & HLINE_CONT)), 1)) { if (h->base_id < h->rows_id) h->counted_rows -= f->wrap_rows != ROWS_UNKNOWN - ? f->wrap_rows : term_hist_line_estimate(h, h->base_id, h->wrap_cols); + ? f->wrap_rows : wsap_vtcore_hist_line_estimate(h, h->base_id, h->wrap_cols); if (f->off != NO_TEXT) page_drop_ref(h, f->off >> 16); h->tail++; @@ -587,7 +587,7 @@ static inline TERM_ALWAYS_INLINE void evict_line(struct hist *h) evict_line_parts(h); } -static TERM_NOINLINE int page_next(struct hist *h) +static WSAP_VTCORE_NOINLINE int page_next(struct hist *h) { for (;;) { if (h->nfree) { @@ -597,7 +597,7 @@ static TERM_NOINLINE int page_next(struct hist *h) return (int)pg; } if (h->npages < h->max_pages) { - uint8_t *page = term_aligned_alloc(64, HIST_PAGE_SIZE); + uint8_t *page = wsap_vtcore_aligned_alloc(64, HIST_PAGE_SIZE); if (!page) return -1; uint32_t pg = h->npages++; @@ -620,7 +620,7 @@ static inline int page_for(struct hist *h, size_t need) if (need > HIST_PAGE_USABLE) return -1; uint32_t pg = h->cur_page; - if (TERM_EXPECT(pg < h->npages && h->page_used[pg] + need <= HIST_PAGE_USABLE, 1)) + if (WSAP_VTCORE_EXPECT(pg < h->npages && h->page_used[pg] + need <= HIST_PAGE_USABLE, 1)) return (int)pg; return page_next(h); } @@ -629,12 +629,12 @@ static inline int page_for(struct hist *h, size_t need) static inline int put_varint(uint8_t *p, uint32_t v) { - if (TERM_EXPECT(v < 0x80, 1)) { + if (WSAP_VTCORE_EXPECT(v < 0x80, 1)) { p[0] = (uint8_t)v; return 1; } p[0] = (uint8_t)(v | 0x80); - if (TERM_EXPECT(v < 0x4000, 1)) { + if (WSAP_VTCORE_EXPECT(v < 0x4000, 1)) { p[1] = (uint8_t)(v >> 7); return 2; } @@ -656,12 +656,12 @@ static inline int put_varint(uint8_t *p, uint32_t v) static inline int get_varint(const uint8_t *p, uint32_t *v) { uint8_t b0 = p[0]; - if (TERM_EXPECT((b0 & 0x80) == 0, 1)) { + if (WSAP_VTCORE_EXPECT((b0 & 0x80) == 0, 1)) { *v = b0; return 1; } uint8_t b1 = p[1]; - if (TERM_EXPECT((b1 & 0x80) == 0, 1)) { + if (WSAP_VTCORE_EXPECT((b1 & 0x80) == 0, 1)) { *v = (uint32_t)(b0 & 0x7f) | ((uint32_t)b1 << 7); return 2; } @@ -691,7 +691,7 @@ static inline uint8_t *emit_run(uint8_t *p, const struct pen_attr *base, const s uint32_t count) { /* Most runs change only colors and cover fewer than 128 cells. */ - if (TERM_EXPECT(count < 0x80 && pen_sl(pen) == pen_sl(base), 1)) { + if (WSAP_VTCORE_EXPECT(count < 0x80 && pen_sl(pen) == pen_sl(base), 1)) { uint32_t dfg = pen->fg != base->fg, dbg = pen->bg != base->bg; p[0] = (uint8_t)(dfg | (dbg << 1)); p[1] = (uint8_t)count; @@ -727,9 +727,9 @@ static inline const uint8_t *read_run(const uint8_t *p, struct pen_attr *pen, ui static bool runs_reserve(struct hist_runs *r, size_t extra) { - if (TERM_EXPECT(r->len + extra <= r->cap, 1)) + if (WSAP_VTCORE_EXPECT(r->len + extra <= r->cap, 1)) return true; - size_t cap = term_grow_cap(r->cap ? r->cap : 256, (size_t)r->len + extra); + size_t cap = wsap_vtcore_grow_cap(r->cap ? r->cap : 256, (size_t)r->len + extra); uint8_t *data = realloc(r->data, cap); if (!data) return false; @@ -746,7 +746,7 @@ static inline void runs_reset(struct hist_runs *r) r->count = 0; } -void term_hist_runs_emit_slow(struct hist_runs *r) +void wsap_vtcore_hist_runs_emit_slow(struct hist_runs *r) { r->len = (uint32_t)(emit_run(r->data + r->len, &r->base, &r->pen, r->count) - r->data); } @@ -812,11 +812,11 @@ struct enc { uint16_t wide; }; -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) /* The prefix of cells where (lane & keep) - target <= span holds in every * lane. Their code points go to dst as bytes. Eight cells per step; the * last step uses masked loads. */ -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline int narrow_prefix_avx512(const struct cell *cells, int len, uint8_t *dst, __m512i keep, __m512i target, __m512i span) { @@ -834,7 +834,7 @@ static inline int narrow_prefix_avx512(const struct cell *cells, int len, uint8_ if (ok0 != m0 || ok1 != m1) { /* Keep the cells before the first failing one. */ uint32_t bad = (uint32_t)(~ok0 & m0) | ((uint32_t)(~ok1 & m1) << 16); - int good = term_ctz32(bad) / 4; + int good = wsap_vtcore_ctz32(bad) / 4; _mm_mask_storeu_epi8(dst + k, (__mmask16)((1u << good) - 1), _mm512_cvtepi32_epi8(cp)); return k + good; } @@ -846,7 +846,7 @@ static inline int narrow_prefix_avx512(const struct cell *cells, int len, uint8_ return len; } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline int narrow_any_pen_prefix_avx512(const struct cell *cells, int len, uint8_t *dst) { const __m512i keep = _mm512_setr_epi32(-1, 0, 0, SHAPE_FLAGS, -1, 0, 0, SHAPE_FLAGS, @@ -856,7 +856,7 @@ static inline int narrow_any_pen_prefix_avx512(const struct cell *cells, int len return narrow_prefix_avx512(cells, len, dst, keep, target, span); } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline int narrow_uniform_prefix_avx512(const struct cell *cells, int len, uint8_t *dst) { uint32_t sl = (uint32_t)(cells[0].flags & STYLE_FLAGS) | ((uint32_t)cells[0].pad << 16); @@ -875,8 +875,8 @@ static inline int narrow_uniform_prefix_avx512(const struct cell *cells, int len * to dst. */ static inline int narrow_any_pen_prefix(const struct cell *cells, int len, uint8_t *dst) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return narrow_any_pen_prefix_avx512(cells, len, dst); #endif int k = 0; @@ -890,7 +890,7 @@ static inline int narrow_any_pen_prefix(const struct cell *cells, int len, uint8 /* Add the pens of n cells to r, one run per change. Cells carry no * underline color, so no pen here has one. */ -static TERM_NOINLINE uint32_t runs_scan(struct hist_runs *r, const struct cell *cells, int n) +static WSAP_VTCORE_NOINLINE uint32_t runs_scan(struct hist_runs *r, const struct cell *cells, int n) { uint32_t links = 0; uint32_t pfg = r->pen.fg, pbg = r->pen.bg; @@ -903,13 +903,13 @@ static TERM_NOINLINE uint32_t runs_scan(struct hist_runs *r, const struct cell * const struct cell *c = &cells[i]; uint32_t sl = (uint32_t)(c->flags & STYLE_FLAGS) | ((uint32_t)c->pad << 16); links |= c->pad; - if (TERM_EXPECT(((c->fg ^ pfg) | (c->bg ^ pbg) | (sl ^ psl)) != 0, 0)) { + if (WSAP_VTCORE_EXPECT(((c->fg ^ pfg) | (c->bg ^ pbg) | (sl ^ psl)) != 0, 0)) { if (count) { uint32_t header = (pfg != bfg ? RUN_FG : 0) | (pbg != bbg ? RUN_BG : 0) | ((uint16_t)psl != (uint16_t)bsl ? RUN_ATTR : 0) | ((psl >> 16) != (bsl >> 16) ? RUN_LINK : 0); rp[0] = (uint8_t)header; - if (TERM_EXPECT(count < 0x80, 1)) { + if (WSAP_VTCORE_EXPECT(count < 0x80, 1)) { rp[1] = (uint8_t)count; rp += 2; } else { @@ -919,7 +919,7 @@ static TERM_NOINLINE uint32_t runs_scan(struct hist_runs *r, const struct cell * rp += (header & RUN_FG) ? 4 : 0; put_u32(rp, pbg); rp += (header & RUN_BG) ? 4 : 0; - if (TERM_EXPECT(header & (RUN_ATTR | RUN_LINK), 0)) { + if (WSAP_VTCORE_EXPECT(header & (RUN_ATTR | RUN_LINK), 0)) { if (header & RUN_ATTR) { put_u16(rp, (uint16_t)psl); rp += 2; } if (header & RUN_LINK) { put_u16(rp, (uint16_t)(psl >> 16)); rp += 2; } } @@ -945,8 +945,8 @@ static TERM_NOINLINE uint32_t runs_scan(struct hist_runs *r, const struct cell * * Their bytes go to dst. */ static inline int narrow_uniform_prefix(const struct cell *cells, int len, uint8_t *dst) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return narrow_uniform_prefix_avx512(cells, len, dst); #endif uint32_t sl = (uint32_t)(cells[0].flags & STYLE_FLAGS) | ((uint32_t)cells[0].pad << 16); @@ -961,11 +961,11 @@ static inline int narrow_uniform_prefix(const struct cell *cells, int len, uint8 return k; } -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) /* Encode a prefix of cells with the pen of cells[0] and no clusters, eight * cells at a time. Return the cells used; runcells counts the cells that * are not trail cells. */ -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static int uniform_utf8_prefix(const struct cell *cells, int len, uint8_t *dst, struct enc *o, uint32_t *runcells) { @@ -1019,11 +1019,11 @@ static int uniform_utf8_prefix(const struct cell *cells, int len, uint8_t *dst, bm = _mm256_maskz_mov_epi32((__mmask8)~m_trail, bm); __mmask32 keep_bytes = _mm256_movepi8_mask(bm); _mm256_storeu_si256((__m256i *)(void *)(dst + bytes), _mm256_maskz_compress_epi8(keep_bytes, w)); - bytes += (uint32_t)term_popcount32(keep_bytes); - uint32_t trails = (uint32_t)term_popcount32(m_trail); - ncells += 8u - trails + (uint32_t)term_popcount32(m_wide); + bytes += (uint32_t)wsap_vtcore_popcount32(keep_bytes); + uint32_t trails = (uint32_t)wsap_vtcore_popcount32(m_trail); + ncells += 8u - trails + (uint32_t)wsap_vtcore_popcount32(m_wide); *runcells += 8u - trails; - nwide += (uint32_t)term_popcount32(m_wide); + nwide += (uint32_t)wsap_vtcore_popcount32(m_wide); wide |= m_wide; ascii &= (uint32_t)(uint8_t)~(ge80 & ~m_trail); } @@ -1036,11 +1036,11 @@ static int uniform_utf8_prefix(const struct cell *cells, int len, uint8_t *dst, } #endif -static TERM_NOINLINE size_t encode_cluster(uint8_t *dst, const struct gstore *g, +static WSAP_VTCORE_NOINLINE size_t encode_cluster(uint8_t *dst, const struct gstore *g, uint32_t handle, uint16_t f) { - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; - int n = term_gstore_expand(g, handle, cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int n = wsap_vtcore_gstore_expand(g, handle, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); size_t b = 0; dst[b++] = PREFIX_CLUSTER; dst[b++] = (uint8_t)((n & 0x1f) | ((f & CELL_WIDE) ? 0x80 : 0) | @@ -1053,7 +1053,7 @@ static TERM_NOINLINE size_t encode_cluster(uint8_t *dst, const struct gstore *g, static size_t encode_shaped(uint8_t *dst, uint32_t cp, uint16_t f, const struct gstore *g, uint8_t *flags) { - if (term_grapheme_is_handle(cp)) { + if (wsap_vtcore_grapheme_is_handle(cp)) { *flags |= HLINE_HAS_CLUSTER | ((f & CELL_WIDE) ? HLINE_HAS_WIDE : 0); return encode_cluster(dst, g, cp, f); } @@ -1118,8 +1118,8 @@ static int encode_cells(struct hist_runs *r, const struct cell *cells, int n, ui *o = (struct enc){ .bytes = (uint32_t)i, .cells = (uint32_t)i, .flags = (uint8_t)(HLINE_NARROW | (c0->pad ? HLINE_HAS_LINK : 0)) }; } -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512() && n - i >= 8 && ((cells[i].flags & SHAPE_FLAGS) || cells[i].c >= 0x80)) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512() && n - i >= 8 && ((cells[i].flags & SHAPE_FLAGS) || cells[i].c >= 0x80)) { /* Text with one pen, eight cells per step. */ struct enc u; uint32_t runcells = 0; @@ -1155,18 +1155,18 @@ static int encode_cells(struct hist_runs *r, const struct cell *cells, int n, ui continue; uint32_t cp = c->c; bool simple = !(f & (CELL_WIDE | CELL_EMOJI | CELL_TEXT)) && cp - 0x20u < 0x60u; - if (!simple && term_grapheme_is_handle(cp) && + if (!simple && wsap_vtcore_grapheme_is_handle(cp) && bytes + CLUSTER_BYTES + (size_t)(n - i) * CELL_BYTES > cap) break; uint32_t sl = (uint32_t)(f & STYLE_FLAGS) | ((uint32_t)c->pad << 16); links |= c->pad; - if (TERM_EXPECT(((c->fg ^ pfg) | (c->bg ^ pbg) | (sl ^ psl)) != 0, 0)) { + if (WSAP_VTCORE_EXPECT(((c->fg ^ pfg) | (c->bg ^ pbg) | (sl ^ psl)) != 0, 0)) { if (count) { uint32_t header = (pfg != bfg ? RUN_FG : 0) | (pbg != bbg ? RUN_BG : 0) | ((uint16_t)psl != (uint16_t)bsl ? RUN_ATTR : 0) | ((psl >> 16) != (bsl >> 16) ? RUN_LINK : 0); *rp++ = (uint8_t)header; - if (TERM_EXPECT(count < 0x80, 1)) + if (WSAP_VTCORE_EXPECT(count < 0x80, 1)) *rp++ = (uint8_t)count; else rp += put_varint(rp, count); @@ -1174,7 +1174,7 @@ static int encode_cells(struct hist_runs *r, const struct cell *cells, int n, ui rp += (header & RUN_FG) ? 4 : 0; put_u32(rp, pbg); rp += (header & RUN_BG) ? 4 : 0; - if (TERM_EXPECT(header & (RUN_ATTR | RUN_LINK), 0)) { + if (WSAP_VTCORE_EXPECT(header & (RUN_ATTR | RUN_LINK), 0)) { if (header & RUN_ATTR) { put_u16(rp, (uint16_t)psl); rp += 2; } if (header & RUN_LINK) { put_u16(rp, (uint16_t)(psl >> 16)); rp += 2; } } @@ -1189,7 +1189,7 @@ static int encode_cells(struct hist_runs *r, const struct cell *cells, int n, ui } count++; nwide += (f & CELL_WIDE) != 0; - if (TERM_EXPECT(simple, 1)) { + if (WSAP_VTCORE_EXPECT(simple, 1)) { dst[bytes++] = (uint8_t)cp; ncells++; continue; @@ -1408,7 +1408,7 @@ static void close_part(struct hist *h, struct hline *p) p->flags &= (uint8_t)~HLINE_OPEN; } -void term_hist_close_open_line(struct hist *h) +void wsap_vtcore_hist_close_open_line(struct hist *h) { struct hline *p = open_part(h); if (!p) @@ -1424,7 +1424,7 @@ void term_hist_close_open_line(struct hist *h) uint64_t first = line_first(h, id); uint64_t rows = first == h->head - 1 ? cheap_rows(p->cells, p->wide, cols) - : cheap_rows(term_hist_line_cells(h, id), term_hist_line_wide(h, id), cols); + : cheap_rows(wsap_vtcore_hist_line_cells(h, id), wsap_vtcore_hist_line_wide(h, id), cols); if (!rows && h->walk_on) { walk_advance(h); rows = h->walk_rows; @@ -1440,7 +1440,7 @@ static struct hline *open_room(struct hist *h, struct hline *p, size_t text_need { uint32_t start = p->off & 0xffff; size_t runs = h->runs.len + runs_need + RUN_MAX; - if (TERM_EXPECT(start + p->text_len + text_need + runs <= HIST_PAGE_USABLE && + if (WSAP_VTCORE_EXPECT(start + p->text_len + text_need + runs <= HIST_PAGE_USABLE && p->cells + add_cells <= HIST_MAX_PART_CELLS && runs <= UINT16_MAX, 1)) return p; @@ -1547,7 +1547,7 @@ static inline void part_add(struct hist *h, struct hline *p, const struct enc *e h->page_used[p->off >> 16] = (p->off & 0xffff) + p->text_len; } -void term_hist_push_row(struct hist *h, const struct cell *cells, int len, bool wrapped, +void wsap_vtcore_hist_push_row(struct hist *h, const struct cell *cells, int len, bool wrapped, const struct gstore *g) { if (!h->line_limit) @@ -1555,7 +1555,7 @@ void term_hist_push_row(struct hist *h, const struct cell *cells, int len, bool struct hline *p = open_part(h); if (!p) { if (len <= 0 && !wrapped) { - term_hist_push_blank(h, 1); + wsap_vtcore_hist_push_blank(h, 1); return; } if (!wrapped && push_uniform_line(h, cells, len)) @@ -1582,12 +1582,12 @@ void term_hist_push_row(struct hist *h, const struct cell *cells, int len, bool return; } if (!wrapped) - term_hist_close_open_line(h); + wsap_vtcore_hist_close_open_line(h); else if (h->wrap_cols && (h->walk_on || (p->flags & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER)))) walk_advance(h); } -void term_hist_push_ascii(struct hist *h, const char *bytes, int n, const struct pen_attr *pen, +void wsap_vtcore_hist_push_ascii(struct hist *h, const char *bytes, int n, const struct pen_attr *pen, bool wrapped) { if (!h->line_limit) @@ -1598,7 +1598,7 @@ void term_hist_push_ascii(struct hist *h, const char *bytes, int n, const struct struct hline *p = open_part(h); if (!p) { if (n <= 0 && !wrapped) { - term_hist_push_blank(h, 1); + wsap_vtcore_hist_push_blank(h, 1); return; } /* A default-pen line: one copy and one descriptor. */ @@ -1643,7 +1643,7 @@ void term_hist_push_ascii(struct hist *h, const char *bytes, int n, const struct n -= chunk; } if (!wrapped) - term_hist_close_open_line(h); + wsap_vtcore_hist_close_open_line(h); else if (h->wrap_cols && h->walk_on) walk_advance(h); } @@ -1663,7 +1663,7 @@ static void text_row_readd(struct hist *h, const struct text_row *row) hist_runs_add(&h->runs, &rr->pen, rr->count); } -void term_hist_push_text(struct hist *h, const struct text_row *row, bool wrapped) +void wsap_vtcore_hist_push_text(struct hist *h, const struct text_row *row, bool wrapped) { if (!h->line_limit) return; @@ -1672,7 +1672,7 @@ void term_hist_push_text(struct hist *h, const struct text_row *row, bool wrappe size_t runs_need = (size_t)rr->len * RUN_MAX / 2 + 2 * RUN_MAX; if (!p) { if (row->cells == 0 && !wrapped) { - term_hist_push_blank(h, 1); + wsap_vtcore_hist_push_blank(h, 1); return; } if (!wrapped && pen_attr_is_default(&row->start)) { @@ -1738,7 +1738,7 @@ void term_hist_push_text(struct hist *h, const struct text_row *row, bool wrappe } part_add(h, p, &(struct enc){ row->text_len, row->cells, row->flags, row->wide }); if (!wrapped) - term_hist_close_open_line(h); + wsap_vtcore_hist_close_open_line(h); else if (h->wrap_cols && (h->walk_on || (p->flags & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER)))) walk_advance(h); } @@ -1754,8 +1754,8 @@ struct hist_stream_state { /* Write the narrow descriptors of ends[i..stop) in blocks, while a block * fits before the ring wraps. Return the first line left for the caller. */ -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, uint32_t cols, struct hist_stream_state *state) { @@ -1771,7 +1771,7 @@ static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends __m512i end = _mm512_cvtepu16_epi32(_mm256_loadu_si256((const __m256i *)(ends + i + 1))); __m512i lens = _mm512_sub_epi32(_mm512_sub_epi32(end, start), _mm512_set1_epi32(1)); __mmask16 empty = _mm512_cmpeq_epi32_mask(lens, _mm512_setzero_si512()); - uint32_t refs = 16 - term_popcount32(empty); + uint32_t refs = 16 - wsap_vtcore_popcount32(empty); text_count += refs; __m512i offsets = _mm512_mask_mov_epi32(_mm512_add_epi32(start, _mm512_set1_epi32((int)base)), empty, _mm512_set1_epi32(-1)); @@ -1821,8 +1821,8 @@ static int lf_rows_avx512(struct hist *restrict h, const uint16_t *restrict ends } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static int lf_rows_avx2(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, uint32_t cols, struct hist_stream_state *state) { @@ -1841,7 +1841,7 @@ static int lf_rows_avx2(struct hist *restrict h, const uint16_t *restrict ends, __m128i end = _mm_cvtepu16_epi32(_mm_loadl_epi64((const __m128i *)(ends + i + 1))); __m128i lens = _mm_sub_epi32(_mm_sub_epi32(end, start), _mm_set1_epi32(1)); __m128i empty = _mm_cmpeq_epi32(lens, _mm_setzero_si128()); - refs = 4 - term_popcount32((unsigned)_mm_movemask_ps(_mm_castsi128_ps(empty))); + refs = 4 - wsap_vtcore_popcount32((unsigned)_mm_movemask_ps(_mm_castsi128_ps(empty))); __m128i offsets = _mm_or_si128(_mm_add_epi32(start, _mm_set1_epi32((int)base)), empty); __m128i rs = _mm_set1_epi32(1); if (cols == 1) rs = _mm_max_epu32(lens, rs); @@ -1883,12 +1883,12 @@ static int lf_rows_avx2(struct hist *restrict h, const uint16_t *restrict ends, static inline int lf_rows(struct hist *restrict h, const uint16_t *restrict ends, int i, int stop, uint32_t cols, struct hist_stream_state *state) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return lf_rows_avx512(h, ends, i, stop, cols, state); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return lf_rows_avx2(h, ends, i, stop, cols, state); #endif #if defined(__aarch64__) @@ -1949,14 +1949,14 @@ static inline int lf_rows(struct hist *restrict h, const uint16_t *restrict ends return i; } -TERM_NOINLINE -void term_hist_push_ascii_lf(struct hist *restrict h, const char *restrict bytes, +WSAP_VTCORE_NOINLINE +void wsap_vtcore_hist_push_ascii_lf(struct hist *restrict h, const char *restrict bytes, const uint16_t *restrict ends, int count) { if (!h->line_limit) return; int i = 0; if (count && hist_is_open(h)) { - term_hist_push_ascii(h, bytes + ends[0], ends[1] - ends[0] - 1, NULL, false); + wsap_vtcore_hist_push_ascii(h, bytes + ends[0], ends[1] - ends[0] - 1, NULL, false); i++; } uint32_t cols = h->wrap_cols ? h->wrap_cols : 1; @@ -2034,8 +2034,8 @@ static_assert(offsetof(struct hist_ascii_line, len) == 8, "len is in the second /* Write the narrow one-row descriptors of lines[i..stream_end) in blocks, * while a block fits before the ring wraps. first is the first byte of * the page copy at base. Return the first line left for the caller. */ -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_line *lines, int i, int stream_end, struct hist_stream_state *state) { @@ -2065,7 +2065,7 @@ static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_ _mm512_inserti64x4(_mm512_castsi256_si512(lo), hi, 1), _mm512_set1_epi32(UINT16_MAX)); __mmask16 empty = _mm512_cmpeq_epi32_mask(lens, _mm512_setzero_si512()); - uint32_t refs = 16 - term_popcount32(empty); + uint32_t refs = 16 - wsap_vtcore_popcount32(empty); text_count += refs; offsets = _mm512_mask_mov_epi32(offsets, empty, _mm512_set1_epi32(-1)); __m512i tags = _mm512_set1_epi32((1u << 24) | (HLINE_NARROW << 16)); @@ -2099,8 +2099,8 @@ static int stream_lines_avx512(struct hist *restrict h, const struct hist_ascii_ } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static int stream_lines_avx2(struct hist *restrict h, const struct hist_ascii_line *lines, int i, int stream_end, struct hist_stream_state *state) { @@ -2118,7 +2118,7 @@ static int stream_lines_avx2(struct hist *restrict h, const struct hist_ascii_li _mm_i32gather_epi32((const int *)((const char *)(lines + i) + 8), index, 1), _mm_set1_epi32(UINT16_MAX)); __m128i empty = _mm_cmpeq_epi32(lens, _mm_setzero_si128()); - refs = 4 - term_popcount32((unsigned)_mm_movemask_ps(_mm_castsi128_ps(empty))); + refs = 4 - wsap_vtcore_popcount32((unsigned)_mm_movemask_ps(_mm_castsi128_ps(empty))); __m128i offsets = _mm_add_epi32(ptrs, _mm_set1_epi32((int)(base - (uint32_t)(uintptr_t)first))); offsets = _mm_or_si128(offsets, empty); @@ -2142,12 +2142,12 @@ static int stream_lines_avx2(struct hist *restrict h, const struct hist_ascii_li static inline int stream_lines(struct hist *restrict h, const struct hist_ascii_line *lines, int i, int stream_end, struct hist_stream_state *state) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return stream_lines_avx512(h, lines, i, stream_end, state); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return stream_lines_avx2(h, lines, i, stream_end, state); #endif #if defined(__aarch64__) @@ -2179,7 +2179,7 @@ static inline int stream_lines(struct hist *restrict h, const struct hist_ascii_ return i; } -void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *lines, int count, +void wsap_vtcore_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *lines, int count, const struct pen_attr *pen) { if (!h->line_limit) @@ -2196,15 +2196,15 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li lines[end].len <= INT32_MAX - bytes) { bytes += lines[end++].len; } - term_hist_push_ascii(h, l->ptr, bytes, pen, true); + wsap_vtcore_hist_push_ascii(h, l->ptr, bytes, pen, true); i = end; continue; } if (!def || hist_is_open(h)) { if (l->len == 0 && !l->wrapped) - term_hist_push_blank(h, 1); + wsap_vtcore_hist_push_blank(h, 1); else - term_hist_push_ascii(h, l->ptr, l->len, pen, l->wrapped); + wsap_vtcore_hist_push_ascii(h, l->ptr, l->len, pen, l->wrapped); i++; continue; } @@ -2230,7 +2230,7 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li size_t span = (size_t)(next->ptr - l->ptr) + next->len; if (span > room) break; - if (TERM_EXPECT(next->len > (uint32_t)cols, 0)) + if (WSAP_VTCORE_EXPECT(next->len > (uint32_t)cols, 0)) extra_rows += rows_narrow(next->len, cols) - 1; stream_end++; } @@ -2259,7 +2259,7 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li struct hline *dst = &h->ring[state.head++ & h->ring_mask]; if (len) { uint32_t line_off = base + (uint32_t)(lines[i].ptr - l->ptr); - if (TERM_EXPECT(len <= cols, 1)) { + if (WSAP_VTCORE_EXPECT(len <= cols, 1)) { part_put_narrow(dst, line_off, len); } else { part_put_narrow_rows(dst, line_off, len, rows_narrow(len, cols)); @@ -2309,7 +2309,7 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li uint32_t len = lines[i].len; /* A blank line: no text, no page slot, one row. The scan does * not stop on it, so the batch keeps its room and its setup. */ - if (TERM_EXPECT(len == 0, 0)) { + if (WSAP_VTCORE_EXPECT(len == 0, 0)) { ring[head++ & rmask] = HLINE_BLANK; rows_add++; continue; @@ -2317,7 +2317,7 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li bytes_copy_small(page + off, lines[i].ptr, (int)len); n_text++; any_text = true; - if (TERM_EXPECT(len <= cols, 1)) { + if (WSAP_VTCORE_EXPECT(len <= cols, 1)) { part_put_narrow(&ring[head++ & rmask], page_off | off, len); rows_add++; } else { @@ -2340,12 +2340,12 @@ void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *li } } -void term_hist_push_blank(struct hist *h, size_t n) +void wsap_vtcore_hist_push_blank(struct hist *h, size_t n) { if (!h->line_limit || n == 0) return; if (hist_is_open(h)) { - term_hist_close_open_line(h); + wsap_vtcore_hist_close_open_line(h); n--; } if (n == 0) @@ -2361,7 +2361,7 @@ void term_hist_push_blank(struct hist *h, size_t n) } if (n >= h->line_limit) { uint64_t end = hist_end_id(h) + n; - term_hist_clear(h); + wsap_vtcore_hist_clear(h); h->base_id = h->rows_id = end - h->line_limit; n = h->line_limit; h->all_blank = true; @@ -2429,7 +2429,7 @@ static void runs_iter_init(struct runs_iter *it, const struct hist *h, const str /* Take up to n cells of the current run. it->pen is their pen. */ static inline uint32_t runs_take(struct runs_iter *it, uint32_t n) { - while (TERM_EXPECT(it->left == 0, 0)) { + while (WSAP_VTCORE_EXPECT(it->left == 0, 0)) { if (it->p < it->end) { it->p = read_run(it->p, &it->pen, &it->left); } else if (it->pending) { @@ -2516,21 +2516,21 @@ static const uint8_t *text_cell(const uint8_t *s, const uint8_t *end, struct gst } uint8_t k = s[1]; s += 2; - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; int n = 0; for (int i = 0; i < (k & 0x1f) && s < end; i++) { uint32_t c; s += get_utf8(s, end, &c); - if (n < TERM_GRAPHEME_MAX_LEN) + if (n < WSAP_VTCORE_GRAPHEME_MAX_LEN) cps[n++] = c; } - *cp = n == 0 ? ' ' : (g && n > 1) ? term_gstore_intern(g, cps, n) : cps[0]; + *cp = n == 0 ? ' ' : (g && n > 1) ? wsap_vtcore_gstore_intern(g, cps, n) : cps[0]; *shape = (uint16_t)(((k & 0x80) ? CELL_WIDE : 0) | ((k & 0x40) ? CELL_EMOJI : 0) | ((k & 0x20) ? CELL_TEXT : 0)); return s; } -uint64_t term_hist_line_cells(const struct hist *h, uint64_t id) +uint64_t wsap_vtcore_hist_line_cells(const struct hist *h, uint64_t id) { if (!line_valid(h, id)) return 0; @@ -2545,7 +2545,7 @@ uint64_t term_hist_line_cells(const struct hist *h, uint64_t id) return cells; } -uint64_t term_hist_line_wide(const struct hist *h, uint64_t id) +uint64_t wsap_vtcore_hist_line_wide(const struct hist *h, uint64_t id) { if (!line_valid(h, id)) return 0; @@ -2560,7 +2560,7 @@ uint64_t term_hist_line_wide(const struct hist *h, uint64_t id) return wide; } -uint8_t term_hist_line_flags(const struct hist *h, uint64_t id) +uint8_t wsap_vtcore_hist_line_flags(const struct hist *h, uint64_t id) { if (!line_valid(h, id)) return 0; @@ -2596,7 +2596,7 @@ static int line_rows_walk(const struct hist *h, uint64_t first, uint64_t end, in return rows; } -int term_hist_line_rows(const struct hist *h, uint64_t id, int cols) +int wsap_vtcore_hist_line_rows(const struct hist *h, uint64_t id, int cols) { if (cols <= 0 || !line_valid(h, id)) return 0; @@ -2604,7 +2604,7 @@ int term_hist_line_rows(const struct hist *h, uint64_t id, int cols) const struct hline *f = part(h, first); if (cols == h->wrap_cols) { if (id < h->rows_id && - ((f->flags & HLINE_ROWS_EXACT) || !(term_hist_line_flags(h, id) & HLINE_HAS_WIDE))) { + ((f->flags & HLINE_ROWS_EXACT) || !(wsap_vtcore_hist_line_flags(h, id) & HLINE_HAS_WIDE))) { if (f->wrap_rows != ROWS_UNKNOWN) return f->wrap_rows; if ((f->flags & HLINE_ROWS_EXACT) && h->exact_rows) @@ -2614,9 +2614,9 @@ int term_hist_line_rows(const struct hist *h, uint64_t id, int cols) h->walk_off == part(h, h->walk_seq)->text_len) return (int)h->walk_rows; } - uint64_t cells = term_hist_line_cells(h, id); + uint64_t cells = wsap_vtcore_hist_line_cells(h, id); if (cells <= (uint64_t)cols || - !(term_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) + !(wsap_vtcore_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) return (int)rows_narrow(cells, cols); return line_rows_walk(h, first, line_end(h, first), cols); } @@ -2672,7 +2672,7 @@ static bool line_narrow(const struct hist *h, uint64_t first, uint64_t end) return true; } -int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, int count, int cols, +int wsap_vtcore_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, int count, int cols, struct cell *out, int *lens, struct gstore *g) { if (count <= 0 || start_seg < 0 || cols <= 0 || !line_valid(h, id)) @@ -2730,7 +2730,7 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, } if (g) - term_gstore_pin(g); + wsap_vtcore_gstore_pin(g); int row = 0, col = 0; int end_seg = start_seg + count; uint64_t s = first; @@ -2787,14 +2787,14 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, int seg_idx = row - start_seg; struct cell *row_out = out + (size_t)seg_idx * (size_t)cols; if (col < cols) - row_out[col] = (struct cell){ ' ', TERM_COLOR_FG, TERM_COLOR_BG, CELL_WRAP_PAD, 0 }; + row_out[col] = (struct cell){ ' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, CELL_WRAP_PAD, 0 }; if (lens) lens[seg_idx] = col < cols ? cols : col; row++; col = 0; if (row == end_seg) { if (g) - term_gstore_unpin(g); + wsap_vtcore_gstore_unpin(g); dec->epoch = h->index_epoch; dec->id = id; dec->cols = (uint16_t)cols; @@ -2820,7 +2820,7 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, } if (row == end_seg) { if (g) - term_gstore_unpin(g); + wsap_vtcore_gstore_unpin(g); dec->epoch = h->index_epoch; dec->id = id; dec->cols = (uint16_t)cols; @@ -2841,15 +2841,15 @@ int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, } dec->valid = false; if (g) - term_gstore_unpin(g); + wsap_vtcore_gstore_unpin(g); return decoded; } -int term_hist_decode_segment(const struct hist *h, uint64_t id, int seg, int cols, +int wsap_vtcore_hist_decode_segment(const struct hist *h, uint64_t id, int seg, int cols, struct cell *out, struct gstore *g) { int len = 0; - int got = term_hist_decode_segments(h, id, seg, 1, cols, out, &len, g); + int got = wsap_vtcore_hist_decode_segments(h, id, seg, 1, cols, out, &len, g); return got > 0 ? len : 0; } @@ -2859,7 +2859,7 @@ static int decode_line(const struct hist *h, uint64_t first, uint64_t end, { int n = 0; if (g) - term_gstore_pin(g); + wsap_vtcore_gstore_pin(g); for (uint64_t s = first; s < end; s++) { const struct hline *p = part(h, s); if (!p->text_len) @@ -2882,11 +2882,11 @@ static int decode_line(const struct hist *h, uint64_t first, uint64_t end, } } if (g) - term_gstore_unpin(g); + wsap_vtcore_gstore_unpin(g); return n; } -int term_hist_text_decode(const struct text_row *row, struct cell *out, int cap, struct gstore *g) +int wsap_vtcore_hist_text_decode(const struct text_row *row, struct cell *out, int cap, struct gstore *g) { struct runs_iter it; runs_iter_runs(&it, &row->runs, &row->start); @@ -2921,7 +2921,7 @@ int term_hist_text_decode(const struct text_row *row, struct cell *out, int cap, return n < cap ? n : cap; } -void term_hist_text_mark_links(const struct text_row *row, void (*mark)(void *ud, uint16_t link), void *ud) +void wsap_vtcore_hist_text_mark_links(const struct text_row *row, void (*mark)(void *ud, uint16_t link), void *ud) { if (!(row->flags & HLINE_HAS_LINK) && !row->start.link) return; @@ -2940,7 +2940,7 @@ void term_hist_text_mark_links(const struct text_row *row, void (*mark)(void *ud mark(ud, it.pending_pen.link); } -void term_hist_mark_links(const struct hist *h, void (*mark)(void *ud, uint16_t link), void *ud) +void wsap_vtcore_hist_mark_links(const struct hist *h, void (*mark)(void *ud, uint16_t link), void *ud) { for (uint64_t s = h->tail; s < h->head; s++) { const struct hline *p = part(h, s); @@ -2976,7 +2976,7 @@ static void drop_head_part(struct hist *h) cont_trim(h); } -int term_hist_peek_last_line(const struct hist *h, struct cell *out, int cap, struct gstore *g) +int wsap_vtcore_hist_peek_last_line(const struct hist *h, struct cell *out, int cap, struct gstore *g) { if (h->lines == 0) return 0; @@ -2984,13 +2984,13 @@ int term_hist_peek_last_line(const struct hist *h, struct cell *out, int cap, st return decode_line(h, line_first(h, id), h->head, out, cap, g); } -int term_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore *g) +int wsap_vtcore_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore *g) { if (h->lines == 0) return 0; uint64_t id = hist_end_id(h) - 1; uint64_t first = line_first(h, id); - int n = out ? decode_line(h, first, h->head, out, cap, g) : (int)term_hist_line_cells(h, id); + int n = out ? decode_line(h, first, h->head, out, cap, g) : (int)wsap_vtcore_hist_line_cells(h, id); if (id < h->rows_id) { rows_uncount(h, id); h->rows_id = id; @@ -3001,8 +3001,8 @@ int term_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore h->index_epoch++; if (h->lines) { uint64_t last = hist_end_id(h) - 1; - h->last_cells = term_hist_line_cells(h, last); - h->last_wide = term_hist_line_wide(h, last); + h->last_cells = wsap_vtcore_hist_line_cells(h, last); + h->last_wide = wsap_vtcore_hist_line_wide(h, last); h->last_id = last; } runs_reset(&h->runs); @@ -3015,21 +3015,21 @@ int term_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore return n; } -int term_hist_pop_tail_cells(struct hist *h, int n, struct cell *out, struct gstore *g) +int wsap_vtcore_hist_pop_tail_cells(struct hist *h, int n, struct cell *out, struct gstore *g) { if (h->lines == 0 || n <= 0) return 0; - uint64_t total = term_hist_line_cells(h, hist_end_id(h) - 1); + uint64_t total = wsap_vtcore_hist_line_cells(h, hist_end_id(h) - 1); if (total == 0) { - term_hist_pop_line(h, NULL, 0, g); + wsap_vtcore_hist_pop_line(h, NULL, 0, g); return 0; } struct cell *all = malloc((size_t)total * sizeof(*all)); if (!all) return 0; if (g) - term_gstore_pin(g); - int got = term_hist_pop_line(h, all, (int)total, g); + wsap_vtcore_gstore_pin(g); + int got = wsap_vtcore_hist_pop_line(h, all, (int)total, g); int take = n < got ? n : got; int keep = got - take; if (keep > 0 && (all[keep].flags & CELL_TRAIL)) { @@ -3041,17 +3041,17 @@ int term_hist_pop_tail_cells(struct hist *h, int n, struct cell *out, struct gst if (keep > 0) { uint16_t cols = h->wrap_cols ? h->wrap_cols : 1; for (int i = 0; i < keep; i += cols) - term_hist_push_row(h, all + i, keep - i < cols ? keep - i : cols, true, g); + wsap_vtcore_hist_push_row(h, all + i, keep - i < cols ? keep - i : cols, true, g); } if (g) - term_gstore_unpin(g); + wsap_vtcore_gstore_unpin(g); free(all); return take; } /* ---- Rows ---- */ -void term_hist_set_width(struct hist *h, int cols) +void wsap_vtcore_hist_set_width(struct hist *h, int cols) { if (h->wrap_cols == cols) return; @@ -3061,7 +3061,7 @@ void term_hist_set_width(struct hist *h, int cols) h->walk_on = false; } -uint64_t term_hist_line_estimate(const struct hist *h, uint64_t id, int cols) +uint64_t wsap_vtcore_hist_line_estimate(const struct hist *h, uint64_t id, int cols) { if (!line_valid(h, id)) return 0; @@ -3071,18 +3071,18 @@ uint64_t term_hist_line_estimate(const struct hist *h, uint64_t id, int cols) return first->wrap_rows != ROWS_UNKNOWN ? first->wrap_rows : h->exact_rows[line_first(h, id) & h->ring_mask]; } - uint64_t cells = term_hist_line_cells(h, id); + uint64_t cells = wsap_vtcore_hist_line_cells(h, id); if (cols == 1) - cells -= term_hist_line_wide(h, id); + cells -= wsap_vtcore_hist_line_wide(h, id); return rows_narrow(cells, cols); } -void term_hist_refine_rows(struct hist *h, uint64_t id, int cols, int rows) +void wsap_vtcore_hist_refine_rows(struct hist *h, uint64_t id, int cols, int rows) { if (cols != h->wrap_cols || id >= h->rows_id || id < h->base_id) return; uint64_t seq = line_first(h, id); - uint64_t old = term_hist_line_estimate(h, id, cols); + uint64_t old = wsap_vtcore_hist_line_estimate(h, id, cols); if (rows >= ROWS_UNKNOWN) { if (!h->exact_rows) { h->exact_rows = calloc((size_t)h->ring_mask + 1, sizeof(*h->exact_rows)); @@ -3098,53 +3098,53 @@ void term_hist_refine_rows(struct hist *h, uint64_t id, int cols, int rows) } /* Fill descriptor counts only. This never reads the encoded text. */ -void term_hist_prepare_rows(struct hist *h, int cols) +void wsap_vtcore_hist_prepare_rows(struct hist *h, int cols) { if (cols != h->wrap_cols) - term_hist_set_width(h, cols); + wsap_vtcore_hist_set_width(h, cols); uint64_t stop = hist_end_id(h) - (hist_is_open(h) ? 1 : 0); for (; h->rows_id < stop; h->rows_id++) { - uint64_t rows = term_hist_line_estimate(h, h->rows_id, cols); + uint64_t rows = wsap_vtcore_hist_line_estimate(h, h->rows_id, cols); struct hline *first = part(h, line_first(h, h->rows_id)); first->wrap_rows = row_count_byte(rows); first->flags &= (uint8_t)~HLINE_ROWS_EXACT; if (rows < ROWS_UNKNOWN && - (!(term_hist_line_flags(h, h->rows_id) & HLINE_HAS_WIDE) || cols == 1)) + (!(wsap_vtcore_hist_line_flags(h, h->rows_id) & HLINE_HAS_WIDE) || cols == 1)) first->flags |= HLINE_ROWS_EXACT; h->counted_rows += rows; } } -uint64_t term_hist_estimated_rows(const struct hist *h, int cols) +uint64_t wsap_vtcore_hist_estimated_rows(const struct hist *h, int cols) { if (!h || cols <= 0 || !h->lines) return 0; uint64_t total = cols == h->wrap_cols ? h->counted_rows : 0; uint64_t first = cols == h->wrap_cols ? h->rows_id : h->base_id; for (uint64_t id = first; id < hist_end_id(h); id++) - total += term_hist_line_estimate(h, id, cols); + total += wsap_vtcore_hist_line_estimate(h, id, cols); return total; } -uint64_t term_hist_rows(const struct hist *h, int cols) +uint64_t wsap_vtcore_hist_rows(const struct hist *h, int cols) { if (!h || cols <= 0) return 0; uint64_t total = 0; for (uint64_t id = hist_first_id(h); id < hist_end_id(h); id++) - total += (uint64_t)term_hist_line_rows(h, id, cols); + total += (uint64_t)wsap_vtcore_hist_line_rows(h, id, cols); return total; } /* Locate a row boundary by its cell offset. Wide wrap pads do not count. */ -uint64_t term_hist_segment_cell(const struct hist *h, uint64_t id, int seg, int cols) +uint64_t wsap_vtcore_hist_segment_cell(const struct hist *h, uint64_t id, int seg, int cols) { if (!line_valid(h, id)) return 0; uint64_t base = id == h->base_cell_id ? h->base_cell : 0; if (seg <= 0) return base; - if (!(term_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) + if (!(wsap_vtcore_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) return base + (uint64_t)seg * cols; uint64_t first = line_first(h, id), end = line_end(h, first), cells = 0; int row = 0, col = 0; @@ -3168,14 +3168,14 @@ uint64_t term_hist_segment_cell(const struct hist *h, uint64_t id, int seg, int return base + cells; } -int term_hist_cell_segment(const struct hist *h, uint64_t id, uint64_t cell, int cols) +int wsap_vtcore_hist_cell_segment(const struct hist *h, uint64_t id, uint64_t cell, int cols) { if (!line_valid(h, id) || cols <= 0) return 0; uint64_t base = id == h->base_cell_id ? h->base_cell : 0; cell = cell > base ? cell - base : 0; - if (!(term_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) { - uint64_t cells = term_hist_line_cells(h, id); + if (!(wsap_vtcore_hist_line_flags(h, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER))) { + uint64_t cells = wsap_vtcore_hist_line_cells(h, id); if (cells && cell >= cells) cell = cells - 1; return (int)(cell / cols); @@ -3205,7 +3205,7 @@ int term_hist_cell_segment(const struct hist *h, uint64_t id, uint64_t cell, int /* ---- Life cycle ---- */ -bool term_hist_init(struct hist *h, int line_limit, size_t byte_cap) +bool wsap_vtcore_hist_init(struct hist *h, int line_limit, size_t byte_cap) { memset(h, 0, sizeof(*h)); h->all_blank = true; @@ -3227,22 +3227,22 @@ bool term_hist_init(struct hist *h, int line_limit, size_t byte_cap) h->page_parts = calloc(h->max_pages, sizeof(*h->page_parts)); h->free_pages = malloc(h->max_pages * sizeof(*h->free_pages)); if (!h->pages || !h->page_used || !h->page_parts || !h->free_pages || !ring_fit(h, 1)) { - term_hist_free(h); + wsap_vtcore_hist_free(h); return false; } return true; } -void term_hist_free(struct hist *h) +void wsap_vtcore_hist_free(struct hist *h) { if (h->pages) for (uint32_t i = 0; i < h->npages; i++) - term_aligned_free(h->pages[i]); + wsap_vtcore_aligned_free(h->pages[i]); free(h->pages); free(h->page_used); free(h->page_parts); free(h->free_pages); - term_aligned_free(h->ring); + wsap_vtcore_aligned_free(h->ring); free(h->blocks); free(h->exact_rows); free(h->cont); @@ -3250,7 +3250,7 @@ void term_hist_free(struct hist *h) memset(h, 0, sizeof(*h)); } -void term_hist_clear(struct hist *h) +void wsap_vtcore_hist_clear(struct hist *h) { h->index_epoch++; uint64_t end = hist_end_id(h); @@ -92,7 +92,7 @@ struct text_row { #define TEXT_ROW_RUNS(cols) (((size_t)(cols) + 2) * 22) /* Emit the pending run in the general form. */ -void term_hist_runs_emit_slow(struct hist_runs *r); +void wsap_vtcore_hist_runs_emit_slow(struct hist_runs *r); /* Close the pending run and start one with the given pen. The caller * sized the buffer. A run that changes only colors and covers fewer than @@ -102,7 +102,7 @@ static inline void hist_runs_switch(struct hist_runs *r, struct text_pen pen) { if (r->count) { uint32_t psl = pen_sl(&r->pen); - if (TERM_EXPECT(r->count < 0x80 && psl == pen_sl(&r->base), 1)) { + if (WSAP_VTCORE_EXPECT(r->count < 0x80 && psl == pen_sl(&r->base), 1)) { uint8_t *p = r->data + r->len; uint32_t dfg = r->pen.fg != r->base.fg, dbg = r->pen.bg != r->base.bg; p[0] = (uint8_t)(dfg | dbg << 1); @@ -112,7 +112,7 @@ static inline void hist_runs_switch(struct hist_runs *r, struct text_pen pen) memcpy(p, &r->pen.bg, 4); r->len = (uint32_t)(p + dbg * 4 - r->data); } else { - term_hist_runs_emit_slow(r); + wsap_vtcore_hist_runs_emit_slow(r); } pen_set(&r->base, r->pen.fg, r->pen.bg, psl); } @@ -160,8 +160,8 @@ static inline void text_row_unshare(struct text_row *row) } /* Write the cells of a text row to out; return the cell count. */ -int term_hist_text_decode(const struct text_row *row, struct cell *out, int cap, struct gstore *g); -void term_hist_text_mark_links(const struct text_row *row, void (*mark)(void *ud, uint16_t link), void *ud); +int wsap_vtcore_hist_text_decode(const struct text_row *row, struct cell *out, int cap, struct gstore *g); +void wsap_vtcore_hist_text_mark_links(const struct text_row *row, void (*mark)(void *ud, uint16_t link), void *ud); struct hist_dec_cache { const uint8_t *p, *end; @@ -225,34 +225,34 @@ static inline uint32_t rows_narrow(uint64_t cells, int cols) (uint32_t)((cells + (uint64_t)cols - 1) / (uint64_t)cols); } -bool term_hist_init(struct hist *h, int line_limit, size_t byte_cap); -void term_hist_free(struct hist *h); -void term_hist_clear(struct hist *h); +bool wsap_vtcore_hist_init(struct hist *h, int line_limit, size_t byte_cap); +void wsap_vtcore_hist_free(struct hist *h); +void wsap_vtcore_hist_clear(struct hist *h); /* Push one screen row. It joins the open line, or starts a new line. A * wrapped row leaves the line open for the next row. */ -void term_hist_push_row(struct hist *h, const struct cell *cells, int len, bool wrapped, +void wsap_vtcore_hist_push_row(struct hist *h, const struct cell *cells, int len, bool wrapped, const struct gstore *g); -void term_hist_push_ascii(struct hist *h, const char *bytes, int n, +void wsap_vtcore_hist_push_ascii(struct hist *h, const char *bytes, int n, const struct pen_attr *pen, bool wrapped); -void term_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *lines, +void wsap_vtcore_hist_push_ascii_lines(struct hist *h, const struct hist_ascii_line *lines, int count, const struct pen_attr *pen); /* Ends include LF. ends[0] is the start of the first line. */ -void term_hist_push_ascii_lf(struct hist *h, const char *bytes, const uint16_t *ends, int count); -/* Push a text row as one screen row, like term_hist_push_row(). */ -void term_hist_push_text(struct hist *h, const struct text_row *row, bool wrapped); +void wsap_vtcore_hist_push_ascii_lf(struct hist *h, const char *bytes, const uint16_t *ends, int count); +/* Push a text row as one screen row, like wsap_vtcore_hist_push_row(). */ +void wsap_vtcore_hist_push_text(struct hist *h, const struct text_row *row, bool wrapped); /* Push n empty unwrapped rows. The first one closes an open line. */ -void term_hist_push_blank(struct hist *h, size_t n); -void term_hist_close_open_line(struct hist *h); +void wsap_vtcore_hist_push_blank(struct hist *h, size_t n); +void wsap_vtcore_hist_close_open_line(struct hist *h); /* Remove the last line. Write its cells to out (at most cap) and return the * number of cells in the line. */ -int term_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore *g); -/* Copy the last line's cells to out, as term_hist_pop_line() does, and keep the line. +int wsap_vtcore_hist_pop_line(struct hist *h, struct cell *out, int cap, struct gstore *g); +/* Copy the last line's cells to out, as wsap_vtcore_hist_pop_line() does, and keep the line. * Return the number of cells in the line. */ -int term_hist_peek_last_line(const struct hist *h, struct cell *out, int cap, struct gstore *g); +int wsap_vtcore_hist_peek_last_line(const struct hist *h, struct cell *out, int cap, struct gstore *g); /* Take up to n cells back off the end of the last line. Return the count. */ -int term_hist_pop_tail_cells(struct hist *h, int n, struct cell *out, struct gstore *g); +int wsap_vtcore_hist_pop_tail_cells(struct hist *h, int n, struct cell *out, struct gstore *g); static inline uint64_t hist_first_id(const struct hist *h) { @@ -269,29 +269,29 @@ static inline bool hist_is_open(const struct hist *h) return h->head != h->tail && (h->ring[(h->head - 1) & h->ring_mask].flags & HLINE_OPEN); } -uint64_t term_hist_line_cells(const struct hist *h, uint64_t id); -uint64_t term_hist_line_wide(const struct hist *h, uint64_t id); -uint8_t term_hist_line_flags(const struct hist *h, uint64_t id); -int term_hist_line_rows(const struct hist *h, uint64_t id, int cols); -int term_hist_decode_segment(const struct hist *h, uint64_t id, int seg, int cols, +uint64_t wsap_vtcore_hist_line_cells(const struct hist *h, uint64_t id); +uint64_t wsap_vtcore_hist_line_wide(const struct hist *h, uint64_t id); +uint8_t wsap_vtcore_hist_line_flags(const struct hist *h, uint64_t id); +int wsap_vtcore_hist_line_rows(const struct hist *h, uint64_t id, int cols); +int wsap_vtcore_hist_decode_segment(const struct hist *h, uint64_t id, int seg, int cols, struct cell *out, struct gstore *g); -int term_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, int count, int cols, +int wsap_vtcore_hist_decode_segments(const struct hist *h, uint64_t id, int start_seg, int count, int cols, struct cell *out, int *lens, struct gstore *g); -uint64_t term_hist_segment_cell(const struct hist *h, uint64_t id, int seg, int cols); -int term_hist_cell_segment(const struct hist *h, uint64_t id, uint64_t cell, int cols); +uint64_t wsap_vtcore_hist_segment_cell(const struct hist *h, uint64_t id, int seg, int cols); +int wsap_vtcore_hist_cell_segment(const struct hist *h, uint64_t id, uint64_t cell, int cols); -void term_hist_mark_links(const struct hist *h, void (*mark)(void *ud, uint16_t link), void *ud); +void wsap_vtcore_hist_mark_links(const struct hist *h, void (*mark)(void *ud, uint16_t link), void *ud); /* Set the width that pushed rows have. It costs O(1): the stored row counts * become stale. Reads count them without changing the history. */ -void term_hist_set_width(struct hist *h, int cols); +void wsap_vtcore_hist_set_width(struct hist *h, int cols); /* Rows of all retained lines at cols. */ -uint64_t term_hist_rows(const struct hist *h, int cols); -uint64_t term_hist_line_estimate(const struct hist *h, uint64_t id, int cols); -uint64_t term_hist_estimated_rows(const struct hist *h, int cols); -void term_hist_prepare_rows(struct hist *h, int cols); -void term_hist_refine_rows(struct hist *h, uint64_t id, int cols, int rows); +uint64_t wsap_vtcore_hist_rows(const struct hist *h, int cols); +uint64_t wsap_vtcore_hist_line_estimate(const struct hist *h, uint64_t id, int cols); +uint64_t wsap_vtcore_hist_estimated_rows(const struct hist *h, int cols); +void wsap_vtcore_hist_prepare_rows(struct hist *h, int cols); +void wsap_vtcore_hist_refine_rows(struct hist *h, uint64_t id, int cols, int rows); #endif diff --git a/src/hist_view.c b/src/hist_view.c index 362e995..1cbbb07 100644 --- a/src/hist_view.c +++ b/src/hist_view.c @@ -3,7 +3,7 @@ #include <stdlib.h> #include <string.h> -void term_hist_view_free(struct hist_view *v) +void wsap_vtcore_hist_view_free(struct hist_view *v) { if (!v) return; @@ -37,10 +37,10 @@ static bool current(const struct hist_view *v, const struct hist *h, int cols) return v->index_cols == cols && v->epoch == h->index_epoch && v->first_id == hist_first_id(h) && v->end_id == hist_end_id(h) && v->head == h->head && v->tail == h->tail && - v->last_cells == (h->lines ? term_hist_line_cells(h, hist_end_id(h) - 1) : 0); + v->last_cells == (h->lines ? wsap_vtcore_hist_line_cells(h, hist_end_id(h) - 1) : 0); } -bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) +bool wsap_vtcore_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) { if (current(v, h, cols)) return true; @@ -54,7 +54,7 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) if (h->lines > v->cap || !v->cap) { if (h->lines > (UINT32_C(1) << 31)) return false; - uint32_t cap = term_next_pow2_32(h->lines < 16 ? 16 : h->lines); + uint32_t cap = wsap_vtcore_next_pow2_32(h->lines < 16 ? 16 : h->lines); if (cap == UINT32_MAX) return false; uint64_t *tree = calloc((size_t)cap + 1, sizeof(*tree)); @@ -75,7 +75,7 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) memset(v->counts, 0, (size_t)v->cap * sizeof(*v->counts)); memset(v->fenwick, 0, ((size_t)v->cap + 1) * sizeof(*v->fenwick)); for (uint64_t id = first; id < end; id++) - v->counts[(uint32_t)id & (v->cap - 1)] = (uint32_t)term_hist_line_estimate(h, id, cols); + v->counts[(uint32_t)id & (v->cap - 1)] = (uint32_t)wsap_vtcore_hist_line_estimate(h, id, cols); /* Build all tree nodes in one pass. */ for (uint32_t i = 1; i <= v->cap; i++) { v->fenwick[i] += v->counts[i - 1]; @@ -88,10 +88,10 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) for (uint64_t id = v->first_id; id < first; id++) set_count(v, id, 0); /* Only the old final line can grow or close. */ - if (v->end_id > first && term_hist_line_cells(h, v->end_id - 1) != v->last_cells) - set_count(v, v->end_id - 1, (uint32_t)term_hist_line_estimate(h, v->end_id - 1, cols)); + if (v->end_id > first && wsap_vtcore_hist_line_cells(h, v->end_id - 1) != v->last_cells) + set_count(v, v->end_id - 1, (uint32_t)wsap_vtcore_hist_line_estimate(h, v->end_id - 1, cols)); for (uint64_t id = v->end_id; id < end; id++) - set_count(v, id, (uint32_t)term_hist_line_estimate(h, id, cols)); + set_count(v, id, (uint32_t)wsap_vtcore_hist_line_estimate(h, id, cols)); } v->first_id = first; v->end_id = end; @@ -99,7 +99,7 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols) v->epoch = h->index_epoch; v->head = h->head; v->tail = h->tail; - v->last_cells = h->lines ? term_hist_line_cells(h, end - 1) : 0; + v->last_cells = h->lines ? wsap_vtcore_hist_line_cells(h, end - 1) : 0; return true; } @@ -110,14 +110,14 @@ static uint64_t anchor_extra(const struct hist_view *v, const struct hist *h, in if (!v->anchor.active || id < hist_first_id(h) || id >= hist_end_id(h)) return 0; uint64_t estimated = current(v, h, cols) ? v->counts[(uint32_t)id & (v->cap - 1)] : - term_hist_line_estimate(h, id, cols); - uint64_t exact = (uint64_t)term_hist_line_rows(h, id, cols); + wsap_vtcore_hist_line_estimate(h, id, cols); + uint64_t exact = (uint64_t)wsap_vtcore_hist_line_rows(h, id, cols); return exact > estimated ? exact - estimated : 0; } -uint64_t term_hist_view_rows(const struct hist_view *v, const struct hist *h, int cols) +uint64_t wsap_vtcore_hist_view_rows(const struct hist_view *v, const struct hist *h, int cols) { - uint64_t rows = current(v, h, cols) ? v->total_rows : term_hist_estimated_rows(h, cols); + uint64_t rows = current(v, h, cols) ? v->total_rows : wsap_vtcore_hist_estimated_rows(h, cols); return rows + anchor_extra(v, h, cols); } @@ -149,7 +149,7 @@ static uint32_t select_slot(const struct hist_view *v, uint64_t row, int *seg) return slot; } -bool term_hist_view_find_row(const struct hist_view *v, const struct hist *h, int row, +bool wsap_vtcore_hist_view_find_row(const struct hist_view *v, const struct hist *h, int row, int cols, uint64_t *id, int *seg) { if (!current(v, h, cols)) { @@ -157,7 +157,7 @@ bool term_hist_view_find_row(const struct hist_view *v, const struct hist *h, in return false; uint64_t target = (uint64_t)row; for (uint64_t line = hist_first_id(h); line < hist_end_id(h); line++) { - uint64_t count = term_hist_line_estimate(h, line, cols); + uint64_t count = wsap_vtcore_hist_line_estimate(h, line, cols); if (target < count) { *id = line; *seg = (int)target; @@ -183,56 +183,56 @@ static int rows_as_int(uint64_t rows) return rows > INT_MAX ? INT_MAX : (int)rows; } -int term_hist_view_scroll_offset(const struct hist_view *v, const struct hist *h, int cols) +int wsap_vtcore_hist_view_scroll_offset(const struct hist_view *v, const struct hist *h, int cols) { if (!v->anchor.active || !h->lines) return 0; uint64_t id = v->anchor.line_id; if (id < hist_first_id(h)) - return rows_as_int(term_hist_view_rows(v, h, cols)); + return rows_as_int(wsap_vtcore_hist_view_rows(v, h, cols)); if (id >= hist_end_id(h)) return 0; int seg = v->cols == cols ? (int)v->anchor.seg : - term_hist_cell_segment(h, id, v->anchor.cell, cols); + wsap_vtcore_hist_cell_segment(h, id, v->anchor.cell, cols); uint64_t rows = 0; if (current(v, h, cols)) rows = v->total_rows - before(v, id); else for (; id < hist_end_id(h); id++) - rows += term_hist_line_estimate(h, id, cols); + rows += wsap_vtcore_hist_line_estimate(h, id, cols); rows += anchor_extra(v, h, cols); return rows > (uint64_t)seg ? rows_as_int(rows - seg) : 0; } -void term_hist_view_note_push(struct hist_view *v, const struct hist *h, int cols) +void wsap_vtcore_hist_view_note_push(struct hist_view *v, const struct hist *h, int cols) { if (!v->anchor.active) return; if (v->anchor.line_id < hist_first_id(h)) v->anchor = (struct view_anchor){ .line_id = hist_first_id(h), .active = true }; - uint64_t base = term_hist_segment_cell(h, v->anchor.line_id, 0, cols); + uint64_t base = wsap_vtcore_hist_segment_cell(h, v->anchor.line_id, 0, cols); if (v->anchor.base_cell != base) { if (v->anchor.cell < base) v->anchor.cell = base; - v->anchor.seg = (uint32_t)term_hist_cell_segment(h, v->anchor.line_id, v->anchor.cell, cols); + v->anchor.seg = (uint32_t)wsap_vtcore_hist_cell_segment(h, v->anchor.line_id, v->anchor.cell, cols); v->anchor.base_cell = base; } } -void term_hist_view_rewrap(struct hist_view *v, const struct hist *h, int cols) +void wsap_vtcore_hist_view_rewrap(struct hist_view *v, const struct hist *h, int cols) { - term_hist_view_note_push(v, h, cols); + wsap_vtcore_hist_view_note_push(v, h, cols); if (v->anchor.active) { if (v->anchor.line_id >= hist_end_id(h)) v->anchor = (struct view_anchor){0}; else - v->anchor.seg = (uint32_t)term_hist_cell_segment(h, v->anchor.line_id, v->anchor.cell, cols); + v->anchor.seg = (uint32_t)wsap_vtcore_hist_cell_segment(h, v->anchor.line_id, v->anchor.cell, cols); } v->cols = cols; v->index_cols = 0; } -void term_hist_view_scroll_to(struct hist_view *v, const struct hist *h, int cols, +void wsap_vtcore_hist_view_scroll_to(struct hist_view *v, const struct hist *h, int cols, struct line_pos screen_top, int offset) { (void)screen_top; @@ -241,22 +241,22 @@ void term_hist_view_scroll_to(struct hist_view *v, const struct hist *h, int col return; } /* Allocation failure uses the read-only history walk. */ - uint64_t total = term_hist_view_rows(v, h, cols); + uint64_t total = wsap_vtcore_hist_view_rows(v, h, cols); if ((uint64_t)offset > total) offset = rows_as_int(total); uint64_t id; int seg; uint64_t row = total - offset; - if (row > INT_MAX || !term_hist_view_find_row(v, h, (int)row, cols, &id, &seg)) + if (row > INT_MAX || !wsap_vtcore_hist_view_find_row(v, h, (int)row, cols, &id, &seg)) return; v->anchor = (struct view_anchor){ .line_id = id, .seg = (uint32_t)seg, - .cell = term_hist_segment_cell(h, id, seg, cols), - .base_cell = term_hist_segment_cell(h, id, 0, cols), .active = true }; + .cell = wsap_vtcore_hist_segment_cell(h, id, seg, cols), + .base_cell = wsap_vtcore_hist_segment_cell(h, id, 0, cols), .active = true }; v->cols = cols; } /* Relative movement visits only the logical lines it crosses. */ -void term_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, +void wsap_vtcore_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, struct line_pos screen_top, int lines) { (void)screen_top; @@ -270,22 +270,22 @@ void term_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, id = hist_first_id(h); if (id >= hist_end_id(h)) id = hist_end_id(h) - 1; - seg = v->cols == cols ? (int64_t)v->anchor.seg : term_hist_cell_segment(h, id, v->anchor.cell, cols); + seg = v->cols == cols ? (int64_t)v->anchor.seg : wsap_vtcore_hist_cell_segment(h, id, v->anchor.cell, cols); } else { if (lines < 0) return; id = hist_end_id(h) - 1; - seg = term_hist_line_rows(h, id, cols); + seg = wsap_vtcore_hist_line_rows(h, id, cols); } seg -= (int64_t)lines; if (lines > 0) { while (seg < 0 && id > hist_first_id(h)) - seg += term_hist_line_rows(h, --id, cols); + seg += wsap_vtcore_hist_line_rows(h, --id, cols); if (seg < 0) seg = 0; } else { for (;;) { - int count = term_hist_line_rows(h, id, cols); + int count = wsap_vtcore_hist_line_rows(h, id, cols); if (seg < count) break; seg -= count; @@ -296,13 +296,13 @@ void term_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, } } v->anchor = (struct view_anchor){ .line_id = id, .seg = (uint32_t)seg, - .cell = term_hist_segment_cell(h, id, (int)seg, cols), - .base_cell = term_hist_segment_cell(h, id, 0, cols), .active = true }; + .cell = wsap_vtcore_hist_segment_cell(h, id, (int)seg, cols), + .base_cell = wsap_vtcore_hist_segment_cell(h, id, 0, cols), .active = true }; v->cols = cols; } /* A viewport walks exact segments from its anchor, never an estimated row. */ -bool term_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int cols, +bool wsap_vtcore_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int cols, int screen_rows, struct line_pos screen_top, int y, struct hist_view_pos *pos) { @@ -310,14 +310,14 @@ bool term_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int if (v->anchor.active && h->lines) { uint64_t id = v->anchor.line_id; int seg = v->cols == cols ? (int)v->anchor.seg : - term_hist_cell_segment(h, id, v->anchor.cell, cols); + wsap_vtcore_hist_cell_segment(h, id, v->anchor.cell, cols); if (id < hist_first_id(h)) { id = hist_first_id(h); seg = 0; } int64_t target = (int64_t)seg + y; while (id < hist_end_id(h)) { - int count = term_hist_line_rows(h, id, cols); + int count = wsap_vtcore_hist_line_rows(h, id, cols); if (target < count) { pos->id = id; pos->seg = (int)target; @@ -334,7 +334,7 @@ bool term_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int } /* Wide line counts become exact when the viewport visits them. */ -void term_hist_view_refine(struct hist_view *v, struct hist *h, int cols, int rows) +void wsap_vtcore_hist_view_refine(struct hist_view *v, struct hist *h, int cols, int rows) { if (!v->anchor.active || !current(v, h, cols)) return; @@ -346,9 +346,9 @@ void term_hist_view_refine(struct hist_view *v, struct hist *h, int cols, int ro seg = 0; } for (; id < hist_end_id(h) && remaining > 0; id++) { - int count = term_hist_line_rows(h, id, cols); + int count = wsap_vtcore_hist_line_rows(h, id, cols); set_count(v, id, (uint32_t)count); - term_hist_refine_rows(h, id, cols, count); + wsap_vtcore_hist_refine_rows(h, id, cols, count); remaining -= count - seg; seg = 0; } diff --git a/src/hist_view.h b/src/hist_view.h index 61b4e89..165ab0b 100644 --- a/src/hist_view.h +++ b/src/hist_view.h @@ -1,5 +1,5 @@ -#ifndef TERM_HIST_VIEW_H -#define TERM_HIST_VIEW_H +#ifndef WSAP_VTCORE_HIST_VIEW_H +#define WSAP_VTCORE_HIST_VIEW_H #include "hist.h" @@ -30,20 +30,20 @@ struct hist_view { int index_cols; }; -void term_hist_view_free(struct hist_view *v); +void wsap_vtcore_hist_view_free(struct hist_view *v); /* Update the index during snapshot capture. Reads do not change it. */ -bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols); -void term_hist_view_refine(struct hist_view *v, struct hist *h, int cols, int rows); -uint64_t term_hist_view_rows(const struct hist_view *v, const struct hist *h, int cols); -bool term_hist_view_find_row(const struct hist_view *v, const struct hist *h, int row, +bool wsap_vtcore_hist_view_sync(struct hist_view *v, const struct hist *h, int cols); +void wsap_vtcore_hist_view_refine(struct hist_view *v, struct hist *h, int cols, int rows); +uint64_t wsap_vtcore_hist_view_rows(const struct hist_view *v, const struct hist *h, int cols); +bool wsap_vtcore_hist_view_find_row(const struct hist_view *v, const struct hist *h, int row, int cols, uint64_t *id, int *seg); /* Read the offset from the anchor at the current width. */ -int term_hist_view_scroll_offset(const struct hist_view *v, const struct hist *h, int cols); -void term_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, +int wsap_vtcore_hist_view_scroll_offset(const struct hist_view *v, const struct hist *h, int cols); +void wsap_vtcore_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols, struct line_pos screen_top, int lines); -void term_hist_view_scroll_to(struct hist_view *v, const struct hist *h, int cols, +void wsap_vtcore_hist_view_scroll_to(struct hist_view *v, const struct hist *h, int cols, struct line_pos screen_top, int offset); struct hist_view_pos { @@ -53,10 +53,10 @@ struct hist_view_pos { }; /* Clamp an evicted anchor. This does not update the index on the write path. */ -void term_hist_view_note_push(struct hist_view *v, const struct hist *h, int cols); -void term_hist_view_rewrap(struct hist_view *v, const struct hist *h, int cols); +void wsap_vtcore_hist_view_note_push(struct hist_view *v, const struct hist *h, int cols); +void wsap_vtcore_hist_view_rewrap(struct hist_view *v, const struct hist *h, int cols); -bool term_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int cols, +bool wsap_vtcore_hist_view_row_pos(const struct hist_view *v, const struct hist *h, int cols, int screen_rows, struct line_pos screen_top, int y, struct hist_view_pos *pos); diff --git a/src/input.c b/src/input.c index 2f0cd5c..7f76bb7 100644 --- a/src/input.c +++ b/src/input.c @@ -1,4 +1,4 @@ -#include "term.h" +#include "wsap_vtcore.h" #include "unicode/utf8.h" #include <string.h> @@ -53,18 +53,18 @@ static inline void sb_u32(struct seqbuf *sb, uint32_t val) static inline void sb_utf8(struct seqbuf *sb, uint32_t cp) { char tmp[8]; - size_t n = (size_t)term_utf8_encode(cp, tmp); + size_t n = (size_t)wsap_vtcore_utf8_encode(cp, tmp); sb_bytes(sb, tmp, n); } -static struct term_input_result sb_result(const struct seqbuf *sb, const char *buf) +static struct wsap_vtcore_input_result sb_result(const struct seqbuf *sb, const char *buf) { if (sb->overflow) - return (struct term_input_result){ .status = TERM_INPUT_BUFFER_FULL }; + return (struct wsap_vtcore_input_result){ .status = WSAP_VTCORE_INPUT_BUFFER_FULL }; size_t len = (size_t)(sb->p - buf); - return (struct term_input_result){ - .status = len ? TERM_INPUT_BYTES : TERM_INPUT_CONSUMED, + return (struct wsap_vtcore_input_result){ + .status = len ? WSAP_VTCORE_INPUT_BYTES : WSAP_VTCORE_INPUT_CONSUMED, .len = len, }; } @@ -74,122 +74,122 @@ struct kitty_desc { char final; }; -static const struct kitty_desc kitty_desc[TERM_KEY_COUNT] = { - [TERM_KEY_RETURN] = { 13, 'u' }, - [TERM_KEY_BACKSPACE] = { 127, 'u' }, - [TERM_KEY_TAB] = { 9, 'u' }, - [TERM_KEY_ESCAPE] = { 27, 'u' }, - - [TERM_KEY_UP] = { 1, 'A' }, - [TERM_KEY_DOWN] = { 1, 'B' }, - [TERM_KEY_RIGHT] = { 1, 'C' }, - [TERM_KEY_LEFT] = { 1, 'D' }, - [TERM_KEY_HOME] = { 1, 'H' }, - [TERM_KEY_END] = { 1, 'F' }, - [TERM_KEY_PAGE_UP] = { 5, '~' }, - [TERM_KEY_PAGE_DOWN] = { 6, '~' }, - [TERM_KEY_INSERT] = { 2, '~' }, - [TERM_KEY_DELETE] = { 3, '~' }, - - [TERM_KEY_F1] = { 1, 'P' }, - [TERM_KEY_F2] = { 1, 'Q' }, - [TERM_KEY_F3] = { 13, '~' }, - [TERM_KEY_F4] = { 1, 'S' }, - [TERM_KEY_F5] = { 15, '~' }, - [TERM_KEY_F6] = { 17, '~' }, - [TERM_KEY_F7] = { 18, '~' }, - [TERM_KEY_F8] = { 19, '~' }, - [TERM_KEY_F9] = { 20, '~' }, - [TERM_KEY_F10] = { 21, '~' }, - [TERM_KEY_F11] = { 23, '~' }, - [TERM_KEY_F12] = { 24, '~' }, - [TERM_KEY_F13] = { 57376, 'u' }, - [TERM_KEY_F14] = { 57377, 'u' }, - [TERM_KEY_F15] = { 57378, 'u' }, - [TERM_KEY_F16] = { 57379, 'u' }, - [TERM_KEY_F17] = { 57380, 'u' }, - [TERM_KEY_F18] = { 57381, 'u' }, - [TERM_KEY_F19] = { 57382, 'u' }, - [TERM_KEY_F20] = { 57383, 'u' }, - [TERM_KEY_F21] = { 57384, 'u' }, - [TERM_KEY_F22] = { 57385, 'u' }, - [TERM_KEY_F23] = { 57386, 'u' }, - [TERM_KEY_F24] = { 57387, 'u' }, - [TERM_KEY_F25] = { 57388, 'u' }, - [TERM_KEY_F26] = { 57389, 'u' }, - [TERM_KEY_F27] = { 57390, 'u' }, - [TERM_KEY_F28] = { 57391, 'u' }, - [TERM_KEY_F29] = { 57392, 'u' }, - [TERM_KEY_F30] = { 57393, 'u' }, - [TERM_KEY_F31] = { 57394, 'u' }, - [TERM_KEY_F32] = { 57395, 'u' }, - [TERM_KEY_F33] = { 57396, 'u' }, - [TERM_KEY_F34] = { 57397, 'u' }, - [TERM_KEY_F35] = { 57398, 'u' }, - - [TERM_KEY_KP_0] = { 57399, 'u' }, - [TERM_KEY_KP_1] = { 57400, 'u' }, - [TERM_KEY_KP_2] = { 57401, 'u' }, - [TERM_KEY_KP_3] = { 57402, 'u' }, - [TERM_KEY_KP_4] = { 57403, 'u' }, - [TERM_KEY_KP_5] = { 57404, 'u' }, - [TERM_KEY_KP_6] = { 57405, 'u' }, - [TERM_KEY_KP_7] = { 57406, 'u' }, - [TERM_KEY_KP_8] = { 57407, 'u' }, - [TERM_KEY_KP_9] = { 57408, 'u' }, - [TERM_KEY_KP_DECIMAL] = { 57409, 'u' }, - [TERM_KEY_KP_DIVIDE] = { 57410, 'u' }, - [TERM_KEY_KP_MULTIPLY] = { 57411, 'u' }, - [TERM_KEY_KP_SUBTRACT] = { 57412, 'u' }, - [TERM_KEY_KP_ADD] = { 57413, 'u' }, - [TERM_KEY_KP_ENTER] = { 57414, 'u' }, - [TERM_KEY_KP_EQUAL] = { 57415, 'u' }, - [TERM_KEY_KP_SEPARATOR] = { 57416, 'u' }, - [TERM_KEY_KP_LEFT] = { 57417, 'u' }, - [TERM_KEY_KP_RIGHT] = { 57418, 'u' }, - [TERM_KEY_KP_UP] = { 57419, 'u' }, - [TERM_KEY_KP_DOWN] = { 57420, 'u' }, - [TERM_KEY_KP_PAGE_UP] = { 57421, 'u' }, - [TERM_KEY_KP_PAGE_DOWN] = { 57422, 'u' }, - [TERM_KEY_KP_HOME] = { 57423, 'u' }, - [TERM_KEY_KP_END] = { 57424, 'u' }, - [TERM_KEY_KP_INSERT] = { 57425, 'u' }, - [TERM_KEY_KP_DELETE] = { 57426, 'u' }, - [TERM_KEY_KP_BEGIN] = { 1, 'E' }, - - [TERM_KEY_CAPS_LOCK] = { 57358, 'u' }, - [TERM_KEY_SCROLL_LOCK] = { 57359, 'u' }, - [TERM_KEY_NUM_LOCK] = { 57360, 'u' }, - [TERM_KEY_PRINT_SCREEN] = { 57361, 'u' }, - [TERM_KEY_PAUSE] = { 57362, 'u' }, - [TERM_KEY_MENU] = { 57363, 'u' }, - - [TERM_KEY_MEDIA_PLAY] = { 57428, 'u' }, - [TERM_KEY_MEDIA_PAUSE] = { 57429, 'u' }, - [TERM_KEY_MEDIA_STOP] = { 57432, 'u' }, - [TERM_KEY_MEDIA_FORWARD] = { 57433, 'u' }, - [TERM_KEY_MEDIA_REWIND] = { 57434, 'u' }, - [TERM_KEY_MEDIA_NEXT] = { 57435, 'u' }, - [TERM_KEY_MEDIA_PREV] = { 57436, 'u' }, - [TERM_KEY_MEDIA_RECORD] = { 57437, 'u' }, - [TERM_KEY_VOLUME_DOWN] = { 57438, 'u' }, - [TERM_KEY_VOLUME_UP] = { 57439, 'u' }, - [TERM_KEY_MUTE] = { 57440, 'u' }, - - [TERM_KEY_LSHIFT] = { 57441, 'u' }, - [TERM_KEY_LCTRL] = { 57442, 'u' }, - [TERM_KEY_LALT] = { 57443, 'u' }, - [TERM_KEY_LSUPER] = { 57444, 'u' }, - [TERM_KEY_LHYPER] = { 57445, 'u' }, - [TERM_KEY_LMETA] = { 57446, 'u' }, - [TERM_KEY_RSHIFT] = { 57447, 'u' }, - [TERM_KEY_RCTRL] = { 57448, 'u' }, - [TERM_KEY_RALT] = { 57449, 'u' }, - [TERM_KEY_RSUPER] = { 57450, 'u' }, - [TERM_KEY_RHYPER] = { 57451, 'u' }, - [TERM_KEY_RMETA] = { 57452, 'u' }, - [TERM_KEY_ISO_LEVEL3_SHIFT] = { 57453, 'u' }, - [TERM_KEY_ISO_LEVEL5_SHIFT] = { 57454, 'u' }, +static const struct kitty_desc kitty_desc[WSAP_VTCORE_KEY_COUNT] = { + [WSAP_VTCORE_KEY_RETURN] = { 13, 'u' }, + [WSAP_VTCORE_KEY_BACKSPACE] = { 127, 'u' }, + [WSAP_VTCORE_KEY_TAB] = { 9, 'u' }, + [WSAP_VTCORE_KEY_ESCAPE] = { 27, 'u' }, + + [WSAP_VTCORE_KEY_UP] = { 1, 'A' }, + [WSAP_VTCORE_KEY_DOWN] = { 1, 'B' }, + [WSAP_VTCORE_KEY_RIGHT] = { 1, 'C' }, + [WSAP_VTCORE_KEY_LEFT] = { 1, 'D' }, + [WSAP_VTCORE_KEY_HOME] = { 1, 'H' }, + [WSAP_VTCORE_KEY_END] = { 1, 'F' }, + [WSAP_VTCORE_KEY_PAGE_UP] = { 5, '~' }, + [WSAP_VTCORE_KEY_PAGE_DOWN] = { 6, '~' }, + [WSAP_VTCORE_KEY_INSERT] = { 2, '~' }, + [WSAP_VTCORE_KEY_DELETE] = { 3, '~' }, + + [WSAP_VTCORE_KEY_F1] = { 1, 'P' }, + [WSAP_VTCORE_KEY_F2] = { 1, 'Q' }, + [WSAP_VTCORE_KEY_F3] = { 13, '~' }, + [WSAP_VTCORE_KEY_F4] = { 1, 'S' }, + [WSAP_VTCORE_KEY_F5] = { 15, '~' }, + [WSAP_VTCORE_KEY_F6] = { 17, '~' }, + [WSAP_VTCORE_KEY_F7] = { 18, '~' }, + [WSAP_VTCORE_KEY_F8] = { 19, '~' }, + [WSAP_VTCORE_KEY_F9] = { 20, '~' }, + [WSAP_VTCORE_KEY_F10] = { 21, '~' }, + [WSAP_VTCORE_KEY_F11] = { 23, '~' }, + [WSAP_VTCORE_KEY_F12] = { 24, '~' }, + [WSAP_VTCORE_KEY_F13] = { 57376, 'u' }, + [WSAP_VTCORE_KEY_F14] = { 57377, 'u' }, + [WSAP_VTCORE_KEY_F15] = { 57378, 'u' }, + [WSAP_VTCORE_KEY_F16] = { 57379, 'u' }, + [WSAP_VTCORE_KEY_F17] = { 57380, 'u' }, + [WSAP_VTCORE_KEY_F18] = { 57381, 'u' }, + [WSAP_VTCORE_KEY_F19] = { 57382, 'u' }, + [WSAP_VTCORE_KEY_F20] = { 57383, 'u' }, + [WSAP_VTCORE_KEY_F21] = { 57384, 'u' }, + [WSAP_VTCORE_KEY_F22] = { 57385, 'u' }, + [WSAP_VTCORE_KEY_F23] = { 57386, 'u' }, + [WSAP_VTCORE_KEY_F24] = { 57387, 'u' }, + [WSAP_VTCORE_KEY_F25] = { 57388, 'u' }, + [WSAP_VTCORE_KEY_F26] = { 57389, 'u' }, + [WSAP_VTCORE_KEY_F27] = { 57390, 'u' }, + [WSAP_VTCORE_KEY_F28] = { 57391, 'u' }, + [WSAP_VTCORE_KEY_F29] = { 57392, 'u' }, + [WSAP_VTCORE_KEY_F30] = { 57393, 'u' }, + [WSAP_VTCORE_KEY_F31] = { 57394, 'u' }, + [WSAP_VTCORE_KEY_F32] = { 57395, 'u' }, + [WSAP_VTCORE_KEY_F33] = { 57396, 'u' }, + [WSAP_VTCORE_KEY_F34] = { 57397, 'u' }, + [WSAP_VTCORE_KEY_F35] = { 57398, 'u' }, + + [WSAP_VTCORE_KEY_KP_0] = { 57399, 'u' }, + [WSAP_VTCORE_KEY_KP_1] = { 57400, 'u' }, + [WSAP_VTCORE_KEY_KP_2] = { 57401, 'u' }, + [WSAP_VTCORE_KEY_KP_3] = { 57402, 'u' }, + [WSAP_VTCORE_KEY_KP_4] = { 57403, 'u' }, + [WSAP_VTCORE_KEY_KP_5] = { 57404, 'u' }, + [WSAP_VTCORE_KEY_KP_6] = { 57405, 'u' }, + [WSAP_VTCORE_KEY_KP_7] = { 57406, 'u' }, + [WSAP_VTCORE_KEY_KP_8] = { 57407, 'u' }, + [WSAP_VTCORE_KEY_KP_9] = { 57408, 'u' }, + [WSAP_VTCORE_KEY_KP_DECIMAL] = { 57409, 'u' }, + [WSAP_VTCORE_KEY_KP_DIVIDE] = { 57410, 'u' }, + [WSAP_VTCORE_KEY_KP_MULTIPLY] = { 57411, 'u' }, + [WSAP_VTCORE_KEY_KP_SUBTRACT] = { 57412, 'u' }, + [WSAP_VTCORE_KEY_KP_ADD] = { 57413, 'u' }, + [WSAP_VTCORE_KEY_KP_ENTER] = { 57414, 'u' }, + [WSAP_VTCORE_KEY_KP_EQUAL] = { 57415, 'u' }, + [WSAP_VTCORE_KEY_KP_SEPARATOR] = { 57416, 'u' }, + [WSAP_VTCORE_KEY_KP_LEFT] = { 57417, 'u' }, + [WSAP_VTCORE_KEY_KP_RIGHT] = { 57418, 'u' }, + [WSAP_VTCORE_KEY_KP_UP] = { 57419, 'u' }, + [WSAP_VTCORE_KEY_KP_DOWN] = { 57420, 'u' }, + [WSAP_VTCORE_KEY_KP_PAGE_UP] = { 57421, 'u' }, + [WSAP_VTCORE_KEY_KP_PAGE_DOWN] = { 57422, 'u' }, + [WSAP_VTCORE_KEY_KP_HOME] = { 57423, 'u' }, + [WSAP_VTCORE_KEY_KP_END] = { 57424, 'u' }, + [WSAP_VTCORE_KEY_KP_INSERT] = { 57425, 'u' }, + [WSAP_VTCORE_KEY_KP_DELETE] = { 57426, 'u' }, + [WSAP_VTCORE_KEY_KP_BEGIN] = { 1, 'E' }, + + [WSAP_VTCORE_KEY_CAPS_LOCK] = { 57358, 'u' }, + [WSAP_VTCORE_KEY_SCROLL_LOCK] = { 57359, 'u' }, + [WSAP_VTCORE_KEY_NUM_LOCK] = { 57360, 'u' }, + [WSAP_VTCORE_KEY_PRINT_SCREEN] = { 57361, 'u' }, + [WSAP_VTCORE_KEY_PAUSE] = { 57362, 'u' }, + [WSAP_VTCORE_KEY_MENU] = { 57363, 'u' }, + + [WSAP_VTCORE_KEY_MEDIA_PLAY] = { 57428, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_PAUSE] = { 57429, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_STOP] = { 57432, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_FORWARD] = { 57433, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_REWIND] = { 57434, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_NEXT] = { 57435, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_PREV] = { 57436, 'u' }, + [WSAP_VTCORE_KEY_MEDIA_RECORD] = { 57437, 'u' }, + [WSAP_VTCORE_KEY_VOLUME_DOWN] = { 57438, 'u' }, + [WSAP_VTCORE_KEY_VOLUME_UP] = { 57439, 'u' }, + [WSAP_VTCORE_KEY_MUTE] = { 57440, 'u' }, + + [WSAP_VTCORE_KEY_LSHIFT] = { 57441, 'u' }, + [WSAP_VTCORE_KEY_LCTRL] = { 57442, 'u' }, + [WSAP_VTCORE_KEY_LALT] = { 57443, 'u' }, + [WSAP_VTCORE_KEY_LSUPER] = { 57444, 'u' }, + [WSAP_VTCORE_KEY_LHYPER] = { 57445, 'u' }, + [WSAP_VTCORE_KEY_LMETA] = { 57446, 'u' }, + [WSAP_VTCORE_KEY_RSHIFT] = { 57447, 'u' }, + [WSAP_VTCORE_KEY_RCTRL] = { 57448, 'u' }, + [WSAP_VTCORE_KEY_RALT] = { 57449, 'u' }, + [WSAP_VTCORE_KEY_RSUPER] = { 57450, 'u' }, + [WSAP_VTCORE_KEY_RHYPER] = { 57451, 'u' }, + [WSAP_VTCORE_KEY_RMETA] = { 57452, 'u' }, + [WSAP_VTCORE_KEY_ISO_LEVEL3_SHIFT] = { 57453, 'u' }, + [WSAP_VTCORE_KEY_ISO_LEVEL5_SHIFT] = { 57454, 'u' }, }; struct legacy_desc { @@ -197,61 +197,61 @@ struct legacy_desc { char final; bool app_cursor; char keypad_ss3; - enum term_key equiv; + enum wsap_vtcore_key equiv; }; -static const struct legacy_desc legacy_desc[TERM_KEY_COUNT] = { - [TERM_KEY_UP] = { .tilde = 0, .final = 'A', .app_cursor = true }, - [TERM_KEY_DOWN] = { .tilde = 0, .final = 'B', .app_cursor = true }, - [TERM_KEY_RIGHT] = { .tilde = 0, .final = 'C', .app_cursor = true }, - [TERM_KEY_LEFT] = { .tilde = 0, .final = 'D', .app_cursor = true }, - [TERM_KEY_HOME] = { .tilde = 0, .final = 'H', .app_cursor = true }, - [TERM_KEY_END] = { .tilde = 0, .final = 'F', .app_cursor = true }, - [TERM_KEY_PAGE_UP] = { .tilde = 5, .final = '~' }, - [TERM_KEY_PAGE_DOWN] = { .tilde = 6, .final = '~' }, - [TERM_KEY_INSERT] = { .tilde = 2, .final = '~' }, - [TERM_KEY_DELETE] = { .tilde = 3, .final = '~' }, - - [TERM_KEY_F1] = { .tilde = 0, .final = 'P' }, - [TERM_KEY_F2] = { .tilde = 0, .final = 'Q' }, - [TERM_KEY_F3] = { .tilde = 0, .final = 'R' }, - [TERM_KEY_F4] = { .tilde = 0, .final = 'S' }, - [TERM_KEY_F5] = { .tilde = 15, .final = '~' }, - [TERM_KEY_F6] = { .tilde = 17, .final = '~' }, - [TERM_KEY_F7] = { .tilde = 18, .final = '~' }, - [TERM_KEY_F8] = { .tilde = 19, .final = '~' }, - [TERM_KEY_F9] = { .tilde = 20, .final = '~' }, - [TERM_KEY_F10] = { .tilde = 21, .final = '~' }, - [TERM_KEY_F11] = { .tilde = 23, .final = '~' }, - [TERM_KEY_F12] = { .tilde = 24, .final = '~' }, - - [TERM_KEY_KP_0] = { .keypad_ss3 = 'p' }, - [TERM_KEY_KP_1] = { .keypad_ss3 = 'q' }, - [TERM_KEY_KP_2] = { .keypad_ss3 = 'r' }, - [TERM_KEY_KP_3] = { .keypad_ss3 = 's' }, - [TERM_KEY_KP_4] = { .keypad_ss3 = 't' }, - [TERM_KEY_KP_5] = { .keypad_ss3 = 'u' }, - [TERM_KEY_KP_6] = { .keypad_ss3 = 'v' }, - [TERM_KEY_KP_7] = { .keypad_ss3 = 'w' }, - [TERM_KEY_KP_8] = { .keypad_ss3 = 'x' }, - [TERM_KEY_KP_9] = { .keypad_ss3 = 'y' }, - [TERM_KEY_KP_DECIMAL] = { .keypad_ss3 = 'n' }, - [TERM_KEY_KP_DIVIDE] = { .keypad_ss3 = 'o' }, - [TERM_KEY_KP_MULTIPLY] = { .keypad_ss3 = 'j' }, - [TERM_KEY_KP_SUBTRACT] = { .keypad_ss3 = 'm' }, - [TERM_KEY_KP_ADD] = { .keypad_ss3 = 'k' }, - [TERM_KEY_KP_ENTER] = { .keypad_ss3 = 'M', .equiv = TERM_KEY_RETURN }, - [TERM_KEY_KP_LEFT] = { .equiv = TERM_KEY_LEFT }, - [TERM_KEY_KP_RIGHT] = { .equiv = TERM_KEY_RIGHT }, - [TERM_KEY_KP_UP] = { .equiv = TERM_KEY_UP }, - [TERM_KEY_KP_DOWN] = { .equiv = TERM_KEY_DOWN }, - [TERM_KEY_KP_PAGE_UP] = { .equiv = TERM_KEY_PAGE_UP }, - [TERM_KEY_KP_PAGE_DOWN] = { .equiv = TERM_KEY_PAGE_DOWN }, - [TERM_KEY_KP_HOME] = { .equiv = TERM_KEY_HOME }, - [TERM_KEY_KP_END] = { .equiv = TERM_KEY_END }, - [TERM_KEY_KP_INSERT] = { .equiv = TERM_KEY_INSERT }, - [TERM_KEY_KP_DELETE] = { .equiv = TERM_KEY_DELETE }, - [TERM_KEY_KP_BEGIN] = { .tilde = 0, .final = 'E' }, +static const struct legacy_desc legacy_desc[WSAP_VTCORE_KEY_COUNT] = { + [WSAP_VTCORE_KEY_UP] = { .tilde = 0, .final = 'A', .app_cursor = true }, + [WSAP_VTCORE_KEY_DOWN] = { .tilde = 0, .final = 'B', .app_cursor = true }, + [WSAP_VTCORE_KEY_RIGHT] = { .tilde = 0, .final = 'C', .app_cursor = true }, + [WSAP_VTCORE_KEY_LEFT] = { .tilde = 0, .final = 'D', .app_cursor = true }, + [WSAP_VTCORE_KEY_HOME] = { .tilde = 0, .final = 'H', .app_cursor = true }, + [WSAP_VTCORE_KEY_END] = { .tilde = 0, .final = 'F', .app_cursor = true }, + [WSAP_VTCORE_KEY_PAGE_UP] = { .tilde = 5, .final = '~' }, + [WSAP_VTCORE_KEY_PAGE_DOWN] = { .tilde = 6, .final = '~' }, + [WSAP_VTCORE_KEY_INSERT] = { .tilde = 2, .final = '~' }, + [WSAP_VTCORE_KEY_DELETE] = { .tilde = 3, .final = '~' }, + + [WSAP_VTCORE_KEY_F1] = { .tilde = 0, .final = 'P' }, + [WSAP_VTCORE_KEY_F2] = { .tilde = 0, .final = 'Q' }, + [WSAP_VTCORE_KEY_F3] = { .tilde = 0, .final = 'R' }, + [WSAP_VTCORE_KEY_F4] = { .tilde = 0, .final = 'S' }, + [WSAP_VTCORE_KEY_F5] = { .tilde = 15, .final = '~' }, + [WSAP_VTCORE_KEY_F6] = { .tilde = 17, .final = '~' }, + [WSAP_VTCORE_KEY_F7] = { .tilde = 18, .final = '~' }, + [WSAP_VTCORE_KEY_F8] = { .tilde = 19, .final = '~' }, + [WSAP_VTCORE_KEY_F9] = { .tilde = 20, .final = '~' }, + [WSAP_VTCORE_KEY_F10] = { .tilde = 21, .final = '~' }, + [WSAP_VTCORE_KEY_F11] = { .tilde = 23, .final = '~' }, + [WSAP_VTCORE_KEY_F12] = { .tilde = 24, .final = '~' }, + + [WSAP_VTCORE_KEY_KP_0] = { .keypad_ss3 = 'p' }, + [WSAP_VTCORE_KEY_KP_1] = { .keypad_ss3 = 'q' }, + [WSAP_VTCORE_KEY_KP_2] = { .keypad_ss3 = 'r' }, + [WSAP_VTCORE_KEY_KP_3] = { .keypad_ss3 = 's' }, + [WSAP_VTCORE_KEY_KP_4] = { .keypad_ss3 = 't' }, + [WSAP_VTCORE_KEY_KP_5] = { .keypad_ss3 = 'u' }, + [WSAP_VTCORE_KEY_KP_6] = { .keypad_ss3 = 'v' }, + [WSAP_VTCORE_KEY_KP_7] = { .keypad_ss3 = 'w' }, + [WSAP_VTCORE_KEY_KP_8] = { .keypad_ss3 = 'x' }, + [WSAP_VTCORE_KEY_KP_9] = { .keypad_ss3 = 'y' }, + [WSAP_VTCORE_KEY_KP_DECIMAL] = { .keypad_ss3 = 'n' }, + [WSAP_VTCORE_KEY_KP_DIVIDE] = { .keypad_ss3 = 'o' }, + [WSAP_VTCORE_KEY_KP_MULTIPLY] = { .keypad_ss3 = 'j' }, + [WSAP_VTCORE_KEY_KP_SUBTRACT] = { .keypad_ss3 = 'm' }, + [WSAP_VTCORE_KEY_KP_ADD] = { .keypad_ss3 = 'k' }, + [WSAP_VTCORE_KEY_KP_ENTER] = { .keypad_ss3 = 'M', .equiv = WSAP_VTCORE_KEY_RETURN }, + [WSAP_VTCORE_KEY_KP_LEFT] = { .equiv = WSAP_VTCORE_KEY_LEFT }, + [WSAP_VTCORE_KEY_KP_RIGHT] = { .equiv = WSAP_VTCORE_KEY_RIGHT }, + [WSAP_VTCORE_KEY_KP_UP] = { .equiv = WSAP_VTCORE_KEY_UP }, + [WSAP_VTCORE_KEY_KP_DOWN] = { .equiv = WSAP_VTCORE_KEY_DOWN }, + [WSAP_VTCORE_KEY_KP_PAGE_UP] = { .equiv = WSAP_VTCORE_KEY_PAGE_UP }, + [WSAP_VTCORE_KEY_KP_PAGE_DOWN] = { .equiv = WSAP_VTCORE_KEY_PAGE_DOWN }, + [WSAP_VTCORE_KEY_KP_HOME] = { .equiv = WSAP_VTCORE_KEY_HOME }, + [WSAP_VTCORE_KEY_KP_END] = { .equiv = WSAP_VTCORE_KEY_END }, + [WSAP_VTCORE_KEY_KP_INSERT] = { .equiv = WSAP_VTCORE_KEY_INSERT }, + [WSAP_VTCORE_KEY_KP_DELETE] = { .equiv = WSAP_VTCORE_KEY_DELETE }, + [WSAP_VTCORE_KEY_KP_BEGIN] = { .tilde = 0, .final = 'E' }, }; enum input_mod_key { @@ -268,42 +268,42 @@ enum input_mod_key { struct mod_desc { enum input_mod_key group; - enum term_key partner; + enum wsap_vtcore_key partner; }; -static const struct mod_desc mod_desc[TERM_KEY_COUNT] = { - [TERM_KEY_LSHIFT] = { MOD_KEY_SHIFT, TERM_KEY_RSHIFT }, - [TERM_KEY_RSHIFT] = { MOD_KEY_SHIFT, TERM_KEY_LSHIFT }, - [TERM_KEY_LCTRL] = { MOD_KEY_CTRL, TERM_KEY_RCTRL }, - [TERM_KEY_RCTRL] = { MOD_KEY_CTRL, TERM_KEY_LCTRL }, - [TERM_KEY_LALT] = { MOD_KEY_ALT, TERM_KEY_RALT }, - [TERM_KEY_RALT] = { MOD_KEY_ALT, TERM_KEY_LALT }, - [TERM_KEY_LSUPER] = { MOD_KEY_SUPER, TERM_KEY_RSUPER }, - [TERM_KEY_RSUPER] = { MOD_KEY_SUPER, TERM_KEY_LSUPER }, - [TERM_KEY_LHYPER] = { MOD_KEY_HYPER, TERM_KEY_RHYPER }, - [TERM_KEY_RHYPER] = { MOD_KEY_HYPER, TERM_KEY_LHYPER }, - [TERM_KEY_LMETA] = { MOD_KEY_META, TERM_KEY_RMETA }, - [TERM_KEY_RMETA] = { MOD_KEY_META, TERM_KEY_LMETA }, - [TERM_KEY_ISO_LEVEL3_SHIFT] = { MOD_KEY_ISO3, TERM_KEY_NONE }, - [TERM_KEY_ISO_LEVEL5_SHIFT] = { MOD_KEY_ISO5, TERM_KEY_NONE }, +static const struct mod_desc mod_desc[WSAP_VTCORE_KEY_COUNT] = { + [WSAP_VTCORE_KEY_LSHIFT] = { MOD_KEY_SHIFT, WSAP_VTCORE_KEY_RSHIFT }, + [WSAP_VTCORE_KEY_RSHIFT] = { MOD_KEY_SHIFT, WSAP_VTCORE_KEY_LSHIFT }, + [WSAP_VTCORE_KEY_LCTRL] = { MOD_KEY_CTRL, WSAP_VTCORE_KEY_RCTRL }, + [WSAP_VTCORE_KEY_RCTRL] = { MOD_KEY_CTRL, WSAP_VTCORE_KEY_LCTRL }, + [WSAP_VTCORE_KEY_LALT] = { MOD_KEY_ALT, WSAP_VTCORE_KEY_RALT }, + [WSAP_VTCORE_KEY_RALT] = { MOD_KEY_ALT, WSAP_VTCORE_KEY_LALT }, + [WSAP_VTCORE_KEY_LSUPER] = { MOD_KEY_SUPER, WSAP_VTCORE_KEY_RSUPER }, + [WSAP_VTCORE_KEY_RSUPER] = { MOD_KEY_SUPER, WSAP_VTCORE_KEY_LSUPER }, + [WSAP_VTCORE_KEY_LHYPER] = { MOD_KEY_HYPER, WSAP_VTCORE_KEY_RHYPER }, + [WSAP_VTCORE_KEY_RHYPER] = { MOD_KEY_HYPER, WSAP_VTCORE_KEY_LHYPER }, + [WSAP_VTCORE_KEY_LMETA] = { MOD_KEY_META, WSAP_VTCORE_KEY_RMETA }, + [WSAP_VTCORE_KEY_RMETA] = { MOD_KEY_META, WSAP_VTCORE_KEY_LMETA }, + [WSAP_VTCORE_KEY_ISO_LEVEL3_SHIFT] = { MOD_KEY_ISO3, WSAP_VTCORE_KEY_NONE }, + [WSAP_VTCORE_KEY_ISO_LEVEL5_SHIFT] = { MOD_KEY_ISO5, WSAP_VTCORE_KEY_NONE }, }; static const unsigned mod_group_input_mod[MOD_KEY_COUNT] = { - TERM_MOD_SHIFT, TERM_MOD_CTRL, TERM_MOD_ALT, - TERM_MOD_SUPER, TERM_MOD_HYPER, TERM_MOD_META, + WSAP_VTCORE_MOD_SHIFT, WSAP_VTCORE_MOD_CTRL, WSAP_VTCORE_MOD_ALT, + WSAP_VTCORE_MOD_SUPER, WSAP_VTCORE_MOD_HYPER, WSAP_VTCORE_MOD_META, 0, 0, }; -static inline bool key_is_modifier(enum term_key k) +static inline bool key_is_modifier(enum wsap_vtcore_key k) { - return (unsigned)k < TERM_KEY_COUNT && - (mod_desc[k].partner != TERM_KEY_NONE || + return (unsigned)k < WSAP_VTCORE_KEY_COUNT && + (mod_desc[k].partner != WSAP_VTCORE_KEY_NONE || mod_desc[k].group == MOD_KEY_ISO3 || mod_desc[k].group == MOD_KEY_ISO5); } -static unsigned effective_mods(const struct term_keyboard_state *s, - const struct term_key_event *ev) +static unsigned effective_mods(const struct wsap_vtcore_keyboard_state *s, + const struct wsap_vtcore_key_event *ev) { unsigned mods = ev->mods; if (!key_is_modifier(ev->key)) return mods; @@ -312,8 +312,8 @@ static unsigned effective_mods(const struct term_keyboard_state *s, if (d->group >= MOD_KEY_ISO3) return mods; unsigned bit = mod_group_input_mod[d->group]; - bool other_held = term_keyboard_key_down(s, d->partner); - if (ev->action != TERM_KEY_RELEASE || other_held) mods |= bit; + bool other_held = wsap_vtcore_keyboard_key_down(s, d->partner); + if (ev->action != WSAP_VTCORE_KEY_RELEASE || other_held) mods |= bit; else mods &= ~bit; return mods; } @@ -325,13 +325,13 @@ static void format_kitty(struct seqbuf *sb, uint32_t code, char final, { sb_bytes(sb, "\033[", 2); if (final != 'u' && final != '~' && code <= 1 && !shifted && !base && - !mods && !(flags & TERM_KEYBOARD_EVENT_TYPES) && !report_text) { + !mods && !(flags & WSAP_VTCORE_KEYBOARD_EVENT_TYPES) && !report_text) { sb_ch(sb, final); return; } sb_u32(sb, code); - if ((flags & TERM_KEYBOARD_ALTERNATE_KEYS) && !functional) { + if ((flags & WSAP_VTCORE_KEYBOARD_ALTERNATE_KEYS) && !functional) { if (shifted) { sb_ch(sb, ':'); sb_u32(sb, shifted); @@ -342,11 +342,11 @@ static void format_kitty(struct seqbuf *sb, uint32_t code, char final, sb_u32(sb, base); } } - if (mods || (flags & TERM_KEYBOARD_EVENT_TYPES) || report_text) { + if (mods || (flags & WSAP_VTCORE_KEYBOARD_EVENT_TYPES) || report_text) { sb_ch(sb, ';'); sb_u32(sb, mods + 1); } - if ((flags & TERM_KEYBOARD_EVENT_TYPES) && event != 1) { + if ((flags & WSAP_VTCORE_KEYBOARD_EVENT_TYPES) && event != 1) { sb_ch(sb, ':'); sb_u32(sb, event); } @@ -357,55 +357,55 @@ static void format_kitty(struct seqbuf *sb, uint32_t code, char final, sb_ch(sb, final); } -static bool encode_kitty(const struct term_keyboard_state *s, - const struct term_key_event *ev, - const struct term_modes *m, +static bool encode_kitty(const struct wsap_vtcore_keyboard_state *s, + const struct wsap_vtcore_key_event *ev, + const struct wsap_vtcore_modes *m, struct seqbuf *sb) { unsigned flags = m->keyboard; - unsigned event = ev->action == TERM_KEY_PRESS ? 1u : - ev->action == TERM_KEY_REPEAT ? 2u : 3u; - if (!flags) return ev->action == TERM_KEY_RELEASE; + unsigned event = ev->action == WSAP_VTCORE_KEY_PRESS ? 1u : + ev->action == WSAP_VTCORE_KEY_REPEAT ? 2u : 3u; + if (!flags) return ev->action == WSAP_VTCORE_KEY_RELEASE; const struct kitty_desc *d = &kitty_desc[ev->key]; bool functional = d->code != 0; char final = functional ? d->final : 'u'; - bool all = (flags & TERM_KEYBOARD_ALL_KEYS) != 0; + bool all = (flags & WSAP_VTCORE_KEYBOARD_ALL_KEYS) != 0; - bool lock = ev->key == TERM_KEY_CAPS_LOCK || ev->key == TERM_KEY_SCROLL_LOCK || - ev->key == TERM_KEY_NUM_LOCK; + bool lock = ev->key == WSAP_VTCORE_KEY_CAPS_LOCK || ev->key == WSAP_VTCORE_KEY_SCROLL_LOCK || + ev->key == WSAP_VTCORE_KEY_NUM_LOCK; if ((key_is_modifier(ev->key) || lock) && !all) return true; unsigned mods = effective_mods(s, ev); - if (ev->action == TERM_KEY_PRESS) { - if (ev->key == TERM_KEY_CAPS_LOCK) mods ^= TERM_MOD_CAPS; - if (ev->key == TERM_KEY_NUM_LOCK) mods ^= TERM_MOD_NUM; + if (ev->action == WSAP_VTCORE_KEY_PRESS) { + if (ev->key == WSAP_VTCORE_KEY_CAPS_LOCK) mods ^= WSAP_VTCORE_MOD_CAPS; + if (ev->key == WSAP_VTCORE_KEY_NUM_LOCK) mods ^= WSAP_VTCORE_MOD_NUM; } - bool plain_control = ev->key == TERM_KEY_RETURN || ev->key == TERM_KEY_TAB || - ev->key == TERM_KEY_BACKSPACE; - if (ev->action == TERM_KEY_RELEASE && - (!(flags & TERM_KEYBOARD_EVENT_TYPES) || (!all && plain_control))) + bool plain_control = ev->key == WSAP_VTCORE_KEY_RETURN || ev->key == WSAP_VTCORE_KEY_TAB || + ev->key == WSAP_VTCORE_KEY_BACKSPACE; + if (ev->action == WSAP_VTCORE_KEY_RELEASE && + (!(flags & WSAP_VTCORE_KEYBOARD_EVENT_TYPES) || (!all && plain_control))) return true; - const unsigned command_mods = TERM_MOD_ALT | TERM_MOD_CTRL | - TERM_MOD_SUPER | TERM_MOD_HYPER | - TERM_MOD_META; + const unsigned command_mods = WSAP_VTCORE_MOD_ALT | WSAP_VTCORE_MOD_CTRL | + WSAP_VTCORE_MOD_SUPER | WSAP_VTCORE_MOD_HYPER | + WSAP_VTCORE_MOD_META; uint32_t text = ev->text; bool has_text = text >= 32 && !(text >= 127 && text < 160) && !(mods & command_mods); - if (!all && has_text) return ev->action == TERM_KEY_RELEASE; + if (!all && has_text) return ev->action == WSAP_VTCORE_KEY_RELEASE; if (!all && plain_control && !(mods & 63)) - return ev->action == TERM_KEY_RELEASE; - if (!(flags & (TERM_KEYBOARD_DISAMBIGUATE | TERM_KEYBOARD_EVENT_TYPES | TERM_KEYBOARD_ALL_KEYS))) - return ev->action == TERM_KEY_RELEASE; + return ev->action == WSAP_VTCORE_KEY_RELEASE; + if (!(flags & (WSAP_VTCORE_KEYBOARD_DISAMBIGUATE | WSAP_VTCORE_KEYBOARD_EVENT_TYPES | WSAP_VTCORE_KEYBOARD_ALL_KEYS))) + return ev->action == WSAP_VTCORE_KEY_RELEASE; uint32_t code = d->code, shifted = 0, base = 0; if (!functional) { code = ev->codepoint; - if (flags & TERM_KEYBOARD_ALTERNATE_KEYS) { - shifted = (mods & TERM_MOD_SHIFT) ? ev->shifted : 0; + if (flags & WSAP_VTCORE_KEYBOARD_ALTERNATE_KEYS) { + shifted = (mods & WSAP_VTCORE_MOD_SHIFT) ? ev->shifted : 0; base = ev->base; if (shifted == code) shifted = 0; if (base == code) base = 0; @@ -413,25 +413,25 @@ static bool encode_kitty(const struct term_keyboard_state *s, } if (!code) return true; - bool report_text = all && (flags & TERM_KEYBOARD_ASSOCIATED_TEXT) && has_text && - ev->action != TERM_KEY_RELEASE; + bool report_text = all && (flags & WSAP_VTCORE_KEYBOARD_ASSOCIATED_TEXT) && has_text && + ev->action != WSAP_VTCORE_KEY_RELEASE; format_kitty(sb, code, final, flags, functional, shifted, base, mods & 0xff, event, report_text, text); return true; } -static uint32_t control_base_char(const struct term_key_event *ev) +static uint32_t control_base_char(const struct wsap_vtcore_key_event *ev) { - uint32_t ch = ((ev->mods & TERM_MOD_SHIFT) && ev->shifted) + uint32_t ch = ((ev->mods & WSAP_VTCORE_MOD_SHIFT) && ev->shifted) ? ev->shifted : ev->codepoint; return ch < 0x80 ? ch : 0; } -static bool encode_legacy(const struct term_key_event *ev, - const struct term_modes *m, +static bool encode_legacy(const struct wsap_vtcore_key_event *ev, + const struct wsap_vtcore_modes *m, struct seqbuf *sb) { - if (m->app_keypad && (unsigned)ev->keypad < TERM_KEY_COUNT && + if (m->app_keypad && (unsigned)ev->keypad < WSAP_VTCORE_KEY_COUNT && legacy_desc[ev->keypad].keypad_ss3) { sb_bytes(sb, "\033O", 2); sb_ch(sb, legacy_desc[ev->keypad].keypad_ss3); @@ -439,7 +439,7 @@ static bool encode_legacy(const struct term_key_event *ev, } uint32_t ch = control_base_char(ev); - if ((ev->mods & TERM_MOD_CTRL) && ch) { + if ((ev->mods & WSAP_VTCORE_MOD_CTRL) && ch) { if ((ch >= 'a' && ch <= 'z') || (ch >= '@' && ch <= '_')) { sb_ch(sb, (char)(ch & 0x1f)); return true; @@ -450,13 +450,13 @@ static bool encode_legacy(const struct term_key_event *ev, unsigned csi = ev->mods & 63; unsigned p = csi + 1; - bool shift = (ev->mods & TERM_MOD_SHIFT) != 0; + bool shift = (ev->mods & WSAP_VTCORE_MOD_SHIFT) != 0; - enum term_key k = ev->key; - if (legacy_desc[k].equiv != TERM_KEY_NONE) + enum wsap_vtcore_key k = ev->key; + if (legacy_desc[k].equiv != WSAP_VTCORE_KEY_NONE) k = legacy_desc[k].equiv; - if ((unsigned)k < TERM_KEY_COUNT) { + if ((unsigned)k < WSAP_VTCORE_KEY_COUNT) { const struct legacy_desc *d = &legacy_desc[k]; if (d->final) { if (d->tilde) { @@ -483,15 +483,15 @@ static bool encode_legacy(const struct term_key_event *ev, } switch (k) { - case TERM_KEY_RETURN: sb_ch(sb, '\r'); return true; - case TERM_KEY_BACKSPACE: + case WSAP_VTCORE_KEY_RETURN: sb_ch(sb, '\r'); return true; + case WSAP_VTCORE_KEY_BACKSPACE: sb_ch(sb, m->backarrow_bs ? '\x08' : '\x7f'); return true; - case TERM_KEY_TAB: + case WSAP_VTCORE_KEY_TAB: if (shift) { sb_bytes(sb, "\033[Z", 3); } else { sb_ch(sb, '\t'); } return true; - case TERM_KEY_ESCAPE: sb_ch(sb, '\033'); return true; + case WSAP_VTCORE_KEY_ESCAPE: sb_ch(sb, '\033'); return true; default: break; } @@ -502,64 +502,64 @@ static bool encode_legacy(const struct term_key_event *ev, return false; } -void term_keyboard_update(struct term_keyboard_state *s, const struct term_key_event *ev) +void wsap_vtcore_keyboard_update(struct wsap_vtcore_keyboard_state *s, const struct wsap_vtcore_key_event *ev) { - if (!s || !ev || ev->key <= TERM_KEY_NONE || ev->key >= TERM_KEY_COUNT) + if (!s || !ev || ev->key <= WSAP_VTCORE_KEY_NONE || ev->key >= WSAP_VTCORE_KEY_COUNT) return; - if (ev->action == TERM_KEY_RELEASE) + if (ev->action == WSAP_VTCORE_KEY_RELEASE) s->down[ev->key >> 6] &= ~(1ull << (ev->key & 63)); - else if (ev->action == TERM_KEY_PRESS || ev->action == TERM_KEY_REPEAT) + else if (ev->action == WSAP_VTCORE_KEY_PRESS || ev->action == WSAP_VTCORE_KEY_REPEAT) s->down[ev->key >> 6] |= 1ull << (ev->key & 63); } -bool term_keyboard_key_down(const struct term_keyboard_state *s, enum term_key key) +bool wsap_vtcore_keyboard_key_down(const struct wsap_vtcore_keyboard_state *s, enum wsap_vtcore_key key) { - return s && key > TERM_KEY_NONE && (unsigned)key < TERM_KEY_COUNT && + return s && key > WSAP_VTCORE_KEY_NONE && (unsigned)key < WSAP_VTCORE_KEY_COUNT && ((s->down[key >> 6] >> (key & 63)) & 1); } -static inline bool legacy_is_escape(const struct term_key_event *ev, - const struct term_modes *m) +static inline bool legacy_is_escape(const struct wsap_vtcore_key_event *ev, + const struct wsap_vtcore_modes *m) { - if (m->app_keypad && (unsigned)ev->keypad < TERM_KEY_COUNT && + if (m->app_keypad && (unsigned)ev->keypad < WSAP_VTCORE_KEY_COUNT && legacy_desc[ev->keypad].keypad_ss3) return true; - if ((ev->mods & TERM_MOD_CTRL) && control_base_char(ev) == '[') + if ((ev->mods & WSAP_VTCORE_MOD_CTRL) && control_base_char(ev) == '[') return true; - enum term_key k = ev->key; - if (legacy_desc[k].equiv != TERM_KEY_NONE) + enum wsap_vtcore_key k = ev->key; + if (legacy_desc[k].equiv != WSAP_VTCORE_KEY_NONE) k = legacy_desc[k].equiv; - if ((unsigned)k < TERM_KEY_COUNT && legacy_desc[k].final) + if ((unsigned)k < WSAP_VTCORE_KEY_COUNT && legacy_desc[k].final) return true; - if (k == TERM_KEY_ESCAPE) + if (k == WSAP_VTCORE_KEY_ESCAPE) return true; - if (k == TERM_KEY_TAB && (ev->mods & TERM_MOD_SHIFT)) + if (k == WSAP_VTCORE_KEY_TAB && (ev->mods & WSAP_VTCORE_MOD_SHIFT)) return true; if (ev->text == '\033') return true; return false; } -struct term_input_result term_input_encode_key(const struct term_keyboard_state *s, - const struct term_key_event *ev, - const struct term_modes *m, +struct wsap_vtcore_input_result wsap_vtcore_input_encode_key(const struct wsap_vtcore_keyboard_state *s, + const struct wsap_vtcore_key_event *ev, + const struct wsap_vtcore_modes *m, char *buf, size_t buf_sz) { - struct term_input_result out = {0}; + struct wsap_vtcore_input_result out = {0}; if (!ev || !m || !buf || - (ev->action != TERM_KEY_PRESS && ev->action != TERM_KEY_REPEAT && - ev->action != TERM_KEY_RELEASE) || - (unsigned)ev->key >= TERM_KEY_COUNT) + (ev->action != WSAP_VTCORE_KEY_PRESS && ev->action != WSAP_VTCORE_KEY_REPEAT && + ev->action != WSAP_VTCORE_KEY_RELEASE) || + (unsigned)ev->key >= WSAP_VTCORE_KEY_COUNT) return out; struct seqbuf sb = { .p = buf, .left = buf_sz }; bool handled = encode_kitty(s, ev, m, &sb); if (!handled) { - if (ev->action == TERM_KEY_RELEASE) + if (ev->action == WSAP_VTCORE_KEY_RELEASE) return out; - if ((ev->mods & TERM_MOD_ALT) && !legacy_is_escape(ev, m)) + if ((ev->mods & WSAP_VTCORE_MOD_ALT) && !legacy_is_escape(ev, m)) sb_ch(&sb, '\033'); handled = encode_legacy(ev, m, &sb); @@ -571,45 +571,45 @@ struct term_input_result term_input_encode_key(const struct term_keyboard_state return sb_result(&sb, buf); } -struct term_input_result term_input_encode_mouse(const struct term_mouse_event *ev, - const struct term_modes *m, +struct wsap_vtcore_input_result wsap_vtcore_input_encode_mouse(const struct wsap_vtcore_mouse_event *ev, + const struct wsap_vtcore_modes *m, char *buf, size_t buf_sz) { - struct term_input_result out = {0}; + struct wsap_vtcore_input_result out = {0}; if (!ev || !m || !buf) return out; - if (!m->mouse || (ev->mods & TERM_MOD_SHIFT)) return out; + if (!m->mouse || (ev->mods & WSAP_VTCORE_MOD_SHIFT)) return out; - out.status = TERM_INPUT_CONSUMED; - if (ev->kind == TERM_MOUSE_LEAVE) return out; - struct term_vector2i cell = ev->pos; + out.status = WSAP_VTCORE_INPUT_CONSUMED; + if (ev->kind == WSAP_VTCORE_MOUSE_LEAVE) return out; + struct wsap_vtcore_vector2i cell = ev->pos; if (cell.x < 0 || cell.y < 0 || cell.x >= m->grid.x || cell.y >= m->grid.y) return out; - if (m->mouse == TERM_MOUSE_X10 && (ev->kind == TERM_MOUSE_RELEASE || ev->kind == TERM_MOUSE_MOTION)) { + if (m->mouse == WSAP_VTCORE_MOUSE_X10 && (ev->kind == WSAP_VTCORE_MOUSE_RELEASE || ev->kind == WSAP_VTCORE_MOUSE_MOTION)) { return out; } - if (ev->kind == TERM_MOUSE_MOTION && (m->mouse == TERM_MOUSE_NORMAL || - (m->mouse == TERM_MOUSE_BUTTON && ev->button == TERM_MOUSE_BUTTON_NONE))) { + if (ev->kind == WSAP_VTCORE_MOUSE_MOTION && (m->mouse == WSAP_VTCORE_MOUSE_NORMAL || + (m->mouse == WSAP_VTCORE_MOUSE_BUTTON && ev->button == WSAP_VTCORE_MOUSE_BUTTON_NONE))) { return out; } int button; - if (ev->button >= TERM_MOUSE_BUTTON_PRIMARY && ev->button <= TERM_MOUSE_BUTTON_NONE) + if (ev->button >= WSAP_VTCORE_MOUSE_BUTTON_PRIMARY && ev->button <= WSAP_VTCORE_MOUSE_BUTTON_NONE) button = ev->button; - else if (ev->button >= TERM_MOUSE_BUTTON_EXTRA_1 && ev->button <= TERM_MOUSE_BUTTON_EXTRA_4) - button = 128 + ev->button - TERM_MOUSE_BUTTON_EXTRA_1; - else if (ev->button >= TERM_MOUSE_WHEEL_UP && ev->button <= TERM_MOUSE_WHEEL_RIGHT) - button = 64 + ev->button - TERM_MOUSE_WHEEL_UP; + else if (ev->button >= WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1 && ev->button <= WSAP_VTCORE_MOUSE_BUTTON_EXTRA_4) + button = 128 + ev->button - WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1; + else if (ev->button >= WSAP_VTCORE_MOUSE_WHEEL_UP && ev->button <= WSAP_VTCORE_MOUSE_WHEEL_RIGHT) + button = 64 + ev->button - WSAP_VTCORE_MOUSE_WHEEL_UP; else { return out; } int mods = 0; - if (ev->mods & TERM_MOD_ALT) mods |= 8; - if (ev->mods & TERM_MOD_CTRL) mods |= 16; + if (ev->mods & WSAP_VTCORE_MOD_ALT) mods |= 8; + if (ev->mods & WSAP_VTCORE_MOD_CTRL) mods |= 16; - int code = button | mods | (ev->kind == TERM_MOUSE_MOTION ? 32 : 0); - int legacy_code = ev->kind == TERM_MOUSE_RELEASE ? 3 | mods : code; - struct term_vector2i report = m->mouse_encoding == TERM_MOUSE_ENC_SGR_PIXELS + int code = button | mods | (ev->kind == WSAP_VTCORE_MOUSE_MOTION ? 32 : 0); + int legacy_code = ev->kind == WSAP_VTCORE_MOUSE_RELEASE ? 3 | mods : code; + struct wsap_vtcore_vector2i report = m->mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS ? ev->pixel : cell; if (report.x < 0 || report.y < 0) return out; @@ -618,16 +618,16 @@ struct term_input_result term_input_encode_mouse(const struct term_mouse_event * struct seqbuf sb = { .p = buf, .left = buf_sz }; - if (m->mouse_encoding == TERM_MOUSE_ENC_SGR || - m->mouse_encoding == TERM_MOUSE_ENC_SGR_PIXELS) { + if (m->mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR || + m->mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS) { sb_bytes(&sb, "\033[<", 3); sb_u32(&sb, (uint32_t)code); sb_ch(&sb, ';'); sb_u32(&sb, report_x); sb_ch(&sb, ';'); sb_u32(&sb, report_y); - sb_ch(&sb, ev->kind == TERM_MOUSE_RELEASE ? 'm' : 'M'); - } else if (m->mouse_encoding == TERM_MOUSE_ENC_URXVT) { + sb_ch(&sb, ev->kind == WSAP_VTCORE_MOUSE_RELEASE ? 'm' : 'M'); + } else if (m->mouse_encoding == WSAP_VTCORE_MOUSE_ENC_URXVT) { sb_bytes(&sb, "\033[", 2); sb_u32(&sb, (uint32_t)(legacy_code + 32)); sb_ch(&sb, ';'); @@ -635,7 +635,7 @@ struct term_input_result term_input_encode_mouse(const struct term_mouse_event * sb_ch(&sb, ';'); sb_u32(&sb, (uint32_t)(cell.y + 1)); sb_ch(&sb, 'M'); - } else if (m->mouse_encoding == TERM_MOUSE_ENC_UTF8) { + } else if (m->mouse_encoding == WSAP_VTCORE_MOUSE_ENC_UTF8) { sb_bytes(&sb, "\033[M", 3); sb_utf8(&sb, (unsigned)legacy_code + 32); sb_utf8(&sb, (unsigned)cell.x + 33); @@ -665,11 +665,11 @@ static bool is_direction_format(uint32_t cp) cp == 0xfeff; } -struct term_input_result term_input_encode_paste(const struct term_modes *m, +struct wsap_vtcore_input_result wsap_vtcore_input_encode_paste(const struct wsap_vtcore_modes *m, const char *text, size_t len, char *buf, size_t capacity) { - struct term_input_result out = {0}; + struct wsap_vtcore_input_result out = {0}; if (!m || !buf || (!text && len)) return out; struct seqbuf sb = { .p = buf, .left = capacity }; @@ -677,7 +677,7 @@ struct term_input_result term_input_encode_paste(const struct term_modes *m, char *body = sb.p; for (size_t i = 0; i < len;) { if (sb.overflow) break; - size_t run = term_scan_printable_span(text + i, len - i, 0x7f); + size_t run = wsap_vtcore_scan_printable_span(text + i, len - i, 0x7f); if (run > 0) { sb_bytes(&sb, text + i, run); i += run; @@ -695,7 +695,7 @@ struct term_input_result term_input_encode_paste(const struct term_modes *m, continue; } uint32_t cp; - int n = term_utf8_decode_one(text + i, len - i, &cp); + int n = wsap_vtcore_utf8_decode_one(text + i, len - i, &cp); if (!n) { i++; continue; } if (cp >= 0xa0 && !is_direction_format(cp)) { sb_bytes(&sb, text + i, (size_t)n); @@ -703,7 +703,7 @@ struct term_input_result term_input_encode_paste(const struct term_modes *m, i += (size_t)n; } - out.status = TERM_INPUT_CONSUMED; + out.status = WSAP_VTCORE_INPUT_CONSUMED; if (!sb.overflow && sb.p == body) return out; if (m->bracketed_paste) sb_bytes(&sb, "\033[201~", 6); return sb_result(&sb, buf); diff --git a/src/internal.h b/src/internal.h index 676413c..81ab53f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -1,7 +1,7 @@ -#ifndef TERM_INTERNAL_H -#define TERM_INTERNAL_H +#ifndef WSAP_VTCORE_INTERNAL_H +#define WSAP_VTCORE_INTERNAL_H -#include "term.h" +#include "wsap_vtcore.h" #include "cell.h" #include "csi.h" #include "gstore.h" @@ -41,7 +41,7 @@ struct keyboard_mode { /* What DECSC saves, as in xterm: the cursor, the pen, origin mode, the * pending wrap, and the character sets. */ -struct term_saved_cursor { +struct wsap_vtcore_saved_cursor { int x, y; uint32_t fg, bg, ul; char charsets[2]; @@ -89,7 +89,7 @@ struct screen { uint32_t top_seg; }; -struct term_sel_point { +struct wsap_vtcore_sel_point { uint64_t line_id; uint32_t cell_off; }; @@ -107,9 +107,9 @@ struct resize_scratch { }; -struct term { +struct wsap_vtcore { /* The writer section. A waiting thread sleeps on it. */ - term_mutex write_lock; + wsap_vtcore_mutex write_lock; _Atomic uint64_t writer_tid; uint32_t write_depth; int cols; @@ -172,8 +172,8 @@ struct term { struct resize_scratch resize; struct grow_buf ascii_ends; struct grow_buf ascii_tail; - struct term_saved_cursor normal_saved_cursor; - struct term_saved_cursor normal_saved_decsc; + struct wsap_vtcore_saved_cursor normal_saved_cursor; + struct wsap_vtcore_saved_cursor normal_saved_decsc; int normal_cols, normal_rows; bool alt_allocated; bool normal_cursor_visible; @@ -186,13 +186,13 @@ struct term { uint64_t full_gen; int prompt_y; int left_margin, right_margin; - struct term_sel_point sel_start, sel_end; - struct term_sel_point sel_anchor_first, sel_anchor_last; - enum term_select_unit select_unit; + struct wsap_vtcore_sel_point sel_start, sel_end; + struct wsap_vtcore_sel_point sel_anchor_first, sel_anchor_last; + enum wsap_vtcore_select_unit select_unit; int mouse_mode, mouse_encoding; - enum term_cursor_style cursor_style; - enum term_cursor_style default_cursor_style; + enum wsap_vtcore_cursor_style cursor_style; + enum wsap_vtcore_cursor_style default_cursor_style; int charset_active; int osc_len; int dcs_len; @@ -200,7 +200,7 @@ struct term { struct keyboard_mode keyboard[2]; /* The DECSC slot. Cold: it stays out of the hot fields above. */ - struct term_saved_cursor saved; + struct wsap_vtcore_saved_cursor saved; uint8_t *tabs; struct cell *view_row_scratch; @@ -221,7 +221,7 @@ struct term { char *cwd; char *pointer_shape; - struct term_callbacks cb; + struct wsap_vtcore_callbacks cb; struct palette palette; struct gstore *gstore; /* Unique for the life of the process. A snapshot compares it, not the @@ -229,10 +229,10 @@ struct term { uint64_t serial; }; -static inline void reset_sgr(struct term *t) +static inline void reset_sgr(struct wsap_vtcore *t) { - t->cur_fg = TERM_COLOR_FG; - t->cur_bg = TERM_COLOR_BG; + t->cur_fg = WSAP_VTCORE_COLOR_FG; + t->cur_bg = WSAP_VTCORE_COLOR_BG; t->bold = false; t->faint = false; t->italic = false; @@ -244,16 +244,16 @@ static inline void reset_sgr(struct term *t) } /* The DECSC slot before any save: home, the default pen, and ASCII. */ -static inline struct term_saved_cursor term_saved_cursor_initial(void) +static inline struct wsap_vtcore_saved_cursor wsap_vtcore_saved_cursor_initial(void) { - return (struct term_saved_cursor){ - .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .charsets = { 'B', 'B' }, + return (struct wsap_vtcore_saved_cursor){ + .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .charsets = { 'B', 'B' }, }; } -static inline struct term_saved_cursor term_cursor_save(const struct term *t) +static inline struct wsap_vtcore_saved_cursor wsap_vtcore_cursor_save(const struct wsap_vtcore *t) { - return (struct term_saved_cursor){ + return (struct wsap_vtcore_saved_cursor){ .x = t->cursor_x, .y = t->cursor_y, .fg = t->cur_fg, .bg = t->cur_bg, .ul = t->cur_ul, .charsets = { t->charsets[0], t->charsets[1] }, @@ -267,7 +267,7 @@ static inline struct term_saved_cursor term_cursor_save(const struct term *t) /* Take the pen, origin mode, and character sets from s. The caller places * the cursor. */ -static inline void term_cursor_apply(struct term *t, const struct term_saved_cursor *s) +static inline void wsap_vtcore_cursor_apply(struct wsap_vtcore *t, const struct wsap_vtcore_saved_cursor *s) { t->cur_fg = s->fg; t->cur_bg = s->bg; @@ -286,12 +286,12 @@ static inline void term_cursor_apply(struct term *t, const struct term_saved_cur t->graphics = t->charsets[t->charset_active] == '0'; } -static inline void send_response(struct term *t, const char *str) +static inline void send_response(struct wsap_vtcore *t, const char *str) { if (t && t->cb.reply) t->cb.reply(t->cb.ud, str, strlen(str)); } -static inline int term_hex_nib(char c) +static inline int wsap_vtcore_hex_nib(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; @@ -299,7 +299,7 @@ static inline int term_hex_nib(char c) return -1; } -static inline bool term_lnm(const struct term *t) +static inline bool wsap_vtcore_lnm(const struct wsap_vtcore *t) { return t->lnm || t->transport_newline; } @@ -314,53 +314,53 @@ static inline bool mode_is_mouse_enc(int m) return m == 1005 || m == 1006 || m == 1015 || m == 1016; } -static const uint16_t term_ul_flags[] = { +static const uint16_t wsap_vtcore_ul_flags[] = { 0, CELL_UNDERLINE, CELL_DOUBLE_UNDERLINE, CELL_CURLY_UNDERLINE, CELL_DOTTED_UNDERLINE, CELL_DASHED_UNDERLINE, }; -static inline uint16_t term_current_flags(const struct term *t) +static inline uint16_t wsap_vtcore_current_flags(const struct wsap_vtcore *t) { uint16_t f = 0; if (t->bold) f |= CELL_BOLD; if (t->faint) f |= CELL_FAINT; if (t->italic) f |= CELL_ITALIC; - if (t->underline < sizeof(term_ul_flags) / sizeof(term_ul_flags[0])) - f |= term_ul_flags[t->underline]; + if (t->underline < sizeof(wsap_vtcore_ul_flags) / sizeof(wsap_vtcore_ul_flags[0])) + f |= wsap_vtcore_ul_flags[t->underline]; if (t->strike) f |= CELL_STRIKE; if (t->overline) f |= CELL_OVERLINE; if (t->cur_link) f |= CELL_LINK; return f; } -static inline uint32_t term_flags_pad(const struct term *t) +static inline uint32_t wsap_vtcore_flags_pad(const struct wsap_vtcore *t) { - return term_current_flags(t) | ((uint32_t)t->cur_link << 16); + return wsap_vtcore_current_flags(t) | ((uint32_t)t->cur_link << 16); } -static inline struct text_pen term_text_pen(const struct term *t) +static inline struct text_pen wsap_vtcore_text_pen(const struct wsap_vtcore *t) { return (struct text_pen){ - .fg = TERM_EXPECT(t->inverse, 0) ? t->cur_bg : t->cur_fg, - .bg = TERM_EXPECT(t->inverse, 0) ? t->cur_fg : t->cur_bg, - .sl = term_flags_pad(t), + .fg = WSAP_VTCORE_EXPECT(t->inverse, 0) ? t->cur_bg : t->cur_fg, + .bg = WSAP_VTCORE_EXPECT(t->inverse, 0) ? t->cur_fg : t->cur_bg, + .sl = wsap_vtcore_flags_pad(t), }; } -static inline void term_tabs_clear(struct term *t) +static inline void wsap_vtcore_tabs_clear(struct wsap_vtcore *t) { memset(t->tabs, 0, (size_t)t->tabs_cap); t->custom_tabs = true; } -static inline void term_tabs_default(struct term *t) +static inline void wsap_vtcore_tabs_default(struct wsap_vtcore *t) { for (int c = 8; c < t->tabs_cap; c += 8) t->tabs[c] = 1; t->custom_tabs = false; } -static inline bool term_str_was_truncated(struct term *t) +static inline bool wsap_vtcore_str_was_truncated(struct wsap_vtcore *t) { bool truncated = t->str_truncated; t->str_truncated = false; @@ -368,27 +368,27 @@ static inline bool term_str_was_truncated(struct term *t) } /* Every thread has its own anchor, so its address names the thread. */ -extern _Thread_local char term_thread_anchor; +extern _Thread_local char wsap_vtcore_thread_anchor; -static inline void term_write_begin(struct term *t) +static inline void wsap_vtcore_write_begin(struct wsap_vtcore *t) { if (!t) return; - uint64_t self = (uint64_t)(uintptr_t)&term_thread_anchor; + uint64_t self = (uint64_t)(uintptr_t)&wsap_vtcore_thread_anchor; if (atomic_load_explicit(&t->writer_tid, memory_order_relaxed) == self) { t->write_depth++; return; } - term_mutex_lock(&t->write_lock); + wsap_vtcore_mutex_lock(&t->write_lock); atomic_store_explicit(&t->writer_tid, self, memory_order_relaxed); t->write_depth = 1; } -static inline void term_write_end(struct term *t) +static inline void wsap_vtcore_write_end(struct wsap_vtcore *t) { if (!t) return; if (--t->write_depth == 0) { atomic_store_explicit(&t->writer_tid, 0, memory_order_relaxed); - term_mutex_unlock(&t->write_lock); + wsap_vtcore_mutex_unlock(&t->write_lock); } } @@ -3,19 +3,19 @@ * the first terminal exists, so every call in a process uses the same * kernels. */ -#include "term.h" +#include "wsap_vtcore.h" #include "simd.h" #include <stdatomic.h> #include <stdlib.h> #include <string.h> -int term_isa_level; +int wsap_vtcore_isa_level; static atomic_int isa_state; static const char *const level_names[] = { "base", "avx2", "avx512" }; -#if defined(TERM_ISA_RUNTIME) +#if defined(WSAP_VTCORE_ISA_RUNTIME) /* The AVX-512 kernels also need VBMI and VBMI2. Every CPU with VBMI except * Cannon Lake has VBMI2. */ static int cpu_level(void) @@ -23,56 +23,56 @@ static int cpu_level(void) __builtin_cpu_init(); if (__builtin_cpu_supports("x86-64-v4") && __builtin_cpu_supports("avx512vbmi") && __builtin_cpu_supports("avx512vbmi2")) - return TERM_ISA_AVX512; + return WSAP_VTCORE_ISA_AVX512; if (__builtin_cpu_supports("x86-64-v3")) - return TERM_ISA_AVX2; - return TERM_ISA_BASE; + return WSAP_VTCORE_ISA_AVX2; + return WSAP_VTCORE_ISA_BASE; } #else static int cpu_level(void) { - return TERM_ISA_FLOOR; + return WSAP_VTCORE_ISA_FLOOR; } #endif static int pick_level(void) { int level = cpu_level(); - /* TERM_HEADLESS_ISA can only lower the level, never below the floor the + /* WSAP_VTCORE_ISA can only lower the level, never below the floor the * compiler flags fix. */ - const char *want = getenv("TERM_HEADLESS_ISA"); - for (int i = TERM_ISA_FLOOR; want && i < level; i++) + const char *want = getenv("WSAP_VTCORE_ISA"); + for (int i = WSAP_VTCORE_ISA_FLOOR; want && i < level; i++) if (!strcmp(want, level_names[i])) level = i; return level; } /* The first caller picks the level. A second caller waits until it is set. */ -void term_isa_init(void) +void wsap_vtcore_isa_init(void) { if (atomic_load_explicit(&isa_state, memory_order_acquire) == 2) return; int expected = 0; if (atomic_compare_exchange_strong(&isa_state, &expected, 1)) { - term_isa_level = pick_level(); + wsap_vtcore_isa_level = pick_level(); atomic_store_explicit(&isa_state, 2, memory_order_release); return; } while (atomic_load_explicit(&isa_state, memory_order_acquire) != 2) - term_cpu_relax(); + wsap_vtcore_cpu_relax(); } -const char *term_isa(void) +const char *wsap_vtcore_isa(void) { - term_isa_init(); + wsap_vtcore_isa_init(); #if defined(__aarch64__) return "neon"; #else - int level = TERM_ISA_FLOOR; - if (term_use_avx2()) - level = TERM_ISA_AVX2; - if (term_use_avx512()) - level = TERM_ISA_AVX512; + int level = WSAP_VTCORE_ISA_FLOOR; + if (wsap_vtcore_use_avx2()) + level = WSAP_VTCORE_ISA_AVX2; + if (wsap_vtcore_use_avx512()) + level = WSAP_VTCORE_ISA_AVX512; return level_names[level]; #endif } diff --git a/src/kernels.h b/src/kernels.h index 5cf0d93..9112c2e 100644 --- a/src/kernels.h +++ b/src/kernels.h @@ -10,8 +10,8 @@ #include <stdint.h> #include <string.h> -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline size_t scan_printable_span_avx512(const char *buf, size_t len, unsigned char hi) { size_t i = 0; @@ -21,21 +21,21 @@ static inline size_t scan_printable_span_avx512(const char *buf, size_t len, uns __m512i v = _mm512_loadu_si512((const void *)(buf + i)); __mmask64 mask = _mm512_cmpge_epu8_mask(_mm512_sub_epi8(v, v20_512), vlim_512); if (mask != 0) - return i + term_ctz64(mask); + return i + wsap_vtcore_ctz64(mask); } if (i < len) { __mmask64 load_mask = ((uint64_t)1 << (len - i)) - 1; __m512i v = _mm512_maskz_loadu_epi8(load_mask, buf + i); __mmask64 mask = _mm512_mask_cmpge_epu8_mask(load_mask, _mm512_sub_epi8(v, v20_512), vlim_512); if (mask != 0) - return i + term_ctz64(mask); + return i + wsap_vtcore_ctz64(mask); } return len; } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline size_t scan_printable_span_avx2(const char *buf, size_t len, unsigned char hi) { size_t i = 0; @@ -48,10 +48,10 @@ static inline size_t scan_printable_span_avx2(const char *buf, size_t len, unsig __m256i sub1 = _mm256_sub_epi8(v1, v_offset); int m0 = _mm256_movemask_epi8(_mm256_cmpgt_epi8(sub0, v_limit)); int m1 = _mm256_movemask_epi8(_mm256_cmpgt_epi8(sub1, v_limit)); - if (TERM_EXPECT((m0 | m1) != 0, 0)) { + if (WSAP_VTCORE_EXPECT((m0 | m1) != 0, 0)) { if (m0 != 0) - return i + term_ctz32(m0); - return i + 32 + term_ctz32(m1); + return i + wsap_vtcore_ctz32(m0); + return i + 32 + wsap_vtcore_ctz32(m1); } } if (i + 32 <= len) { @@ -59,7 +59,7 @@ static inline size_t scan_printable_span_avx2(const char *buf, size_t len, unsig __m256i sub = _mm256_sub_epi8(v, v_offset); int mask = _mm256_movemask_epi8(_mm256_cmpgt_epi8(sub, v_limit)); if (mask != 0) - return i + term_ctz32(mask); + return i + wsap_vtcore_ctz32(mask); i += 32; } if (i + 16 <= len) { @@ -67,7 +67,7 @@ static inline size_t scan_printable_span_avx2(const char *buf, size_t len, unsig __m128i sub = _mm_sub_epi8(v, _mm_set1_epi8((char)(0x20 + 0x80))); int mask = _mm_movemask_epi8(_mm_cmpgt_epi8(sub, _mm_set1_epi8((char)(hi - 0xa1)))) & 0xFFFF; if (mask != 0) - return i + term_ctz32(mask); + return i + wsap_vtcore_ctz32(mask); i += 16; } for (; i < len; i++) { @@ -83,12 +83,12 @@ static inline size_t scan_printable_span(const char *buf, size_t len, unsigned char hi) { /* A short span costs less inline than as a call. */ -#if defined(TERM_KERNEL_AVX512) - if (len >= 64 && term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (len >= 64 && wsap_vtcore_use_avx512()) return scan_printable_span_avx512(buf, len, hi); #endif -#if defined(TERM_KERNEL_AVX2) - if (len >= 32 && term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (len >= 32 && wsap_vtcore_use_avx2()) return scan_printable_span_avx2(buf, len, hi); #endif size_t i = 0; @@ -108,26 +108,26 @@ static inline size_t scan_printable_span(const char *buf, size_t len, uint8x16_t mor = vorrq_u8(vorrq_u8(m0, m1), vorrq_u8(m2, m3)); uint64x2_t mor64 = vreinterpretq_u64_u8(mor); - if (TERM_EXPECT((vgetq_lane_u64(mor64, 0) | vgetq_lane_u64(mor64, 1)) != 0, 0)) { + if (WSAP_VTCORE_EXPECT((vgetq_lane_u64(mor64, 0) | vgetq_lane_u64(mor64, 1)) != 0, 0)) { uint64x2_t m0_64 = vreinterpretq_u64_u8(m0); uint64_t lo0 = vgetq_lane_u64(m0_64, 0), hi0 = vgetq_lane_u64(m0_64, 1); - if (lo0) return i + (term_ctz64(lo0) >> 3); - if (hi0) return i + 8 + (term_ctz64(hi0) >> 3); + if (lo0) return i + (wsap_vtcore_ctz64(lo0) >> 3); + if (hi0) return i + 8 + (wsap_vtcore_ctz64(hi0) >> 3); uint64x2_t m1_64 = vreinterpretq_u64_u8(m1); uint64_t lo1 = vgetq_lane_u64(m1_64, 0), hi1 = vgetq_lane_u64(m1_64, 1); - if (lo1) return i + 16 + (term_ctz64(lo1) >> 3); - if (hi1) return i + 24 + (term_ctz64(hi1) >> 3); + if (lo1) return i + 16 + (wsap_vtcore_ctz64(lo1) >> 3); + if (hi1) return i + 24 + (wsap_vtcore_ctz64(hi1) >> 3); uint64x2_t m2_64 = vreinterpretq_u64_u8(m2); uint64_t lo2 = vgetq_lane_u64(m2_64, 0), hi2 = vgetq_lane_u64(m2_64, 1); - if (lo2) return i + 32 + (term_ctz64(lo2) >> 3); - if (hi2) return i + 40 + (term_ctz64(hi2) >> 3); + if (lo2) return i + 32 + (wsap_vtcore_ctz64(lo2) >> 3); + if (hi2) return i + 40 + (wsap_vtcore_ctz64(hi2) >> 3); uint64x2_t m3_64 = vreinterpretq_u64_u8(m3); uint64_t lo3 = vgetq_lane_u64(m3_64, 0), hi3 = vgetq_lane_u64(m3_64, 1); - if (lo3) return i + 48 + (term_ctz64(lo3) >> 3); - if (hi3) return i + 56 + (term_ctz64(hi3) >> 3); + if (lo3) return i + 48 + (wsap_vtcore_ctz64(lo3) >> 3); + if (hi3) return i + 56 + (wsap_vtcore_ctz64(hi3) >> 3); } } for (; i + 16 <= len; i += 16) { @@ -136,14 +136,14 @@ static inline size_t scan_printable_span(const char *buf, size_t len, uint64x2_t m64 = vreinterpretq_u64_u8(mask); uint64_t lo = vgetq_lane_u64(m64, 0); uint64_t hi64 = vgetq_lane_u64(m64, 1); - if (lo) return i + (term_ctz64(lo) >> 3); - if (hi64) return i + 8 + (term_ctz64(hi64) >> 3); + if (lo) return i + (wsap_vtcore_ctz64(lo) >> 3); + if (hi64) return i + 8 + (wsap_vtcore_ctz64(hi64) >> 3); } if (i + 8 <= len) { uint8x8_t v8 = vld1_u8((const uint8_t *)buf + i); uint8x8_t mask8 = vcge_u8(vsub_u8(v8, vget_low_u8(v20)), vget_low_u8(vlim)); uint64_t m64 = vget_lane_u64(vreinterpret_u64_u8(mask8), 0); - if (m64) return i + (term_ctz64(m64) >> 3); + if (m64) return i + (wsap_vtcore_ctz64(m64) >> 3); i += 8; } #elif defined(__x86_64__) @@ -154,19 +154,19 @@ static inline size_t scan_printable_span(const char *buf, size_t len, __m128i m1 = _mm_cmpgt_epi8(_mm_sub_epi8(_mm_loadu_si128((const __m128i *)(buf + i + 16)), v_offset), v_limit); __m128i m2 = _mm_cmpgt_epi8(_mm_sub_epi8(_mm_loadu_si128((const __m128i *)(buf + i + 32)), v_offset), v_limit); __m128i m3 = _mm_cmpgt_epi8(_mm_sub_epi8(_mm_loadu_si128((const __m128i *)(buf + i + 48)), v_offset), v_limit); - if (TERM_EXPECT(_mm_movemask_epi8(_mm_or_si128(_mm_or_si128(m0, m1), _mm_or_si128(m2, m3))) != 0, 0)) { + if (WSAP_VTCORE_EXPECT(_mm_movemask_epi8(_mm_or_si128(_mm_or_si128(m0, m1), _mm_or_si128(m2, m3))) != 0, 0)) { uint64_t mask = (uint64_t)(unsigned)_mm_movemask_epi8(m0) | (uint64_t)(unsigned)_mm_movemask_epi8(m1) << 16 | (uint64_t)(unsigned)_mm_movemask_epi8(m2) << 32 | (uint64_t)(unsigned)_mm_movemask_epi8(m3) << 48; - return i + (size_t)term_ctz64(mask); + return i + (size_t)wsap_vtcore_ctz64(mask); } } for (; i + 16 <= len; i += 16) { int mask = _mm_movemask_epi8(_mm_cmpgt_epi8( _mm_sub_epi8(_mm_loadu_si128((const __m128i *)(buf + i)), v_offset), v_limit)); if (mask != 0) - return i + (size_t)term_ctz32((unsigned)mask); + return i + (size_t)wsap_vtcore_ctz32((unsigned)mask); } #endif for (; i < len; i++) { @@ -179,10 +179,10 @@ static inline size_t scan_printable_span(const char *buf, size_t len, /* Copy n bytes with loads that stay inside [src, src + n). Short text runs * are common; a libc call costs more than the copy. */ -static inline TERM_ALWAYS_INLINE void bytes_copy_small(uint8_t *restrict dst, +static inline WSAP_VTCORE_ALWAYS_INLINE void bytes_copy_small(uint8_t *restrict dst, const char *restrict src, int n) { - if (TERM_EXPECT((unsigned)(n - 16) <= 16u, 1)) { + if (WSAP_VTCORE_EXPECT((unsigned)(n - 16) <= 16u, 1)) { /* 16 to 32 bytes: two overlapping 16-byte copies. Both loads stay * inside [src, src + n). This is the usual history line length, and * two copies cost less here than the loop below. */ @@ -217,8 +217,8 @@ static inline size_t scan_crlf_tail(const char *buf, size_t i, size_t len) return i; } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline size_t scan_crlf_pairs_avx512(const char *buf, size_t len) { size_t i = 0; @@ -226,14 +226,14 @@ static inline size_t scan_crlf_pairs_avx512(const char *buf, size_t len) for (; i + 64 <= len; i += 64) { uint64_t eq = _mm512_cmpeq_epi8_mask(_mm512_loadu_si512((const void *)(buf + i)), pair); if (eq != ~0ull) - return i + ((size_t)term_ctz64(~eq) & ~(size_t)1); + return i + ((size_t)wsap_vtcore_ctz64(~eq) & ~(size_t)1); } return scan_crlf_tail(buf, i, len); } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline size_t scan_crlf_pairs_avx2(const char *buf, size_t len) { size_t i = 0; @@ -242,7 +242,7 @@ static inline size_t scan_crlf_pairs_avx2(const char *buf, size_t len) uint32_t eq = (uint32_t)_mm256_movemask_epi8( _mm256_cmpeq_epi8(_mm256_loadu_si256((const __m256i *)(const void *)(buf + i)), pair)); if (eq != ~0u) - return i + ((size_t)term_ctz32(~eq) & ~(size_t)1); + return i + ((size_t)wsap_vtcore_ctz32(~eq) & ~(size_t)1); } return scan_crlf_tail(buf, i, len); } @@ -251,12 +251,12 @@ static inline size_t scan_crlf_pairs_avx2(const char *buf, size_t len) /* The length of the prefix of buf made of "\r\n" pairs; always even. */ static inline size_t scan_crlf_pairs(const char *buf, size_t len) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return scan_crlf_pairs_avx512(buf, len); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return scan_crlf_pairs_avx2(buf, len); #endif size_t i = 0; @@ -264,16 +264,16 @@ static inline size_t scan_crlf_pairs(const char *buf, size_t len) const uint8x16_t pair = vreinterpretq_u8_u16(vdupq_n_u16(0x0A0D)); for (; i + 16 <= len; i += 16) { uint8x16_t eq = vceqq_u8(vld1q_u8((const uint8_t *)buf + i), pair); - uint16_t bits = term_lane_bits(eq); + uint16_t bits = wsap_vtcore_lane_bits(eq); if (bits != 0xFFFF) - return i + ((size_t)term_ctz32((unsigned)~bits & 0xFFFFu) & ~(size_t)1); + return i + ((size_t)wsap_vtcore_ctz32((unsigned)~bits & 0xFFFFu) & ~(size_t)1); } #endif return scan_crlf_tail(buf, i, len); } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline size_t scan_byte_run_avx512(const char *buf, size_t len, char byte) { size_t i = 0; @@ -281,7 +281,7 @@ static inline size_t scan_byte_run_avx512(const char *buf, size_t len, char byte for (; i + 64 <= len; i += 64) { uint64_t eq = _mm512_cmpeq_epi8_mask(_mm512_loadu_si512((const void *)(buf + i)), want); if (eq != ~0ull) - return i + (size_t)term_ctz64(~eq); + return i + (size_t)wsap_vtcore_ctz64(~eq); } while (i < len && buf[i] == byte) i++; @@ -289,8 +289,8 @@ static inline size_t scan_byte_run_avx512(const char *buf, size_t len, char byte } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline size_t scan_byte_run_avx2(const char *buf, size_t len, char byte) { size_t i = 0; @@ -299,7 +299,7 @@ static inline size_t scan_byte_run_avx2(const char *buf, size_t len, char byte) uint32_t eq = (uint32_t)_mm256_movemask_epi8( _mm256_cmpeq_epi8(_mm256_loadu_si256((const __m256i *)(const void *)(buf + i)), want)); if (eq != ~0u) - return i + (size_t)term_ctz32(~eq); + return i + (size_t)wsap_vtcore_ctz32(~eq); } while (i < len && buf[i] == byte) i++; @@ -310,21 +310,21 @@ static inline size_t scan_byte_run_avx2(const char *buf, size_t len, char byte) /* The length of the prefix of buf made of byte. */ static inline size_t scan_byte_run(const char *buf, size_t len, char byte) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return scan_byte_run_avx512(buf, len, byte); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return scan_byte_run_avx2(buf, len, byte); #endif size_t i = 0; #if defined(__aarch64__) const uint8x16_t want = vdupq_n_u8((uint8_t)byte); for (; i + 16 <= len; i += 16) { - uint16_t bits = term_lane_bits(vceqq_u8(vld1q_u8((const uint8_t *)buf + i), want)); + uint16_t bits = wsap_vtcore_lane_bits(vceqq_u8(vld1q_u8((const uint8_t *)buf + i), want)); if (bits != 0xFFFF) - return i + (size_t)term_ctz32((unsigned)~bits & 0xFFFFu); + return i + (size_t)wsap_vtcore_ctz32((unsigned)~bits & 0xFFFFu); } #elif defined(__x86_64__) const __m128i want = _mm_set1_epi8(byte); @@ -332,7 +332,7 @@ static inline size_t scan_byte_run(const char *buf, size_t len, char byte) unsigned eq = (unsigned)_mm_movemask_epi8( _mm_cmpeq_epi8(_mm_loadu_si128((const __m128i *)(const void *)(buf + i)), want)); if (eq != 0xFFFFu) - return i + (size_t)term_ctz32(~eq & 0xFFFFu); + return i + (size_t)wsap_vtcore_ctz32(~eq & 0xFFFFu); } #endif while (i < len && buf[i] == byte) @@ -355,16 +355,16 @@ static inline int scan_ascii_lf_tail(const char *buf, int i, int len, uint16_t * return count; } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline int store_lf_offsets_avx512(uint16_t *ends, uint64_t nl, __m512i lanes, __m128i block) { - unsigned n = (unsigned)term_popcount64(nl); + unsigned n = (unsigned)wsap_vtcore_popcount64(nl); __m512i packed = _mm512_maskz_compress_epi8(nl, lanes); __m128i offsets = _mm_add_epi16(_mm_cvtepu8_epi16(_mm512_castsi512_si128(packed)), block); _mm_storeu_si128((__m128i *)ends, offsets); - if (TERM_EXPECT(n > 8, 0)) { + if (WSAP_VTCORE_EXPECT(n > 8, 0)) { __m512i base = _mm512_broadcast_i32x4(block); __m512i wide = _mm512_add_epi16(_mm512_cvtepu8_epi16(_mm512_castsi512_si256(packed)), base); _mm512_storeu_si512(ends, wide); @@ -376,7 +376,7 @@ static inline int store_lf_offsets_avx512(uint16_t *ends, uint64_t nl, return (int)n; } -TERM_TARGET_AVX512 TERM_MAYBE_UNUSED +WSAP_VTCORE_TARGET_AVX512 WSAP_VTCORE_MAYBE_UNUSED static int scan_ascii_lf_avx512(const char *buf, int len, uint16_t *ends) { int i = 0, count = 0; @@ -416,8 +416,8 @@ static int scan_ascii_lf_avx512(const char *buf, int len, uint16_t *ends) } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 TERM_MAYBE_UNUSED +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 WSAP_VTCORE_MAYBE_UNUSED static int scan_ascii_lf_avx2(const char *buf, int len, uint16_t *ends) { int i = 0, count = 0; @@ -430,7 +430,7 @@ static int scan_ascii_lf_avx2(const char *buf, int len, uint16_t *ends) _mm256_cmpgt_epi8(d, _mm256_set1_epi8((char)0xde))) & ~nl; if (bad) break; while (nl) { - ends[++count] = (uint16_t)(i + term_ctz32(nl) + 1); + ends[++count] = (uint16_t)(i + wsap_vtcore_ctz32(nl) + 1); nl &= nl - 1; } } @@ -440,14 +440,14 @@ static int scan_ascii_lf_avx2(const char *buf, int len, uint16_t *ends) /* Find complete ASCII lines. Stop at the first byte other than text or LF. * The caller supplies len + 65 entries. len must fit in uint16_t. */ -static TERM_NOINLINE TERM_MAYBE_UNUSED int scan_ascii_lf(const char *buf, int len, uint16_t *ends) +static WSAP_VTCORE_NOINLINE WSAP_VTCORE_MAYBE_UNUSED int scan_ascii_lf(const char *buf, int len, uint16_t *ends) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return scan_ascii_lf_avx512(buf, len, ends); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return scan_ascii_lf_avx2(buf, len, ends); #endif int i = 0, count = 0; @@ -457,14 +457,14 @@ static TERM_NOINLINE TERM_MAYBE_UNUSED int scan_ascii_lf(const char *buf, int le uint32_t nl = 0, bad = 0; for (int q = 0; q < 2; q++) { uint8x16_t v = vld1q_u8((const uint8_t *)buf + i + q * 16); - nl |= (uint32_t)term_lane_bits(vceqq_u8(v, vdupq_n_u8('\n'))) << (q * 16); - bad |= (uint32_t)term_lane_bits(vcgeq_u8(vsubq_u8(v, vdupq_n_u8(0x20)), + nl |= (uint32_t)wsap_vtcore_lane_bits(vceqq_u8(v, vdupq_n_u8('\n'))) << (q * 16); + bad |= (uint32_t)wsap_vtcore_lane_bits(vcgeq_u8(vsubq_u8(v, vdupq_n_u8(0x20)), vdupq_n_u8(0x5f))) << (q * 16); } bad &= ~nl; if (bad) break; while (nl) { - ends[++count] = (uint16_t)(i + term_ctz32(nl) + 1); + ends[++count] = (uint16_t)(i + wsap_vtcore_ctz32(nl) + 1); nl &= nl - 1; } } @@ -472,8 +472,8 @@ static TERM_NOINLINE TERM_MAYBE_UNUSED int scan_ascii_lf(const char *buf, int le return scan_ascii_lf_tail(buf, i, len, ends, count); } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline void fill_cells_avx512(struct cell * restrict row, int cols, uint32_t fg, uint32_t bg) { __m128i cell = _mm_setr_epi32(' ', (int)fg, (int)bg, 0); @@ -496,8 +496,8 @@ static inline void fill_cells_avx512(struct cell * restrict row, int cols, uint3 } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline void fill_cells_avx2(struct cell * restrict row, int cols, uint32_t fg, uint32_t bg) { struct cell fill = { .c = ' ', .fg = fg, .bg = bg, .flags = 0, .pad = 0 }; @@ -519,21 +519,21 @@ static inline void fill_cells_avx2(struct cell * restrict row, int cols, uint32_ static inline void fill_cells(struct cell * restrict row, int cols, uint32_t fg, uint32_t bg) { struct cell fill = { .c = ' ', .fg = fg, .bg = bg, .flags = 0, .pad = 0 }; -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) { - if (TERM_EXPECT(cols > 0, 1)) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) { + if (WSAP_VTCORE_EXPECT(cols > 0, 1)) fill_cells_avx512(row, cols, fg, bg); return; } #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2() && TERM_EXPECT(cols >= 8, 1)) { +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2() && WSAP_VTCORE_EXPECT(cols >= 8, 1)) { fill_cells_avx2(row, cols, fg, bg); return; } #endif #if defined(__aarch64__) - if (TERM_EXPECT(cols > 0, 1)) { + if (WSAP_VTCORE_EXPECT(cols > 0, 1)) { uint32x4_t blank = { ' ', fg, bg, 0 }; uint32x4x4_t b4 = {{ blank, blank, blank, blank }}; int c = 0; @@ -571,11 +571,11 @@ static inline void fill_cells(struct cell * restrict row, int cols, uint32_t fg, static inline void clear_cells_default(struct cell *row, int cols) { - fill_cells(row, cols, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(row, cols, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline void put_ascii_chunk_avx512(struct cell * restrict dst, const char * restrict src, int n, uint32_t fg, uint32_t bg, uint32_t flags) { @@ -622,8 +622,8 @@ static inline void put_ascii_chunk_avx512(struct cell * restrict dst, const char } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline void put_ascii_chunk_avx2(struct cell * restrict dst, const char * restrict src, int n, uint32_t fg, uint32_t bg, uint32_t flags) { @@ -683,19 +683,19 @@ static inline void put_ascii_quad_neon(struct cell *dst, const char *src, } #endif -TERM_ALWAYS_INLINE +WSAP_VTCORE_ALWAYS_INLINE static inline void put_ascii_chunk(struct cell * restrict dst, const char * restrict src, int n, uint32_t fg, uint32_t bg, uint32_t flags) { /* A short chunk costs less inline than as a call. */ -#if defined(TERM_KERNEL_AVX512) - if (n >= 16 && term_use_avx512()) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (n >= 16 && wsap_vtcore_use_avx512()) { put_ascii_chunk_avx512(dst, src, n, fg, bg, flags); return; } #endif -#if defined(TERM_KERNEL_AVX2) - if (n >= 16 && term_use_avx2()) { +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (n >= 16 && wsap_vtcore_use_avx2()) { put_ascii_chunk_avx2(dst, src, n, fg, bg, flags); return; } diff --git a/src/meson.build b/src/meson.build index 7684275..ce91573 100644 --- a/src/meson.build +++ b/src/meson.build @@ -2,11 +2,11 @@ subdir('osc') # The SONAME carries the major version. An ABI break bumps it, so an old # binary keeps the old library. -term_soversion = meson.project_version().split('.')[0] +wsap_vtcore_soversion = meson.project_version().split('.')[0] # The x86-64 SIMD kernels pick their level at run time (see simd.h), so the # library needs no ISA flags. -march in c_args sets the lowest level. -term_lib = both_libraries('term', +wsap_vtcore_lib = both_libraries('wsap_vtcore', 'core.c', 'escape.c', 'fastcsi.c', @@ -23,12 +23,12 @@ term_lib = both_libraries('term', 'term.c', 'text.c', 'text_run.c', - term_osc_src, - include_directories: term_private_inc, + wsap_vtcore_osc_src, + include_directories: wsap_vtcore_private_inc, dependencies: [m_dep, thread_dep], gnu_symbol_visibility: 'hidden', version: meson.project_version(), - soversion: term_soversion, + soversion: wsap_vtcore_soversion, install: true ) diff --git a/src/osc/clipboard.c b/src/osc/clipboard.c index 4f550ba..b330ab8 100644 --- a/src/osc/clipboard.c +++ b/src/osc/clipboard.c @@ -65,7 +65,7 @@ static bool b64_decode(const char *s, size_t n, char *out, size_t *out_len) return true; } -void term_osc52(struct term *t, const char *params) +void wsap_vtcore_osc52(struct wsap_vtcore *t, const char *params) { const char *sep = strchr(params, ';'); if (!sep || sep == params) diff --git a/src/osc/dispatch.c b/src/osc/dispatch.c index 400adbf..442c2e8 100644 --- a/src/osc/dispatch.c +++ b/src/osc/dispatch.c @@ -9,18 +9,18 @@ #define OSC_HEAP_INIT 4096 #define OSC_HEAP_KEEP (1u << 20) -size_t term_osc_room(const struct term *t) +size_t wsap_vtcore_osc_room(const struct wsap_vtcore *t) { size_t cap = t->osc_heap ? t->osc_heap_cap : sizeof(t->osc_buf); return cap - 1 - (size_t)t->osc_len; } -char *term_osc_tail(struct term *t) +char *wsap_vtcore_osc_tail(struct wsap_vtcore *t) { return (t->osc_heap ? t->osc_heap : t->osc_buf) + t->osc_len; } -bool term_osc_grow(struct term *t) +bool wsap_vtcore_osc_grow(struct wsap_vtcore *t) { if (!t->osc_heap) { char *p = malloc(OSC_HEAP_INIT); @@ -30,9 +30,9 @@ bool term_osc_grow(struct term *t) t->osc_heap_cap = OSC_HEAP_INIT; return true; } - if (t->osc_heap_cap >= TERM_OSC_MAX) return false; + if (t->osc_heap_cap >= WSAP_VTCORE_OSC_MAX) return false; size_t cap = t->osc_heap_cap * 2; - if (cap > TERM_OSC_MAX) cap = TERM_OSC_MAX; + if (cap > WSAP_VTCORE_OSC_MAX) cap = WSAP_VTCORE_OSC_MAX; char *p = realloc(t->osc_heap, cap); if (!p) return false; t->osc_heap = p; @@ -40,7 +40,7 @@ bool term_osc_grow(struct term *t) return true; } -void term_osc_cleanup(struct term *t) +void wsap_vtcore_osc_cleanup(struct wsap_vtcore *t) { free(t->osc_heap); t->osc_heap = NULL; @@ -48,7 +48,7 @@ void term_osc_cleanup(struct term *t) free(t->dcs_buf); t->dcs_buf = NULL; t->dcs_cap = 0; - term_osc8_cleanup(t); + wsap_vtcore_osc8_cleanup(t); free(t->cwd); t->cwd = NULL; free(t->pointer_shape); @@ -57,7 +57,7 @@ void term_osc_cleanup(struct term *t) /* Reply to a color query. An OSC 4 reply names the index it answers for; * index is negative for OSC 10, 11, and 12. */ -static void send_color_query_reply(struct term *t, int code, int index, uint32_t argb) +static void send_color_query_reply(struct wsap_vtcore *t, int code, int index, uint32_t argb) { char resp[64], prefix[16] = ""; uint8_t r = (argb >> 16) & 0xff, g = (argb >> 8) & 0xff, b = argb & 0xff; @@ -69,15 +69,15 @@ static void send_color_query_reply(struct term *t, int code, int index, uint32_t send_response(t, resp); } -static void osc_color_set_or_query(struct term *t, int code, const char *params, int slot) +static void osc_color_set_or_query(struct wsap_vtcore *t, int code, const char *params, int slot) { if (!strcmp(params, "?")) { send_color_query_reply(t, code, -1, t->palette.colors[slot]); return; } uint32_t argb; - if (term_color_parse(params, &argb)) - term_palette_set(&t->palette, slot, argb); + if (wsap_vtcore_color_parse(params, &argb)) + wsap_vtcore_palette_set(&t->palette, slot, argb); } static long osc_next_index(const char **pp) @@ -91,7 +91,7 @@ static long osc_next_index(const char **pp) return idx; } -static void osc4_handle(struct term *t, const char *params) +static void osc4_handle(struct wsap_vtcore *t, const char *params) { const char *p = params; while (*p) { @@ -113,8 +113,8 @@ static void osc4_handle(struct term *t, const char *params) memcpy(buf, spec, spec_len); buf[spec_len] = '\0'; uint32_t argb; - if (term_color_parse(buf, &argb)) - term_palette_set(&t->palette, (int)idx, argb); + if (wsap_vtcore_color_parse(buf, &argb)) + wsap_vtcore_palette_set(&t->palette, (int)idx, argb); } } p = spec_end; @@ -122,10 +122,10 @@ static void osc4_handle(struct term *t, const char *params) } } -static void osc104_handle(struct term *t, const char *params) +static void osc104_handle(struct wsap_vtcore *t, const char *params) { if (!*params) { - term_palette_reset_all(&t->palette); + wsap_vtcore_palette_reset_all(&t->palette); return; } const char *p = params; @@ -134,13 +134,13 @@ static void osc104_handle(struct term *t, const char *params) if (idx < 0) return; if (idx <= 255) - term_palette_reset(&t->palette, (int)idx); + wsap_vtcore_palette_reset(&t->palette, (int)idx); } } -void term_osc_finish(struct term *t) +void wsap_vtcore_osc_finish(struct wsap_vtcore *t) { - if (!term_str_was_truncated(t)) { + if (!wsap_vtcore_str_was_truncated(t)) { char *buf = t->osc_heap ? t->osc_heap : t->osc_buf; buf[t->osc_len] = '\0'; @@ -175,34 +175,34 @@ void term_osc_finish(struct term *t) osc4_handle(t, params); break; case 8: - term_osc8(t, params); + wsap_vtcore_osc8(t, params); break; case 10: - osc_color_set_or_query(t, 10, params, TERM_PALETTE_FG); + osc_color_set_or_query(t, 10, params, WSAP_VTCORE_PALETTE_FG); break; case 11: - osc_color_set_or_query(t, 11, params, TERM_PALETTE_BG); + osc_color_set_or_query(t, 11, params, WSAP_VTCORE_PALETTE_BG); break; case 12: - osc_color_set_or_query(t, 12, params, TERM_PALETTE_CURSOR); + osc_color_set_or_query(t, 12, params, WSAP_VTCORE_PALETTE_CURSOR); break; case 52: - term_osc52(t, params); + wsap_vtcore_osc52(t, params); break; case 104: osc104_handle(t, params); break; case 110: - term_palette_reset(&t->palette, TERM_PALETTE_FG); + wsap_vtcore_palette_reset(&t->palette, WSAP_VTCORE_PALETTE_FG); break; case 111: - term_palette_reset(&t->palette, TERM_PALETTE_BG); + wsap_vtcore_palette_reset(&t->palette, WSAP_VTCORE_PALETTE_BG); break; case 112: - term_palette_reset(&t->palette, TERM_PALETTE_CURSOR); + wsap_vtcore_palette_reset(&t->palette, WSAP_VTCORE_PALETTE_CURSOR); break; default: - term_osc_misc_dispatch(t, code, params); + wsap_vtcore_osc_misc_dispatch(t, code, params); break; } } diff --git a/src/osc/link.c b/src/osc/link.c index f31a750..363a568 100644 --- a/src/osc/link.c +++ b/src/osc/link.c @@ -4,15 +4,15 @@ #include <stdlib.h> #include <string.h> -#define TERM_LINK_MAX 8192 -#define TERM_LINK_URI_MAX 4096 +#define WSAP_VTCORE_LINK_MAX 8192 +#define WSAP_VTCORE_LINK_URI_MAX 4096 struct link_hash_slot { uint64_t hash; uint16_t id; }; -struct term_links { +struct wsap_vtcore_links { char **uri; uint16_t *free_ids; struct link_hash_slot *hash_table; @@ -31,7 +31,7 @@ static inline uint64_t hash_uri(const char *s) return h ? h : 1; } -static void links_insert_hash(struct term_links *l, uint64_t h, uint16_t id) +static void links_insert_hash(struct wsap_vtcore_links *l, uint64_t h, uint16_t id) { if (!l->hash_table || !l->hash_cap) return; @@ -48,9 +48,9 @@ static void links_insert_hash(struct term_links *l, uint64_t h, uint16_t id) } } -static bool links_grow(struct term_links *l) +static bool links_grow(struct wsap_vtcore_links *l) { - uint16_t new_cap = l->capacity == 0 ? 64 : l->capacity < 4096 ? l->capacity * 2 : TERM_LINK_MAX; + uint16_t new_cap = l->capacity == 0 ? 64 : l->capacity < 4096 ? l->capacity * 2 : WSAP_VTCORE_LINK_MAX; if (new_cap <= l->capacity) return false; char **new_uri = realloc(l->uri, sizeof(char *) * new_cap); @@ -89,7 +89,7 @@ static bool links_grow(struct term_links *l) static void links_mark_row(const struct cell *row, int len, uint64_t *mark, uint16_t cap) { - if (len > TERM_MAX_COLS) len = TERM_MAX_COLS; + if (len > WSAP_VTCORE_MAX_COLS) len = WSAP_VTCORE_MAX_COLS; for (int i = 0; i < len; i++) { uint16_t id = row[i].pad; if (id && id <= cap) @@ -123,19 +123,19 @@ static void links_mark_screen(const struct screen *s, struct links_mark *m) if (row->kind == ROW_CELLS) links_mark_row(row->cells, row->len, m->mark, m->cap); else - term_hist_text_mark_links(&row->text, links_mark_hist, m); + wsap_vtcore_hist_text_mark_links(&row->text, links_mark_hist, m); } } -static void links_gc(struct term *t, struct term_links *l) +static void links_gc(struct wsap_vtcore *t, struct wsap_vtcore_links *l) { - uint64_t mark[TERM_LINK_MAX / 64] = { 0 }; + uint64_t mark[WSAP_VTCORE_LINK_MAX / 64] = { 0 }; struct links_mark m = { mark, l->capacity }; links_mark_id(t->cur_link, mark, l->capacity); links_mark_screen(&t->scr, &m); if (t->alternate && t->alt_allocated) links_mark_screen(&t->alt_scr, &m); - term_hist_mark_links(&t->hist, links_mark_hist, &m); + wsap_vtcore_hist_mark_links(&t->hist, links_mark_hist, &m); l->free_count = 0; for (int i = 0; i + 1 < l->next; i++) { if (l->uri[i] && !(mark[i >> 6] & (1ull << (i & 63)))) { @@ -154,7 +154,7 @@ static void links_gc(struct term *t, struct term_links *l) } } -static uint16_t links_find(const struct term_links *l, const char *uri, uint64_t h) +static uint16_t links_find(const struct wsap_vtcore_links *l, const char *uri, uint64_t h) { if (!l->hash_table || !l->hash_cap) return 0; @@ -174,7 +174,7 @@ static uint16_t links_find(const struct term_links *l, const char *uri, uint64_t return 0; } -static uint16_t links_alloc(struct term *t, struct term_links *l) +static uint16_t links_alloc(struct wsap_vtcore *t, struct wsap_vtcore_links *l) { if (l->free_count) return l->free_ids[--l->free_count]; @@ -186,7 +186,7 @@ static uint16_t links_alloc(struct term *t, struct term_links *l) return 0; } -void term_osc8(struct term *t, const char *params) +void wsap_vtcore_osc8(struct wsap_vtcore *t, const char *params) { const char *sep = strchr(params, ';'); if (!sep) @@ -196,11 +196,11 @@ void term_osc8(struct term *t, const char *params) t->cur_link = 0; return; } - if (strlen(uri) > TERM_LINK_URI_MAX) { + if (strlen(uri) > WSAP_VTCORE_LINK_URI_MAX) { t->cur_link = 0; return; } - struct term_links *l = t->links; + struct wsap_vtcore_links *l = t->links; if (!l) { l = calloc(1, sizeof(*l)); if (!l) { @@ -218,7 +218,7 @@ void term_osc8(struct term *t, const char *params) t->cur_link = 0; return; } - l->uri[id - 1] = term_strdup(uri); + l->uri[id - 1] = wsap_vtcore_strdup(uri); if (!l->uri[id - 1]) { l->free_ids[l->free_count++] = id; t->cur_link = 0; @@ -229,12 +229,12 @@ void term_osc8(struct term *t, const char *params) t->cur_link = id; } -const char *term_osc8_url_at(const struct term *t, int col, int row) +const char *wsap_vtcore_osc8_url_at(const struct wsap_vtcore *t, int col, int row) { - const struct term_links *l = t->links; + const struct wsap_vtcore_links *l = t->links; if (!l || col < 0 || col >= t->cols) return NULL; - const struct cell *cells = term_screen_view_row(t, row); + const struct cell *cells = wsap_vtcore_screen_view_row(t, row); if (!cells) return NULL; uint16_t id = cells[col].pad; @@ -244,9 +244,9 @@ const char *term_osc8_url_at(const struct term *t, int col, int row) return l->uri[id - 1]; } -void term_osc8_cleanup(struct term *t) +void wsap_vtcore_osc8_cleanup(struct wsap_vtcore *t) { - struct term_links *l = t->links; + struct wsap_vtcore_links *l = t->links; if (!l) return; for (uint16_t i = 0; i < l->capacity; i++) diff --git a/src/osc/meson.build b/src/osc/meson.build index a3b9efa..efe79c2 100644 --- a/src/osc/meson.build +++ b/src/osc/meson.build @@ -1,4 +1,4 @@ -term_osc_src = files( +wsap_vtcore_osc_src = files( 'clipboard.c', 'dispatch.c', 'link.c', diff --git a/src/osc/misc.c b/src/osc/misc.c index 74b35cf..243c2ec 100644 --- a/src/osc/misc.c +++ b/src/osc/misc.c @@ -3,9 +3,9 @@ #include <stdlib.h> #include <string.h> -static void osc7_cwd(struct term *t, const char *uri) +static void osc7_cwd(struct wsap_vtcore *t, const char *uri) { - if (!term_has_prefix_ci(uri, "file://")) + if (!wsap_vtcore_has_prefix_ci(uri, "file://")) return; const char *p = uri + 7; const char *slash = strchr(p, '/'); @@ -16,8 +16,8 @@ static void osc7_cwd(struct term *t, const char *uri) char *d = cwd; while (*path) { int hi, lo; - if (*path == '%' && (hi = term_hex_nib(path[1])) >= 0 && - (lo = term_hex_nib(path[2])) >= 0) { + if (*path == '%' && (hi = wsap_vtcore_hex_nib(path[1])) >= 0 && + (lo = wsap_vtcore_hex_nib(path[2])) >= 0) { *d++ = (char)(hi * 16 + lo); path += 3; } else { @@ -29,7 +29,7 @@ static void osc7_cwd(struct term *t, const char *uri) t->cwd = cwd; } -static void osc777_notify(struct term *t, const char *params) +static void osc777_notify(struct wsap_vtcore *t, const char *params) { if (strncmp(params, "notify;", 7)) return; @@ -43,7 +43,7 @@ static void osc777_notify(struct term *t, const char *params) *wsep = ';'; } -void term_osc_misc_dispatch(struct term *t, long code, const char *params) +void wsap_vtcore_osc_misc_dispatch(struct wsap_vtcore *t, long code, const char *params) { if (!params) return; @@ -57,7 +57,7 @@ void term_osc_misc_dispatch(struct term *t, long code, const char *params) break; case 22: free(t->pointer_shape); - t->pointer_shape = *params ? term_strdup(params) : NULL; + t->pointer_shape = *params ? wsap_vtcore_strdup(params) : NULL; break; case 777: if (t->cb.notify) diff --git a/src/osc/osc.h b/src/osc/osc.h index 1d6680e..735e483 100644 --- a/src/osc/osc.h +++ b/src/osc/osc.h @@ -1,27 +1,27 @@ -#ifndef TERM_OSC_H -#define TERM_OSC_H +#ifndef WSAP_VTCORE_OSC_H +#define WSAP_VTCORE_OSC_H #include <stdbool.h> #include <stddef.h> #include <stdint.h> -struct term; +struct wsap_vtcore; -#define TERM_OSC_MAX (16u << 20) +#define WSAP_VTCORE_OSC_MAX (16u << 20) -size_t term_osc_room(const struct term *t); -char *term_osc_tail(struct term *t); -bool term_osc_grow(struct term *t); +size_t wsap_vtcore_osc_room(const struct wsap_vtcore *t); +char *wsap_vtcore_osc_tail(struct wsap_vtcore *t); +bool wsap_vtcore_osc_grow(struct wsap_vtcore *t); -void term_osc_finish(struct term *t); +void wsap_vtcore_osc_finish(struct wsap_vtcore *t); -void term_osc_cleanup(struct term *t); +void wsap_vtcore_osc_cleanup(struct wsap_vtcore *t); -void term_osc8(struct term *t, const char *params); -void term_osc52(struct term *t, const char *params); -void term_osc_misc_dispatch(struct term *t, long code, const char *params); +void wsap_vtcore_osc8(struct wsap_vtcore *t, const char *params); +void wsap_vtcore_osc52(struct wsap_vtcore *t, const char *params); +void wsap_vtcore_osc_misc_dispatch(struct wsap_vtcore *t, long code, const char *params); -const char *term_osc8_url_at(const struct term *t, int col, int row); -void term_osc8_cleanup(struct term *t); +const char *wsap_vtcore_osc8_url_at(const struct wsap_vtcore *t, int col, int row); +void wsap_vtcore_osc8_cleanup(struct wsap_vtcore *t); #endif diff --git a/src/palette.c b/src/palette.c index 610fe52..ab7d7a6 100644 --- a/src/palette.c +++ b/src/palette.c @@ -81,7 +81,7 @@ static inline float linf_to_srgbf(float c) : 12.92f * c; } -static const struct term_theme builtin_theme = { +static const struct wsap_vtcore_theme builtin_theme = { .fg = 0xFFFFFFFFu, .bg = 0xFF1E1E2Eu, .cursor = 0xFF89B4FAu, @@ -93,12 +93,12 @@ static const struct term_theme builtin_theme = { }, }; -void term_theme_default(struct term_theme *theme) +void wsap_vtcore_theme_default(struct wsap_vtcore_theme *theme) { *theme = builtin_theme; } -static const struct term_theme high_contrast_theme = { +static const struct wsap_vtcore_theme high_contrast_theme = { .fg = 0xFFFFFFFFu, .bg = 0xFF000000u, .cursor = 0xFF00FFFFu, @@ -110,14 +110,14 @@ static const struct term_theme high_contrast_theme = { }, }; -void term_theme_high_contrast(struct term_theme *theme) +void wsap_vtcore_theme_high_contrast(struct wsap_vtcore_theme *theme) { *theme = high_contrast_theme; } /* Finds the slot for key and the default it resets to. Keys are * foreground, background, and color0 to color15. */ -static uint32_t *palette_slot(struct term_theme *p, const char *key, +static uint32_t *palette_slot(struct wsap_vtcore_theme *p, const char *key, uint32_t *fallback) { if (!strcmp(key, "foreground")) { @@ -145,7 +145,7 @@ static uint32_t *palette_slot(struct term_theme *p, const char *key, return &p->ansi[i]; } -bool term_theme_set_key(struct term_theme *p, const char *key, const char *val) +bool wsap_vtcore_theme_set_key(struct wsap_vtcore_theme *p, const char *key, const char *val) { if (!p || !key || !val) return false; @@ -158,7 +158,7 @@ bool term_theme_set_key(struct term_theme *p, const char *key, const char *val) return true; } uint32_t v; - if (!term_color_parse(val, &v)) + if (!wsap_vtcore_color_parse(val, &v)) return false; *slot = v; return true; @@ -167,7 +167,7 @@ bool term_theme_set_key(struct term_theme *p, const char *key, const char *val) static bool parse_hex_channel(const char *s, size_t len, uint8_t *out) { if (len == 2) { - int d0 = term_hex_nib(s[0]), d1 = term_hex_nib(s[1]); + int d0 = wsap_vtcore_hex_nib(s[0]), d1 = wsap_vtcore_hex_nib(s[1]); if ((d0 | d1) < 0) return false; *out = (uint8_t)((d0 << 4) | d1); @@ -177,7 +177,7 @@ static bool parse_hex_channel(const char *s, size_t len, uint8_t *out) return false; unsigned value = 0; for (size_t i = 0; i < len; i++) { - int d = term_hex_nib(s[i]); + int d = wsap_vtcore_hex_nib(s[i]); if (d < 0) return false; value = (value << 4) | (unsigned)d; @@ -234,11 +234,11 @@ static bool parse_hex_rgb(const char *s, size_t cw, uint32_t *out) !parse_hex_channel(s + cw, cw, &g) || !parse_hex_channel(s + 2 * cw, cw, &b)) return false; - *out = term_rgb(r, g, b); + *out = wsap_vtcore_rgb(r, g, b); return true; } -bool term_color_parse(const char *input, uint32_t *out) +bool wsap_vtcore_color_parse(const char *input, uint32_t *out) { if (!input || !out) return false; @@ -294,7 +294,7 @@ bool term_color_parse(const char *input, uint32_t *out) parse_hex_channel(channels[j], chlens[j], &c[j]); if (!ok) return false; } - *out = term_rgb(c[0], c[1], c[2]); + *out = wsap_vtcore_rgb(c[0], c[1], c[2]); return true; } @@ -357,7 +357,7 @@ static uint32_t lab_to_rgb(struct lab lab) float g = linf_to_srgbf(-xf * 0.9692660f + yf * 1.8760108f + zf * 0.0415560f); float b = linf_to_srgbf(xf * 0.0556434f - yf * 0.2040259f + zf * 1.0572252f); - return term_rgb(quantize_channel(r), quantize_channel(g), quantize_channel(b)); + return wsap_vtcore_rgb(quantize_channel(r), quantize_channel(g), quantize_channel(b)); } static struct lab lab_lerp(float t, struct lab a, struct lab b) @@ -375,7 +375,7 @@ static struct lab lab_lerp(float t, struct lab a, struct lab b) * between the background, the ANSI colors, and the foreground, so they match * the theme instead of the fixed xterm values. */ -static void derive_palette(uint32_t *p, const struct term_theme *theme) +static void derive_palette(uint32_t *p, const struct wsap_vtcore_theme *theme) { struct lab base8[8]; base8[0] = lab_from_rgb(theme->bg); @@ -385,9 +385,9 @@ static void derive_palette(uint32_t *p, const struct term_theme *theme) for (int i = 0; i < 16; i++) p[i] = theme->ansi[i]; - p[TERM_PALETTE_FG] = theme->fg; - p[TERM_PALETTE_BG] = theme->bg; - p[TERM_PALETTE_CURSOR] = theme->cursor; + p[WSAP_VTCORE_PALETTE_FG] = theme->fg; + p[WSAP_VTCORE_PALETTE_BG] = theme->bg; + p[WSAP_VTCORE_PALETTE_CURSOR] = theme->cursor; bool is_light_theme = base8[7].l < base8[0].l; if (is_light_theme) { @@ -427,9 +427,9 @@ static void derive_palette(uint32_t *p, const struct term_theme *theme) } } -void term_palette_init(struct palette *p, const struct term_theme *theme) +void wsap_vtcore_palette_init(struct palette *p, const struct wsap_vtcore_theme *theme) { - static const struct term_theme zero; + static const struct wsap_vtcore_theme zero; p->theme = theme && memcmp(theme, &zero, sizeof(zero)) ? *theme : builtin_theme; if (!p->theme.cursor) p->theme.cursor = builtin_theme.cursor; @@ -438,21 +438,21 @@ void term_palette_init(struct palette *p, const struct term_theme *theme) p->version++; } -void term_palette_set(struct palette *p, int slot, uint32_t argb) +void wsap_vtcore_palette_set(struct palette *p, int slot, uint32_t argb) { - if ((unsigned)slot >= TERM_PALETTE_SIZE || p->colors[slot] == argb) + if ((unsigned)slot >= WSAP_VTCORE_PALETTE_SIZE || p->colors[slot] == argb) return; p->colors[slot] = argb; p->version++; } -void term_palette_reset(struct palette *p, int slot) +void wsap_vtcore_palette_reset(struct palette *p, int slot) { - if ((unsigned)slot < TERM_PALETTE_SIZE) - term_palette_set(p, slot, p->base[slot]); + if ((unsigned)slot < WSAP_VTCORE_PALETTE_SIZE) + wsap_vtcore_palette_set(p, slot, p->base[slot]); } -void term_palette_reset_all(struct palette *p) +void wsap_vtcore_palette_reset_all(struct palette *p) { if (memcmp(p->colors, p->base, sizeof(p->colors))) { memcpy(p->colors, p->base, sizeof(p->colors)); diff --git a/src/palette.h b/src/palette.h index 083ad8d..b5ac284 100644 --- a/src/palette.h +++ b/src/palette.h @@ -1,10 +1,10 @@ -#ifndef TERM_PALETTE_H -#define TERM_PALETTE_H +#ifndef WSAP_VTCORE_PALETTE_H +#define WSAP_VTCORE_PALETTE_H #include <stdbool.h> #include <stdint.h> -#include "term.h" +#include "wsap_vtcore.h" /* * The colors of one terminal. base holds the colors that the theme gives; @@ -12,18 +12,18 @@ * 10, 11, or 12. version changes whenever colors changes. */ struct palette { - uint32_t colors[TERM_PALETTE_SIZE]; - uint32_t base[TERM_PALETTE_SIZE]; - struct term_theme theme; + uint32_t colors[WSAP_VTCORE_PALETTE_SIZE]; + uint32_t base[WSAP_VTCORE_PALETTE_SIZE]; + struct wsap_vtcore_theme theme; uint64_t version; }; /* Set every entry from theme. An all-zero theme selects the built-in theme. */ -void term_palette_init(struct palette *p, const struct term_theme *theme); -/* Change one entry (0-255, TERM_PALETTE_FG, _BG, or _CURSOR). */ -void term_palette_set(struct palette *p, int slot, uint32_t argb); +void wsap_vtcore_palette_init(struct palette *p, const struct wsap_vtcore_theme *theme); +/* Change one entry (0-255, WSAP_VTCORE_PALETTE_FG, _BG, or _CURSOR). */ +void wsap_vtcore_palette_set(struct palette *p, int slot, uint32_t argb); /* Restore one entry, or all entries, to the theme color. */ -void term_palette_reset(struct palette *p, int slot); -void term_palette_reset_all(struct palette *p); +void wsap_vtcore_palette_reset(struct palette *p, int slot); +void wsap_vtcore_palette_reset_all(struct palette *p); #endif @@ -2,12 +2,12 @@ #define WSAP_TERM_PEN_H #include "compat.h" -#include "term.h" +#include "wsap_vtcore.h" #include <stdbool.h> #include <stdint.h> #include <string.h> -struct term_pen { +struct wsap_vtcore_pen { uint32_t fg; uint32_t bg; uint32_t ul; @@ -71,12 +71,12 @@ static inline void pen_set_text(struct pen_attr *p, struct text_pen pen) static inline struct pen_attr pen_attr_default(void) { - return (struct pen_attr){ .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }; + return (struct pen_attr){ .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }; } static inline bool pen_attr_is_default(const struct pen_attr *a) { - return a->fg == TERM_COLOR_FG && a->bg == TERM_COLOR_BG && a->flags == 0 && a->link == 0; + return a->fg == WSAP_VTCORE_COLOR_FG && a->bg == WSAP_VTCORE_COLOR_BG && a->flags == 0 && a->link == 0; } static inline bool pen_attr_equal(const struct pen_attr *a, const struct pen_attr *b) @@ -84,15 +84,15 @@ static inline bool pen_attr_equal(const struct pen_attr *a, const struct pen_att return a->fg == b->fg && a->bg == b->bg && a->flags == b->flags && a->link == b->link; } -static inline uint32_t term_rgb(int r, int g, int b) +static inline uint32_t wsap_vtcore_rgb(int r, int g, int b) { - return term_color_rgb((uint8_t)r, (uint8_t)g, (uint8_t)b); + return wsap_vtcore_color_rgb((uint8_t)r, (uint8_t)g, (uint8_t)b); } -static inline void pen_reset(struct term_pen *p) +static inline void pen_reset(struct wsap_vtcore_pen *p) { - p->fg = TERM_COLOR_FG; - p->bg = TERM_COLOR_BG; + p->fg = WSAP_VTCORE_COLOR_FG; + p->bg = WSAP_VTCORE_COLOR_BG; p->ul = 0; p->underline = 0; p->bold = false; @@ -112,7 +112,7 @@ static inline int sgr_extended_color(const int *params, int nparams, uint16_t su if (i + 2 < nparams && params[i + 1] == 5) { int index = params[i + 2]; if (index >= 0 && index <= 255) { - *color = term_color_index(index); + *color = wsap_vtcore_color_index(index); *assigned = true; } return 2; @@ -123,7 +123,7 @@ static inline int sgr_extended_color(const int *params, int nparams, uint16_t su int k = i + 2; if (k < 16 && k < nparams) { uint32_t shifted = (~(uint32_t)subparams) >> k; - colon = term_ctz32(shifted); + colon = wsap_vtcore_ctz32(shifted); int max_colon = (nparams < 16 ? nparams : 16) - k; if (colon > max_colon) colon = max_colon; @@ -131,27 +131,27 @@ static inline int sgr_extended_color(const int *params, int nparams, uint16_t su int skip = colon >= 4 ? 1 : 0; if (i + 4 + skip >= nparams) return 0; - *color = term_rgb(params[i + 2 + skip], params[i + 3 + skip], params[i + 4 + skip]); + *color = wsap_vtcore_rgb(params[i + 2 + skip], params[i + 3 + skip], params[i + 4 + skip]); *assigned = true; return 4 + skip; } -static inline bool pen_set_standard_color(struct term_pen *p, int code) +static inline bool pen_set_standard_color(struct wsap_vtcore_pen *p, int code) { if ((unsigned)(code - 30) < 8) - p->fg = term_color_index(code - 30); + p->fg = wsap_vtcore_color_index(code - 30); else if ((unsigned)(code - 40) < 8) - p->bg = term_color_index(code - 40); + p->bg = wsap_vtcore_color_index(code - 40); else if ((unsigned)(code - 90) < 8) - p->fg = term_color_index(code - 90 + 8); + p->fg = wsap_vtcore_color_index(code - 90 + 8); else if ((unsigned)(code - 100) < 8) - p->bg = term_color_index(code - 100 + 8); + p->bg = wsap_vtcore_color_index(code - 100 + 8); else return false; return true; } -static inline void sgr_apply(struct term_pen *pen, const int *params, int nparams, uint16_t subparams) +static inline void sgr_apply(struct wsap_vtcore_pen *pen, const int *params, int nparams, uint16_t subparams) { if (nparams == 0) { pen_reset(pen); @@ -185,14 +185,14 @@ static inline void sgr_apply(struct term_pen *pen, const int *params, int nparam if (ok) pen->fg = c; break; } - case 39: pen->fg = TERM_COLOR_FG; break; + case 39: pen->fg = WSAP_VTCORE_COLOR_FG; break; case 48: { uint32_t c; bool ok; i += sgr_extended_color(params, nparams, subparams, i, &c, &ok); if (ok) pen->bg = c; break; } - case 49: pen->bg = TERM_COLOR_BG; break; + case 49: pen->bg = WSAP_VTCORE_COLOR_BG; break; case 53: pen->overline = true; break; case 55: pen->overline = false; break; case 58: { @@ -1,11 +1,11 @@ #include "compat.h" #include "kernels.h" -#include "term.h" +#include "wsap_vtcore.h" -TERM_HOT -size_t term_scan_printable_span(const char *buf, size_t len, unsigned char hi) +WSAP_VTCORE_HOT +size_t wsap_vtcore_scan_printable_span(const char *buf, size_t len, unsigned char hi) { /* The only entry point that can run before the first terminal. */ - term_isa_init(); + wsap_vtcore_isa_init(); return scan_printable_span(buf, len, hi); } diff --git a/src/screen.c b/src/screen.c index ab6989a..8b1b5ce 100644 --- a/src/screen.c +++ b/src/screen.c @@ -10,7 +10,7 @@ static void *grow(struct grow_buf *b, size_t bytes) { if (bytes > b->cap) { - size_t cap = term_grow_cap(b->cap ? b->cap : 256, bytes); + size_t cap = wsap_vtcore_grow_cap(b->cap ? b->cap : 256, bytes); void *data = realloc(b->data, cap); if (!data) return NULL; @@ -52,7 +52,7 @@ static bool screen_setup(struct screen *s, int cols, int rows, uint64_t *next_ui s->text_slab = text_slab; s->text_cap = bytes; } - fill_cells(s->cells_slab, (int)cells, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(s->cells_slab, (int)cells, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); s->rows = rows; s->cols = cols; s->top = 0; @@ -79,7 +79,7 @@ static bool screen_setup(struct screen *s, int cols, int rows, uint64_t *next_ui return true; } -static void screen_push_row_inner(struct term *t, struct srow *row) +static void screen_push_row_inner(struct wsap_vtcore *t, struct srow *row) { srow_materialize_text(row); bool wrapped = (row->flags & RF_WRAPPED) != 0; @@ -93,27 +93,27 @@ static void screen_push_row_inner(struct term *t, struct srow *row) memset(tr->text + tr->text_len, ' ', (size_t)fill); text_commit(row, fill, fill, fill, HLINE_NARROW, (struct text_pen){ tr->fill.fg, tr->fill.bg, 0 }); } - term_hist_push_text(&t->hist, tr, wrapped); + wsap_vtcore_hist_push_text(&t->hist, tr, wrapped); return; } /* The rest of a wrapped row is part of the line: blanks up to the edge. */ - if (TERM_EXPECT(wrapped && row->len < cols, 0)) { + if (WSAP_VTCORE_EXPECT(wrapped && row->len < cols, 0)) { srow_settle(row, cols); if (!(row->flags & RF_TAIL_PADDED)) - fill_cells(row->cells + row->len, cols - row->len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(row->cells + row->len, cols - row->len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); row->flags |= RF_TAIL_PADDED; row->len = (uint16_t)cols; } - term_hist_push_row(&t->hist, row->cells, row->len, wrapped, t->gstore); + wsap_vtcore_hist_push_row(&t->hist, row->cells, row->len, wrapped, t->gstore); } -void term_screen_push_row(struct term *t, struct srow *row) +void wsap_vtcore_screen_push_row(struct wsap_vtcore *t, struct srow *row) { screen_push_row_inner(t, row); /* The push can drop more rows than it adds, so the view learns the new * history size here and not before. */ - if (TERM_EXPECT(t->view.anchor.active, 0)) - term_hist_view_note_push(&t->view, &t->hist, t->cols); + if (WSAP_VTCORE_EXPECT(t->view.anchor.active, 0)) + wsap_vtcore_hist_view_note_push(&t->view, &t->hist, t->cols); } static void screen_free(struct screen *s) @@ -127,35 +127,35 @@ static void screen_free(struct screen *s) } /* Read the history count without changing its rows. */ -int term_screen_history_rows(const struct term *t) +int wsap_vtcore_screen_history_rows(const struct wsap_vtcore *t) { if (!t || !screen_has_history(t)) return 0; - uint64_t rows = term_hist_view_rows(&t->view, &t->hist, t->cols); + uint64_t rows = wsap_vtcore_hist_view_rows(&t->view, &t->hist, t->cols); return rows > INT_MAX ? INT_MAX : (int)rows; } -int term_history_rows(const struct term *t) +int wsap_vtcore_history_rows(const struct wsap_vtcore *t) { if (!t) return 0; - term_write_begin((struct term *)t); - int rows = term_screen_history_rows(t); - term_write_end((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + int rows = wsap_vtcore_screen_history_rows(t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return rows; } -const struct cell *term_screen_view_row(const struct term *t, int y) +const struct cell *wsap_vtcore_screen_view_row(const struct wsap_vtcore *t, int y) { if (!t || y < 0 || y >= t->rows) return NULL; struct hist_view_pos pos; - if (term_hist_view_row_pos(&t->view, &t->hist, t->cols, t->rows, screen_top_line(t), y, &pos)) { + if (wsap_vtcore_hist_view_row_pos(&t->view, &t->hist, t->cols, t->rows, screen_top_line(t), y, &pos)) { struct cell *out = t->view_row_scratch; - int got = term_hist_decode_segment(&t->hist, pos.id, pos.seg, t->cols, out, t->gstore); + int got = wsap_vtcore_hist_decode_segment(&t->hist, pos.id, pos.seg, t->cols, out, t->gstore); if (got < t->cols) { - fill_cells(out + got, t->cols - got, TERM_COLOR_FG, TERM_COLOR_BG); - int line_rows = term_hist_line_rows(&t->hist, pos.id, t->cols); + fill_cells(out + got, t->cols - got, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); + int line_rows = wsap_vtcore_hist_line_rows(&t->hist, pos.id, t->cols); if (pos.seg + 1 < line_rows || (pos.id + 1 == hist_end_id(&t->hist) && hist_is_open(&t->hist))) set_cells_wrap_pad(out + got, t->cols - got); } @@ -170,7 +170,7 @@ const struct cell *term_screen_view_row(const struct term *t, int y) return srow->cells; if (srow->len > 0) memcpy(out, srow->cells, (size_t)srow->len * sizeof(struct cell)); - fill_cells(out + srow->len, t->cols - srow->len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(out + srow->len, t->cols - srow->len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); return out; } text_row_cells(srow, out, t->cols); @@ -186,14 +186,14 @@ static inline uint64_t mix64(uint64_t x) return x ^ (x >> 33); } -uint64_t term_screen_view_row_key(const struct term *t, int y) +uint64_t wsap_vtcore_screen_view_row_key(const struct wsap_vtcore *t, int y) { if (!t || y < 0 || y >= t->rows) return 0; struct hist_view_pos pos; - if (term_hist_view_row_pos(&t->view, &t->hist, t->cols, t->rows, screen_top_line(t), y, &pos)) { + if (wsap_vtcore_hist_view_row_pos(&t->view, &t->hist, t->cols, t->rows, screen_top_line(t), y, &pos)) { uint64_t line_ver = (pos.id + 1 == hist_end_id(&t->hist) && hist_is_open(&t->hist)) - ? (term_hist_line_cells(&t->hist, pos.id) << 32) : 0; + ? (wsap_vtcore_hist_line_cells(&t->hist, pos.id) << 32) : 0; if (pos.id == t->hist.base_cell_id) line_ver ^= mix64(t->hist.base_cell); return mix64(((uint64_t)pos.id << 16) ^ (uint64_t)pos.seg ^ line_ver ^ 0x517cc1b727220a95ull); @@ -204,62 +204,62 @@ uint64_t term_screen_view_row_key(const struct term *t, int y) return mix64(row->uid ^ ((uint64_t)row->version << 32)); } -int term_view_offset(const struct term *t) +int wsap_vtcore_view_offset(const struct wsap_vtcore *t) { if (!t) return 0; - return term_hist_view_scroll_offset(&t->view, &t->hist, t->cols); + return wsap_vtcore_hist_view_scroll_offset(&t->view, &t->hist, t->cols); } -void term_scroll_to(struct term *t, int offset) +void wsap_vtcore_scroll_to(struct wsap_vtcore *t, int offset) { if (!t) return; - term_write_begin(t); + wsap_vtcore_write_begin(t); if (t->alternate || offset < 0) offset = 0; struct view_anchor old = t->view.anchor; - term_hist_view_scroll_to(&t->view, &t->hist, t->cols, screen_top_line(t), offset); + wsap_vtcore_hist_view_scroll_to(&t->view, &t->hist, t->cols, screen_top_line(t), offset); if (old.active != t->view.anchor.active || old.line_id != t->view.anchor.line_id || old.seg != t->view.anchor.seg) t->full_gen++; - term_write_end(t); + wsap_vtcore_write_end(t); } -void term_scroll(struct term *t, int lines) +void wsap_vtcore_scroll(struct wsap_vtcore *t, int lines) { if (!t) return; /* Read the alternate flag inside the writer section. A read before - * term_write_begin races with a feed on another thread. */ - term_write_begin(t); + * wsap_vtcore_write_begin races with a feed on another thread. */ + wsap_vtcore_write_begin(t); if (t->alternate) { - term_write_end(t); + wsap_vtcore_write_end(t); return; } struct view_anchor old = t->view.anchor; - term_hist_view_scroll(&t->view, &t->hist, t->cols, screen_top_line(t), lines); + wsap_vtcore_hist_view_scroll(&t->view, &t->hist, t->cols, screen_top_line(t), lines); if (old.active != t->view.anchor.active || old.line_id != t->view.anchor.line_id || old.seg != t->view.anchor.seg) t->full_gen++; - term_write_end(t); + wsap_vtcore_write_end(t); } -struct term_scrollback term_scrollback(const struct term *t) +struct wsap_vtcore_scrollback wsap_vtcore_scrollback(const struct wsap_vtcore *t) { if (!t) - return (struct term_scrollback){ 0 }; - term_write_begin((struct term *)t); - struct term_scrollback sb = { 0 }; + return (struct wsap_vtcore_scrollback){ 0 }; + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + struct wsap_vtcore_scrollback sb = { 0 }; if (!t->alternate) { - sb.offset = term_view_offset(t); - sb.total = term_screen_history_rows(t); + sb.offset = wsap_vtcore_view_offset(t); + sb.total = wsap_vtcore_screen_history_rows(t); } - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return sb; } -void term_screen_erase_line(struct term *t, int mode) +void wsap_vtcore_screen_erase_line(struct wsap_vtcore *t, int mode) { t->pending_wrap = false; int p = phys_row(t, t->cursor_y); @@ -272,7 +272,7 @@ void term_screen_erase_line(struct term *t, int mode) } } -void term_screen_delete_chars(struct term *t, int n) +void wsap_vtcore_screen_delete_chars(struct wsap_vtcore *t, int n) { t->pending_wrap = false; if (t->cursor_x >= t->cols) @@ -283,7 +283,7 @@ void term_screen_delete_chars(struct term *t, int n) n = cols - x; int p = phys_row(t, t->cursor_y); struct cell *row = row_cells(t, p); - struct srow *srow = term_row(t, t->cursor_y); + struct srow *srow = wsap_vtcore_row(t, t->cursor_y); int len = srow->len; clear_wide_edges(row, x, x + n, len); if (len > cols) { @@ -304,7 +304,7 @@ void term_screen_delete_chars(struct term *t, int n) int from = cols - n; if (from < x) from = x; - term_row_fill_gap(srow, from); + wsap_vtcore_row_fill_gap(srow, from); fill_cells(&row[from], cols - from, t->cur_fg, t->cur_bg); srow->len = (uint16_t)cols; } @@ -313,7 +313,7 @@ void term_screen_delete_chars(struct term *t, int n) srow->version++; } -void term_screen_insert_chars(struct term *t, int n) +void wsap_vtcore_screen_insert_chars(struct wsap_vtcore *t, int n) { t->pending_wrap = false; if (t->cursor_x >= t->cols) @@ -324,8 +324,8 @@ void term_screen_insert_chars(struct term *t, int n) n = cols - x; int p = phys_row(t, t->cursor_y); struct cell *row = row_cells(t, p); - struct srow *srow = term_row(t, t->cursor_y); - term_row_fill_gap(srow, x); + struct srow *srow = wsap_vtcore_row(t, t->cursor_y); + wsap_vtcore_row_fill_gap(srow, x); int len = srow->len; if (x > 0 && x < len && (row[x].flags & CELL_TRAIL)) { fill_cells(row + x - 1, 2, t->cur_fg, t->cur_bg); @@ -355,7 +355,7 @@ void term_screen_insert_chars(struct term *t, int n) srow->version++; } -void term_screen_erase_all(struct term *t) +void wsap_vtcore_screen_erase_all(struct wsap_vtcore *t) { t->pending_wrap = false; struct screen *s = &t->scr; @@ -369,9 +369,9 @@ void term_screen_erase_all(struct term *t) t->full_gen++; } -#if defined(TERM_KERNEL_AVX2) +#if defined(WSAP_VTCORE_KERNEL_AVX2) /* The inner columns [1, len - 1): the callers probed both ends. */ -TERM_TARGET_AVX2 +WSAP_VTCORE_TARGET_AVX2 static bool text_has_text_avx2(const uint8_t *text, int len) { int x = 1; @@ -388,7 +388,7 @@ static bool text_has_text_avx2(const uint8_t *text, int len) return false; } -TERM_TARGET_AVX2 +WSAP_VTCORE_TARGET_AVX2 static bool cells_has_text_avx2(const struct cell *cells, int len) { int x = 1; @@ -433,8 +433,8 @@ static inline bool text_has_text(const uint8_t *text, int len) return true; } #elif defined(__x86_64__) -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return text_has_text_avx2(text, len); #endif const __m128i vspace = _mm_set1_epi8(' '); @@ -473,8 +473,8 @@ static inline bool cells_has_text(const struct cell *cells, int len) if (vmaxvq_u32(cmp) != 0) return true; } -#elif defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#elif defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return cells_has_text_avx2(cells, len); #endif for (; x < len - 1; x++) @@ -493,14 +493,14 @@ static inline bool srow_has_text(const struct srow *r, int cols) return cells_has_text(r->cells, len); } -void term_screen_erase(struct term *t, int mode) +void wsap_vtcore_screen_erase(struct wsap_vtcore *t, int mode) { t->pending_wrap = false; if (mode == 3) { - term_hist_clear(&t->hist); + wsap_vtcore_hist_clear(&t->hist); t->view.anchor = (struct view_anchor){0}; t->view.index_cols = 0; - term_select_clear(t); + wsap_vtcore_select_clear(t); t->full_gen++; return; } @@ -514,8 +514,8 @@ void term_screen_erase(struct term *t, int mode) for (int y = rows - 1; y >= 0; y--) { const struct srow *r = &slots[p]; p = (p == 0) ? rows - 1 : p - 1; - if (TERM_EXPECT(r->len == 0, 1)) { - if (TERM_EXPECT((r->flags & RF_WRAPPED) != 0, 0)) + if (WSAP_VTCORE_EXPECT(r->len == 0, 1)) { + if (WSAP_VTCORE_EXPECT((r->flags & RF_WRAPPED) != 0, 0)) tail_clean = false; continue; } @@ -526,13 +526,13 @@ void term_screen_erase(struct term *t, int mode) tail_clean = false; } if (last_active >= 0 && !t->alternate) { - term_screen_scroll_region(t, 0, rows - 1, last_active + 1, false, true); + wsap_vtcore_screen_scroll_region(t, 0, rows - 1, last_active + 1, false, true); if (tail_clean) { t->view.anchor = (struct view_anchor){0}; return; } } - term_screen_erase_all(t); + wsap_vtcore_screen_erase_all(t); t->view.anchor = (struct view_anchor){0}; t->full_gen++; } else if (mode == 0) { @@ -561,7 +561,7 @@ void term_screen_erase(struct term *t, int mode) } /* Reset a recycled row's contents and identity; callers choose its version. */ -static inline void reset_scrolled_row(struct term *t, struct srow *row, bool def) +static inline void reset_scrolled_row(struct wsap_vtcore *t, struct srow *row, bool def) { row->kind = ROW_CELLS; row->uid = ++t->next_row_uid; @@ -575,7 +575,7 @@ static inline void reset_scrolled_row(struct term *t, struct srow *row, bool def } } -static void rotate_and_clear_srows(struct term *t, struct srow *base, int height, +static void rotate_and_clear_srows(struct wsap_vtcore *t, struct srow *base, int height, int count, bool down, bool def) { struct srow tmp[64]; @@ -600,7 +600,7 @@ static void rotate_and_clear_srows(struct term *t, struct srow *base, int height free(saved); } -void term_screen_scroll_region(struct term *t, int top, int bottom, int count, +void wsap_vtcore_screen_scroll_region(struct wsap_vtcore *t, int top, int bottom, int count, bool down, bool history) { t->pending_wrap = false; @@ -619,7 +619,7 @@ void term_screen_scroll_region(struct term *t, int top, int bottom, int count, if (!down) { bool has_hist = history && screen_has_history(t); - if (TERM_EXPECT(t->prompt_y >= 0, 0) && !t->alternate) { + if (WSAP_VTCORE_EXPECT(t->prompt_y >= 0, 0) && !t->alternate) { if (history) { if (t->prompt_y > 0) t->prompt_y = t->prompt_y > count ? t->prompt_y - count : 0; @@ -635,8 +635,8 @@ void term_screen_scroll_region(struct term *t, int top, int bottom, int count, int p = orig_top + i; if (p >= rows) p -= rows; struct srow *row = &s->slot[p]; - if (TERM_EXPECT(has_hist, 1)) - term_screen_push_row(t, row); + if (WSAP_VTCORE_EXPECT(has_hist, 1)) + wsap_vtcore_screen_push_row(t, row); else screen_drop_top(s, row); if (history) { @@ -683,9 +683,9 @@ void term_screen_scroll_region(struct term *t, int top, int bottom, int count, if (!down && history && top == 0 && !t->alternate) { for (int i = 0; i < count; i++) { - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); if (bottom + 1 < t->rows) - term_screen_scroll_region(t, bottom, t->rows - 1, 1, true, false); + wsap_vtcore_screen_scroll_region(t, bottom, t->rows - 1, 1, true, false); } return; } @@ -734,9 +734,9 @@ void term_screen_scroll_region(struct term *t, int top, int bottom, int count, t->full_gen++; } -static bool term_resize_internal(struct term *t, int cols, int rows); +static bool wsap_vtcore_resize_internal(struct wsap_vtcore *t, int cols, int rows); -void term_screen_set_alternate(struct term *t, bool enabled) +void wsap_vtcore_screen_set_alternate(struct wsap_vtcore *t, bool enabled) { if (t->alternate == enabled) return; @@ -759,7 +759,7 @@ void term_screen_set_alternate(struct term *t, bool enabled) struct screen tmp_scr = t->scr; t->scr = t->alt_scr; t->alt_scr = tmp_scr; - t->normal_saved_cursor = term_cursor_save(t); + t->normal_saved_cursor = wsap_vtcore_cursor_save(t); t->normal_saved_decsc = t->saved; t->normal_cursor_visible = t->cursor_visible; t->normal_cursor_style = (uint8_t)t->cursor_style; @@ -776,7 +776,7 @@ void term_screen_set_alternate(struct term *t, bool enabled) t->right_margin = t->cols - 1; /* The alternate screen has no history to show. */ t->view.anchor = (struct view_anchor){0}; - term_select_clear(t); + wsap_vtcore_select_clear(t); t->full_gen++; } else { int cols = t->cols; @@ -789,29 +789,29 @@ void term_screen_set_alternate(struct term *t, bool enabled) t->alternate = false; t->saved = t->normal_saved_decsc; t->cursor_visible = t->normal_cursor_visible; - t->cursor_style = (enum term_cursor_style)t->normal_cursor_style; + t->cursor_style = (enum wsap_vtcore_cursor_style)t->normal_cursor_style; t->cursor_blink = t->normal_cursor_blink; - term_cursor_apply(t, &t->normal_saved_cursor); + wsap_vtcore_cursor_apply(t, &t->normal_saved_cursor); t->cursor_x = t->normal_saved_cursor.x; t->cursor_y = t->normal_saved_cursor.y; t->pending_wrap = t->normal_saved_cursor.pending_wrap; if (cols != t->cols || rows != t->rows) - term_resize_internal(t, cols, rows); + wsap_vtcore_resize_internal(t, cols, rows); t->scroll_top = 0; t->scroll_bottom = t->rows - 1; t->left_margin = 0; t->right_margin = t->cols - 1; /* The alternate screen has no history to show. */ t->view.anchor = (struct view_anchor){0}; - term_select_clear(t); + wsap_vtcore_select_clear(t); t->full_gen++; } } -/* The caller has checked that requested is in [0, TERM_SCROLLBACK_MAX]. */ +/* The caller has checked that requested is in [0, WSAP_VTCORE_SCROLLBACK_MAX]. */ static int scrollback_lines(int requested) { - return requested == 0 ? TERM_SCROLLBACK_DEFAULT : requested; + return requested == 0 ? WSAP_VTCORE_SCROLLBACK_DEFAULT : requested; } static atomic_int tables_state; @@ -824,16 +824,16 @@ static void tables_init(void) return; int expected = 0; if (atomic_compare_exchange_strong(&tables_state, &expected, 1)) { - term_isa_init(); - term_text_tables_init(); + wsap_vtcore_isa_init(); + wsap_vtcore_text_tables_init(); atomic_store_explicit(&tables_state, 2, memory_order_release); return; } while (atomic_load_explicit(&tables_state, memory_order_acquire) != 2) - term_cpu_relax(); + wsap_vtcore_cpu_relax(); } -bool term_tables_ready(void) +bool wsap_vtcore_tables_ready(void) { return atomic_load_explicit(&tables_state, memory_order_relaxed) == 2; } @@ -849,31 +849,31 @@ static bool name_valid(const char *s) return true; } -struct term *term_new(const struct term_options *opt) +struct wsap_vtcore *wsap_vtcore_new(const struct wsap_vtcore_options *opt) { tables_init(); - static const struct term_options defaults; + static const struct wsap_vtcore_options defaults; if (!opt) opt = &defaults; for (size_t i = 0; i < sizeof(opt->reserved) / sizeof(opt->reserved[0]); i++) if (opt->reserved[i]) return NULL; - if (opt->size.x < 0 || opt->size.y < 0 || opt->size.x > TERM_MAX_COLS) + if (opt->size.x < 0 || opt->size.y < 0 || opt->size.x > WSAP_VTCORE_MAX_COLS) return NULL; - if (opt->scrollback < 0 || opt->scrollback > TERM_SCROLLBACK_MAX || - (unsigned)opt->cursor_style > TERM_CURSOR_BAR) + if (opt->scrollback < 0 || opt->scrollback > WSAP_VTCORE_SCROLLBACK_MAX || + (unsigned)opt->cursor_style > WSAP_VTCORE_CURSOR_BAR) return NULL; - const char *name = opt->name && *opt->name ? opt->name : "term"; + const char *name = opt->name && *opt->name ? opt->name : "wsap_vtcore"; if (!name_valid(name)) return NULL; int cols = opt->size.x == 0 ? 80 : opt->size.x; int rows = opt->size.y == 0 ? 24 : opt->size.y; static _Atomic uint64_t next_serial = 1; - struct term *t = calloc(1, sizeof(*t)); + struct wsap_vtcore *t = calloc(1, sizeof(*t)); if (!t) return NULL; - if (!term_mutex_init(&t->write_lock)) { + if (!wsap_vtcore_mutex_init(&t->write_lock)) { free(t); return NULL; } @@ -888,35 +888,35 @@ struct term *term_new(const struct term_options *opt) t->prompt_y = -1; t->sb_capacity = scrollback_lines(opt->scrollback); t->cb = opt->callbacks; - term_palette_init(&t->palette, &opt->theme); + wsap_vtcore_palette_init(&t->palette, &opt->theme); t->next_row_uid = 1; if (!screen_setup(&t->scr, cols, rows, &t->next_row_uid)) { - term_mutex_destroy(&t->write_lock); + wsap_vtcore_mutex_destroy(&t->write_lock); free(t); return NULL; } - if (!term_hist_init(&t->hist, t->sb_capacity, 0)) { + if (!wsap_vtcore_hist_init(&t->hist, t->sb_capacity, 0)) { screen_free(&t->scr); - term_mutex_destroy(&t->write_lock); + wsap_vtcore_mutex_destroy(&t->write_lock); free(t); return NULL; } t->hist.wrap_cols = (uint16_t)cols; - t->gstore = term_gstore_new(t); + t->gstore = wsap_vtcore_gstore_new(t); t->view_scratch_cap = cols > 256 ? cols : 256; t->view_row_scratch = calloc((size_t)t->view_scratch_cap, sizeof(struct cell)); t->tabs_cap = cols > 256 ? cols : 256; t->tabs = calloc((size_t)t->tabs_cap, 1); if (!t->gstore || !t->view_row_scratch || !t->tabs) { - term_free(t); + wsap_vtcore_free(t); return NULL; } - t->cur_fg = TERM_COLOR_FG; - t->cur_bg = TERM_COLOR_BG; + t->cur_fg = WSAP_VTCORE_COLOR_FG; + t->cur_bg = WSAP_VTCORE_COLOR_BG; t->cursor_visible = true; t->default_cursor_style = opt->cursor_style; t->default_cursor_blink = !opt->cursor_steady; @@ -924,16 +924,16 @@ struct term *term_new(const struct term_options *opt) t->cursor_blink = t->default_cursor_blink; t->autowrap = true; t->charsets[0] = t->charsets[1] = 'B'; - t->saved = term_saved_cursor_initial(); + t->saved = wsap_vtcore_saved_cursor_initial(); memcpy(t->tcap_name, t->name, sizeof(t->name)); - term_tabs_default(t); + wsap_vtcore_tabs_default(t); t->full_gen = 1; memset(t->text_width.lo, 0xFF, sizeof(t->text_width.lo)); return t; } -void term_free(struct term *t) +void wsap_vtcore_free(struct wsap_vtcore *t) { if (!t) return; @@ -949,13 +949,13 @@ void term_free(struct term *t) free(t->resize.lens.data); free(t->ascii_ends.data); free(t->ascii_tail.data); - term_hist_free(&t->hist); - term_hist_view_free(&t->view); + wsap_vtcore_hist_free(&t->hist); + wsap_vtcore_hist_view_free(&t->view); free(t->view_row_scratch); free(t->tabs); - term_osc_cleanup(t); - term_gstore_free(t->gstore); - term_mutex_destroy(&t->write_lock); + wsap_vtcore_osc_cleanup(t); + wsap_vtcore_gstore_free(t->gstore); + wsap_vtcore_mutex_destroy(&t->write_lock); free(t); } @@ -1005,7 +1005,7 @@ static bool reflow_target_end_row(struct reflow_target *r, bool wrapped) int len = r->x > r->cols ? r->cols : r->x; memcpy(dst_cells, r->cells, (size_t)len * sizeof(struct cell)); if (len < r->cols) - fill_cells(dst_cells + len, r->cols - len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(dst_cells + len, r->cols - len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); dst->len = len; dst->wrapped = wrapped; r->x = 0; @@ -1025,7 +1025,7 @@ static bool reflow_append_span(struct reflow_target *r, const struct cell *cells int take = len - i < room ? len - i : room; if (i + take < len && (cells[i + take].flags & CELL_TRAIL)) { if (--take == 0) { - r->cells[r->x] = (struct cell){' ', TERM_COLOR_FG, TERM_COLOR_BG, CELL_WRAP_PAD, 0}; + r->cells[r->x] = (struct cell){' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, CELL_WRAP_PAD, 0}; r->x++; if (!reflow_target_end_row(r, true)) return false; @@ -1075,7 +1075,7 @@ static bool reflow_append_wide(struct reflow_target *r, const struct cell *cells int n = (cells[i].flags & CELL_WIDE) && r->cols > 1 ? 2 : 1; if (r->x + n > r->cols) { if (r->x < r->cols) { - r->cells[r->x] = (struct cell){' ', TERM_COLOR_FG, TERM_COLOR_BG, CELL_WRAP_PAD, 0}; + r->cells[r->x] = (struct cell){' ', WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, CELL_WRAP_PAD, 0}; r->x++; } if (!reflow_target_end_row(r, true)) @@ -1140,26 +1140,26 @@ static bool reflow_append(struct reflow_target *r, const struct cell *cells, int /* Move up to max_pull rows from the end of history to the top of dst. A line * that does not fit whole leaves its first rows in history, still open. */ -static int pull_history_rows(struct term *t, struct screen *dst_scr, int cols, int max_pull) +static int pull_history_rows(struct wsap_vtcore *t, struct screen *dst_scr, int cols, int max_pull) { struct hist *h = &t->hist; int pull = 0; for (uint64_t id = hist_end_id(h); pull < max_pull && id > hist_first_id(h); id--) - pull += term_hist_line_rows(h, id - 1, cols); + pull += wsap_vtcore_hist_line_rows(h, id - 1, cols); if (pull > max_pull) pull = max_pull; int slot = pull; while (slot > 0) { uint64_t id = hist_end_id(h) - 1; - int line_rows = term_hist_line_rows(h, id, cols); + int line_rows = wsap_vtcore_hist_line_rows(h, id, cols); bool open = hist_is_open(h); int take = slot < line_rows ? slot : line_rows; int first = line_rows - take; struct cell *pull_buf = grow(&t->resize.pull, (size_t)take * (size_t)cols * sizeof(*pull_buf)); int *pull_lens = grow(&t->resize.lens, (size_t)take * sizeof(*pull_lens)); if (pull_buf && pull_lens) - term_hist_decode_segments(h, id, first, take, cols, pull_buf, pull_lens, t->gstore); + wsap_vtcore_hist_decode_segments(h, id, first, take, cols, pull_buf, pull_lens, t->gstore); for (int seg = line_rows - 1; seg >= first; seg--) { struct srow *dst = &dst_scr->slot[--slot]; int idx = seg - first; @@ -1168,7 +1168,7 @@ static int pull_history_rows(struct term *t, struct screen *dst_scr, int cols, i memcpy(dst->cells, pull_buf + (size_t)idx * cols, (size_t)cols * sizeof(struct cell)); bool wrapped = seg + 1 < line_rows || open; if (got < cols) { - fill_cells(dst->cells + got, cols - got, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(dst->cells + got, cols - got, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); if (wrapped) { set_cells_wrap_pad(dst->cells + got, cols - got); got = cols; @@ -1181,20 +1181,20 @@ static int pull_history_rows(struct term *t, struct screen *dst_scr, int cols, i dst->uid = ++t->next_row_uid; } if (first == 0) { - term_hist_pop_line(h, NULL, 0, t->gstore); + wsap_vtcore_hist_pop_line(h, NULL, 0, t->gstore); continue; } struct cell *rest = grow(&t->resize.rest, (size_t)first * (size_t)cols * sizeof(*rest)); int *lens = grow(&t->resize.lens, (size_t)first * sizeof(*lens)); if (rest && lens) - term_hist_decode_segments(h, id, 0, first, cols, rest, lens, t->gstore); - term_hist_pop_line(h, NULL, 0, t->gstore); + wsap_vtcore_hist_decode_segments(h, id, 0, first, cols, rest, lens, t->gstore); + wsap_vtcore_hist_pop_line(h, NULL, 0, t->gstore); if (rest && lens) { for (int seg = 0; seg < first; seg++) { struct cell *row = rest + (size_t)seg * cols; if (lens[seg] < cols) - fill_cells(row + lens[seg], cols - lens[seg], TERM_COLOR_FG, TERM_COLOR_BG); - term_hist_push_row(h, row, cols, true, t->gstore); + fill_cells(row + lens[seg], cols - lens[seg], WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); + wsap_vtcore_hist_push_row(h, row, cols, true, t->gstore); } } } @@ -1202,7 +1202,7 @@ static int pull_history_rows(struct term *t, struct screen *dst_scr, int cols, i } /* The spare screen, set up as cols x rows, for a resize to build into. */ -static bool resize_target(struct term *t, struct screen *out, int cols, int rows, +static bool resize_target(struct wsap_vtcore *t, struct screen *out, int cols, int rows, const struct screen *from) { *out = t->spare; @@ -1250,9 +1250,9 @@ static void copy_srow_resized(struct srow *dst, struct srow *src, int old_cols, dst->version = src->version + 1; } -static bool term_resize_internal(struct term *t, int cols, int rows) +static bool wsap_vtcore_resize_internal(struct wsap_vtcore *t, int cols, int rows) { - term_gstore_pin(t->gstore); + wsap_vtcore_gstore_pin(t->gstore); if (t->alternate || cols == t->scr.cols) { struct screen *active_scr = &t->scr; @@ -1261,7 +1261,7 @@ static bool term_resize_internal(struct term *t, int cols, int rows) struct screen new_scr; if (!resize_target(t, &new_scr, cols, rows, active_scr)) { - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return false; } @@ -1270,7 +1270,7 @@ static bool term_resize_internal(struct term *t, int cols, int rows) if (rows < old_rows && t->cursor_y >= rows) { int shift = t->cursor_y - rows + 1; for (int i = 0; i < shift; i++) - term_screen_scroll_up(t); + wsap_vtcore_screen_scroll_up(t); t->cursor_y -= shift; t->saved.y = t->saved.y >= shift ? t->saved.y - shift : 0; } @@ -1322,9 +1322,9 @@ static bool term_resize_internal(struct term *t, int cols, int rows) t->scroll_bottom = rows - 1; t->left_margin = 0; t->right_margin = cols - 1; - term_hist_view_rewrap(&t->view, &t->hist, cols); + wsap_vtcore_hist_view_rewrap(&t->view, &t->hist, cols); t->full_gen++; - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return true; } @@ -1333,7 +1333,7 @@ static bool term_resize_internal(struct term *t, int cols, int rows) struct screen new_scr; if (!resize_target(t, &new_scr, cols, rows, &t->scr)) { - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return false; } @@ -1357,17 +1357,17 @@ static bool term_resize_internal(struct term *t, int cols, int rows) }; if (!r.cells) { t->spare = new_scr; - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return false; } /* The open history line reflows with the screen. It is read here and * removed only after the reflow succeeds. The prompt line never rewraps. */ if (hist_is_open(&t->hist) && t->prompt_y != 0) { - uint64_t n = term_hist_line_cells(&t->hist, hist_end_id(&t->hist) - 1); + uint64_t n = wsap_vtcore_hist_line_cells(&t->hist, hist_end_id(&t->hist) - 1); struct cell *pulled = n ? grow(&t->resize.pull, n * sizeof(*pulled)) : NULL; if (n && !pulled) goto reflow_failed; - int got = term_hist_peek_last_line(&t->hist, pulled, pulled ? (int)n : 0, t->gstore); + int got = wsap_vtcore_hist_peek_last_line(&t->hist, pulled, pulled ? (int)n : 0, t->gstore); if (pulled && got > 0 && !reflow_append(&r, pulled, got, -1, -1)) goto reflow_failed; } @@ -1425,14 +1425,14 @@ static bool term_resize_internal(struct term *t, int cols, int rows) if (len > src->len && src->len < old_cols && !(src->flags & RF_TAIL_PADDED)) { fill_cells(src->cells + src->len, old_cols - src->len, - TERM_COLOR_FG, TERM_COLOR_BG); + WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); src->flags |= RF_TAIL_PADDED; } const struct cell *in_cells = cells; if (len > old_cols && line_buf && (size_t)len <= line_cap) { memcpy(line_buf, cells, (size_t)old_cols * sizeof(struct cell)); - fill_cells(line_buf + old_cols, len - old_cols, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(line_buf + old_cols, len - old_cols, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); in_cells = line_buf; } else if (len > old_cols) { len = old_cols; @@ -1453,11 +1453,11 @@ static bool term_resize_internal(struct term *t, int cols, int rows) * nothing below can fail. */ if (hist_is_open(&t->hist)) { if (t->prompt_y == 0) - term_hist_close_open_line(&t->hist); + wsap_vtcore_hist_close_open_line(&t->hist); else - term_hist_pop_line(&t->hist, NULL, 0, t->gstore); + wsap_vtcore_hist_pop_line(&t->hist, NULL, 0, t->gstore); } - term_hist_set_width(&t->hist, cols); + wsap_vtcore_hist_set_width(&t->hist, cols); int visible = rows - (cols > old_cols ? old_rows - active : 0); if (visible < 1) @@ -1471,7 +1471,7 @@ static bool term_resize_internal(struct term *t, int cols, int rows) screen_start = r.cursor_y; for (int i = 0; i < screen_start; i++) { int push_len = (r.out[i].wrapped && r.out[i].len < cols) ? cols : r.out[i].len; - term_hist_push_row(&t->hist, reflow_out_row_cells(&r, i), push_len, + wsap_vtcore_hist_push_row(&t->hist, reflow_out_row_cells(&r, i), push_len, r.out[i].wrapped, t->gstore); } } else if (r.count < visible && t->hist.lines > 0) { @@ -1487,7 +1487,7 @@ static bool term_resize_internal(struct term *t, int cols, int rows) int len = r.out[i].len; memcpy(dst->cells, reflow_out_row_cells(&r, i), (size_t)len * sizeof(struct cell)); if (len < cols) - fill_cells(dst->cells + len, cols - len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(dst->cells + len, cols - len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); dst->kind = ROW_CELLS; dst->len = (uint16_t)len; dst->flags = (r.out[i].wrapped ? RF_WRAPPED : 0) | RF_TAIL_PADDED; @@ -1530,28 +1530,28 @@ static bool term_resize_internal(struct term *t, int cols, int rows) t->scroll_bottom = rows - 1; t->left_margin = 0; t->right_margin = cols - 1; - term_hist_view_rewrap(&t->view, &t->hist, cols); + wsap_vtcore_hist_view_rewrap(&t->view, &t->hist, cols); t->full_gen++; - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return true; reflow_failed: t->spare = new_scr; - term_gstore_unpin(t->gstore); + wsap_vtcore_gstore_unpin(t->gstore); return false; } -bool term_resize(struct term *t, struct term_vector2i size) +bool wsap_vtcore_resize(struct wsap_vtcore *t, struct wsap_vtcore_vector2i size) { if (!t) return false; int cols = size.x; int rows = size.y; - if (cols < 1 || rows < 1 || cols > TERM_MAX_COLS) + if (cols < 1 || rows < 1 || cols > WSAP_VTCORE_MAX_COLS) return false; - term_write_begin(t); + wsap_vtcore_write_begin(t); if (cols == t->cols && rows == t->rows) { - term_write_end(t); + wsap_vtcore_write_end(t); return true; } @@ -1559,7 +1559,7 @@ bool term_resize(struct term *t, struct term_vector2i size) int new_cap = cols + 64; uint8_t *new_tabs = realloc(t->tabs, (size_t)new_cap); if (!new_tabs) { - term_write_end(t); + wsap_vtcore_write_end(t); return false; } memset(new_tabs + t->tabs_cap, 0, (size_t)(new_cap - t->tabs_cap)); @@ -1579,7 +1579,7 @@ bool term_resize(struct term *t, struct term_vector2i size) int new_cap = cols + 64; struct cell *new_scratch = realloc(t->view_row_scratch, (size_t)new_cap * sizeof(struct cell)); if (!new_scratch) { - term_write_end(t); + wsap_vtcore_write_end(t); return false; } memset(new_scratch + t->view_scratch_cap, 0, (size_t)(new_cap - t->view_scratch_cap) * sizeof(struct cell)); @@ -1587,7 +1587,7 @@ bool term_resize(struct term *t, struct term_vector2i size) t->view_scratch_cap = new_cap; } - bool ok = term_resize_internal(t, cols, rows); - term_write_end(t); + bool ok = wsap_vtcore_resize_internal(t, cols, rows); + wsap_vtcore_write_end(t); return ok; } diff --git a/src/screen.h b/src/screen.h index df464a7..1b5d8eb 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,5 +1,5 @@ -#ifndef TERM_SCREEN_H -#define TERM_SCREEN_H +#ifndef WSAP_VTCORE_SCREEN_H +#define WSAP_VTCORE_SCREEN_H #include <assert.h> #include "compat.h" @@ -7,38 +7,38 @@ #include "kernels.h" #include "simd.h" -void term_screen_scroll_region(struct term *t, int top, int bottom, int count, bool down, bool history); -void term_screen_set_alternate(struct term *t, bool enabled); -void term_screen_erase(struct term *t, int mode); -void term_screen_erase_all(struct term *t); -void term_screen_erase_line(struct term *t, int mode); -void term_screen_delete_chars(struct term *t, int count); -void term_screen_insert_chars(struct term *t, int count); +void wsap_vtcore_screen_scroll_region(struct wsap_vtcore *t, int top, int bottom, int count, bool down, bool history); +void wsap_vtcore_screen_set_alternate(struct wsap_vtcore *t, bool enabled); +void wsap_vtcore_screen_erase(struct wsap_vtcore *t, int mode); +void wsap_vtcore_screen_erase_all(struct wsap_vtcore *t); +void wsap_vtcore_screen_erase_line(struct wsap_vtcore *t, int mode); +void wsap_vtcore_screen_delete_chars(struct wsap_vtcore *t, int count); +void wsap_vtcore_screen_insert_chars(struct wsap_vtcore *t, int count); -const struct cell *term_screen_view_row(const struct term *t, int y); -uint64_t term_screen_view_row_key(const struct term *t, int y); +const struct cell *wsap_vtcore_screen_view_row(const struct wsap_vtcore *t, int y); +uint64_t wsap_vtcore_screen_view_row_key(const struct wsap_vtcore *t, int y); /* The selected columns [c0, c1] of each view row; c1 < c0 when none. */ /* False when memory runs out; c0 and c1 are then not complete. */ -bool term_selection_view_spans(const struct term *t, int *c0, int *c1); +bool wsap_vtcore_selection_view_spans(const struct wsap_vtcore *t, int *c0, int *c1); -int term_screen_history_rows(const struct term *t); +int wsap_vtcore_screen_history_rows(const struct wsap_vtcore *t); /* Rows of history above the live screen. The view owns the offset. */ -int term_view_offset(const struct term *t); +int wsap_vtcore_view_offset(const struct wsap_vtcore *t); -static inline bool screen_has_history(const struct term *t) +static inline bool screen_has_history(const struct wsap_vtcore *t) { return !t->alternate && t->hist.line_limit > 0; } -static inline int phys_row(const struct term *t, int y) +static inline int phys_row(const struct wsap_vtcore *t, int y) { int p = t->scr.top + y; return p >= t->scr.rows ? p - t->scr.rows : p; } -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 static inline void set_cells_wrap_pad_avx2(struct cell *cells, int count) { const __m256i mask = _mm256_setr_epi32(0, 0, 0, (int)CELL_WRAP_PAD, @@ -61,8 +61,8 @@ static inline void set_cells_wrap_pad(struct cell *cells, int count) { if (count <= 0) return; -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2() && count >= 4) { +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2() && count >= 4) { set_cells_wrap_pad_avx2(cells, count); return; } @@ -115,12 +115,12 @@ static inline void init_ascii_text_row(struct text_row *tr, uint8_t *text, uint1 #endif /* The extra lanes cover unused fill data and run padding. */ #if defined(__x86_64__) || defined(_M_X64) - __m128i pen = _mm_setr_epi32(TERM_COLOR_FG, TERM_COLOR_BG, 0, TERM_COLOR_FG); + __m128i pen = _mm_setr_epi32(WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, 0, WSAP_VTCORE_COLOR_FG); _mm_storeu_si128((__m128i *)&tr->start, pen); _mm_storeu_si128((__m128i *)&tr->runs.base, pen); _mm_storeu_si128((__m128i *)&tr->runs.pen, pen); #elif defined(__aarch64__) - uint32x4_t pen = { TERM_COLOR_FG, TERM_COLOR_BG, 0, TERM_COLOR_FG }; + uint32x4_t pen = { WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG, 0, WSAP_VTCORE_COLOR_FG }; vst1q_u32((uint32_t *)&tr->start, pen); vst1q_u32((uint32_t *)&tr->runs.base, pen); vst1q_u32((uint32_t *)&tr->runs.pen, pen); @@ -154,7 +154,7 @@ static inline struct srow *screen_row_at(const struct screen *s, int y) return screen_get_row(s, y); } -static inline struct srow *term_row(const struct term *t, int y) +static inline struct srow *wsap_vtcore_row(const struct wsap_vtcore *t, int y) { return screen_get_row(&t->scr, y); } @@ -165,7 +165,7 @@ static inline int text_row_decode(const struct srow *row, struct cell *out, int { srow_materialize_text((struct srow *)row); const struct text_row *tr = &row->text; - int n = term_hist_text_decode(tr, out, cols, NULL); + int n = wsap_vtcore_hist_text_decode(tr, out, cols, NULL); int fill = tr->fill_to < cols ? tr->fill_to : cols; if (n < fill) { fill_cells(out + n, fill - n, tr->fill.fg, tr->fill.bg); @@ -179,7 +179,7 @@ static inline void text_row_cells(const struct srow *row, struct cell *out, int { int n = text_row_decode(row, out, cols); if (n < cols) - fill_cells(out + n, cols - n, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(out + n, cols - n, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); } /* Turn a text row into a cells row. Only the write core does this. Its @@ -190,7 +190,7 @@ static inline void srow_settle(struct srow *row, int cols) if (row->kind == ROW_TEXT) { int n = text_row_decode(row, row->cells, cols); if (n < cols && !(row->flags & RF_TAIL_PADDED)) - fill_cells(row->cells + n, cols - n, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(row->cells + n, cols - n, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); row->flags |= RF_TAIL_PADDED; row->kind = ROW_CELLS; } @@ -203,9 +203,9 @@ static inline void srow_settle(struct srow *row, int cols) * history, so they keep the history format. NULL when neither holds. The * caller has handled a pending wrap, insert mode, and margins. */ -static inline struct srow *text_append_row(struct term *t) +static inline struct srow *text_append_row(struct wsap_vtcore *t) { - struct srow *row = term_row(t, t->cursor_y); + struct srow *row = wsap_vtcore_row(t, t->cursor_y); if (row->kind == ROW_TEXT) { text_row_unshare(&row->text); if (t->cursor_x != row->text.cells) @@ -220,7 +220,7 @@ static inline struct srow *text_append_row(struct term *t) * history can copy its runs. */ struct pen_attr start = pen_attr_default(); if (t->cursor_y > 0) { - const struct srow *prev = term_row(t, t->cursor_y - 1); + const struct srow *prev = wsap_vtcore_row(t, t->cursor_y - 1); if (prev->kind == ROW_TEXT && (prev->flags & RF_WRAPPED)) start = prev->text.runs.pen; } @@ -263,7 +263,7 @@ static inline void text_append(struct srow *row, const uint8_t *bytes, int nbyte text_commit(row, nbytes, chars, cells, hflags, pen); } -static inline struct cell *row_cells(const struct term *t, int p) +static inline struct cell *row_cells(const struct wsap_vtcore *t, int p) { struct srow *row = &t->scr.slot[p]; if (row->kind != ROW_CELLS) @@ -276,14 +276,14 @@ static inline struct cell *row_cells(const struct term *t, int p) * or a resize can never leave a stale id behind. */ /* The logical line of screen row 0, and the row's segment in it. */ -static inline struct line_pos screen_top_line(const struct term *t) +static inline struct line_pos screen_top_line(const struct wsap_vtcore *t) { if (!screen_has_history(t)) return (struct line_pos){ t->scr.top_id, t->scr.top_seg }; uint64_t end = hist_end_id(&t->hist); if (!hist_is_open(&t->hist)) return (struct line_pos){ end, 0 }; - return (struct line_pos){ end - 1, (uint32_t)term_hist_line_rows(&t->hist, end - 1, t->cols) }; + return (struct line_pos){ end - 1, (uint32_t)wsap_vtcore_hist_line_rows(&t->hist, end - 1, t->cols) }; } static inline struct line_pos line_pos_next(struct line_pos p, const struct srow *row) @@ -293,7 +293,7 @@ static inline struct line_pos line_pos_next(struct line_pos p, const struct srow } /* The oldest line that history or the screen still holds. */ -static inline uint64_t first_retained_line(const struct term *t) +static inline uint64_t first_retained_line(const struct wsap_vtcore *t) { if (screen_has_history(t) && t->hist.lines) return hist_first_id(&t->hist); @@ -329,12 +329,12 @@ static inline void repair_wide_row(struct cell *row, int from, int to, int cols, } } -static inline bool using_default_colors(const struct term *t) +static inline bool using_default_colors(const struct wsap_vtcore *t) { - return t->cur_fg == TERM_COLOR_FG && t->cur_bg == TERM_COLOR_BG; + return t->cur_fg == WSAP_VTCORE_COLOR_FG && t->cur_bg == WSAP_VTCORE_COLOR_BG; } -static inline void mark_row_blank(struct term *t, int p) +static inline void mark_row_blank(struct wsap_vtcore *t, int p) { struct srow *row = &t->scr.slot[p]; uint8_t tail_padded = ((row->kind == ROW_CELLS && row->len == 0) || row->kind == ROW_TEXT) @@ -345,11 +345,11 @@ static inline void mark_row_blank(struct term *t, int p) row->version++; } -static inline void term_row_fill_gap(struct srow *row, int x) +static inline void wsap_vtcore_row_fill_gap(struct srow *row, int x) { if (x > row->len) { if (!(row->flags & RF_TAIL_PADDED)) - fill_cells(row->cells + row->len, x - row->len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(row->cells + row->len, x - row->len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); row->len = (uint16_t)x; } } @@ -365,12 +365,12 @@ static inline void write_cell_span(struct cell *row, int x, } } -static inline void erase_span(struct term *t, int p, int from, int to) +static inline void erase_span(struct wsap_vtcore *t, int p, int from, int to) { bool pristine = using_default_colors(t); struct srow *row = &t->scr.slot[p]; int len = row->len; - if (to > TERM_MAX_COLS) to = TERM_MAX_COLS; + if (to > WSAP_VTCORE_MAX_COLS) to = WSAP_VTCORE_MAX_COLS; if (pristine && to > len) to = len; if (from >= to) return; @@ -385,7 +385,7 @@ static inline void erase_span(struct term *t, int p, int from, int to) row_set_wrapped(row, false); if (!pristine) { - term_row_fill_gap(row, from); + wsap_vtcore_row_fill_gap(row, from); fill_cells(cells + from, to - from, t->cur_fg, t->cur_bg); if (to > len) { row->len = (uint16_t)to; @@ -409,19 +409,19 @@ static inline void erase_span(struct term *t, int p, int from, int to) } } -static inline int erase_width(const struct term *t, int p) +static inline int erase_width(const struct wsap_vtcore *t, int p) { return t->scr.slot[p].len > t->cols ? t->scr.slot[p].len : t->cols; } -static inline void erase_row(struct term *t, int p) +static inline void erase_row(struct wsap_vtcore *t, int p) { erase_span(t, p, 0, erase_width(t, p)); } -static inline void clamp_selection_after_scroll(struct term *t) +static inline void clamp_selection_after_scroll(struct wsap_vtcore *t) { - if (TERM_EXPECT(!t->selection, 1)) + if (WSAP_VTCORE_EXPECT(!t->selection, 1)) return; uint64_t first_id = first_retained_line(t); if (t->sel_end.line_id < first_id) { @@ -433,7 +433,7 @@ static inline void clamp_selection_after_scroll(struct term *t) } /* Move a row that leaves the top of the normal screen into history. */ -void term_screen_push_row(struct term *t, struct srow *row); +void wsap_vtcore_screen_push_row(struct wsap_vtcore *t, struct srow *row); /* Count a row that leaves the top of a screen without history. */ static inline void screen_drop_top(struct screen *s, const struct srow *row) @@ -445,33 +445,33 @@ static inline void screen_drop_top(struct screen *s, const struct srow *row) /* Clear a row that enters at the bottom. With a colored pen it is a text row * that is all fill: blanks in the pen colors, which text can append over. */ -static inline void screen_new_row(struct term *t, struct srow *row) +static inline void screen_new_row(struct wsap_vtcore *t, struct srow *row) { row->uid = ++t->next_row_uid; row->version++; row->flags = ((row->kind == ROW_CELLS && row->len == 0) || row->kind == ROW_TEXT) ? (row->flags & RF_TAIL_PADDED) : 0; - if (TERM_EXPECT(using_default_colors(t), 1)) { + if (WSAP_VTCORE_EXPECT(using_default_colors(t), 1)) { row->kind = ROW_CELLS; row->len = 0; } else { row->kind = ROW_TEXT; - text_row_start(&row->text, &(struct pen_attr){ .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }); + text_row_start(&row->text, &(struct pen_attr){ .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }); row->text.fill_to = (uint16_t)t->scr.cols; row->text.fill = (struct pen_attr){ .fg = t->cur_fg, .bg = t->cur_bg }; row->len = (uint16_t)t->scr.cols; } } -static inline void term_screen_scroll_up(struct term *t) +static inline void wsap_vtcore_screen_scroll_up(struct wsap_vtcore *t) { struct screen *s = &t->scr; struct srow *row = &s->slot[s->top]; - if (TERM_EXPECT(screen_has_history(t), 1)) - term_screen_push_row(t, row); + if (WSAP_VTCORE_EXPECT(screen_has_history(t), 1)) + wsap_vtcore_screen_push_row(t, row); else screen_drop_top(s, row); - if (TERM_EXPECT(t->prompt_y > 0, 0) && !t->alternate) + if (WSAP_VTCORE_EXPECT(t->prompt_y > 0, 0) && !t->alternate) t->prompt_y--; s->top = s->top + 1 == s->rows ? 0 : s->top + 1; clamp_selection_after_scroll(t); diff --git a/src/selection.c b/src/selection.c index 1d931c9..f2dbd1a 100644 --- a/src/selection.c +++ b/src/selection.c @@ -5,13 +5,13 @@ #include <stdlib.h> #include <string.h> -static char *link_at_text(const struct term *t, struct term_vector2i cell) +static char *link_at_text(const struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell) { int col = cell.x, row = cell.y; if (!t || col < 0 || col >= t->cols || row < 0 || row >= t->rows) return NULL; - const char *link = term_osc8_url_at(t, col, row); - if (link) return term_strdup(link); - const struct cell *cells = term_screen_view_row(t, row); + const char *link = wsap_vtcore_osc8_url_at(t, col, row); + if (link) return wsap_vtcore_strdup(link); + const struct cell *cells = wsap_vtcore_screen_view_row(t, row); if (!cells) return NULL; int start = col, end = col; while (start > 0 && cells[start - 1].c > ' ' && cells[start - 1].c < 127) start--; @@ -48,27 +48,27 @@ static char *link_at_text(const struct term *t, struct term_vector2i cell) while (n && (mask[(unsigned char)url[n - 1] >> 6] & (1ULL << ((unsigned char)url[n - 1] & 63)))) url[--n] = 0; if (col < start + (int)(url - text) + (int)n && n > scheme) - out = term_strdup(url); + out = wsap_vtcore_strdup(url); } free(text); return out; } -char *term_link_at(const struct term *t, struct term_vector2i cell) +char *wsap_vtcore_link_at(const struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell) { if (!t) return NULL; - term_write_begin((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); char *text = link_at_text(t, cell); - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return text; } -void term_select_clear(struct term *t) +void wsap_vtcore_select_clear(struct wsap_vtcore *t) { if (t) { - term_write_begin(t); + wsap_vtcore_write_begin(t); t->selection = false; - term_write_end(t); + wsap_vtcore_write_end(t); } } @@ -85,7 +85,7 @@ static inline int word_class(uint32_t c) return 1; } -static inline int sel_point_cmp(struct term_sel_point a, struct term_sel_point b) +static inline int sel_point_cmp(struct wsap_vtcore_sel_point a, struct wsap_vtcore_sel_point b) { if (a.line_id < b.line_id) return -1; if (a.line_id > b.line_id) return 1; @@ -100,7 +100,7 @@ static inline int sel_point_cmp(struct term_sel_point a, struct term_sel_point b * gives the line and segment of each screen row. */ struct lines { - const struct term *t; + const struct wsap_vtcore *t; int cols; bool hist; uint64_t hist_end; @@ -111,7 +111,7 @@ struct lines { /* False when a screen taller than the stack array needs memory and none is * left. L can still be passed to lines_free(). */ -static bool lines_init(struct lines *L, const struct term *t) +static bool lines_init(struct lines *L, const struct wsap_vtcore *t) { L->t = t; L->cols = t->cols; @@ -154,7 +154,7 @@ static inline bool is_open_line(const struct lines *L, uint64_t id) static inline int hist_segs(const struct lines *L, uint64_t id) { - return in_hist(L, id) ? term_hist_line_rows(&L->t->hist, id, L->cols) : 0; + return in_hist(L, id) ? wsap_vtcore_hist_line_rows(&L->t->hist, id, L->cols) : 0; } static int screen_row_of(const struct lines *L, uint64_t id, int seg) @@ -181,14 +181,14 @@ static int line_total_segs(const struct lines *L, uint64_t id) static const struct cell *line_seg_cells(const struct lines *L, uint64_t id, int seg, struct cell *scratch, bool *out_wrapped) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; struct cell *buf = scratch ? scratch : t->view_row_scratch; int hrows = hist_segs(L, id); if (seg < hrows) { - int got = term_hist_decode_segment(&t->hist, id, seg, L->cols, buf, t->gstore); + int got = wsap_vtcore_hist_decode_segment(&t->hist, id, seg, L->cols, buf, t->gstore); bool wrapped = seg + 1 < hrows || is_open_line(L, id); if (got < L->cols) { - fill_cells(buf + got, L->cols - got, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(buf + got, L->cols - got, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); if (wrapped) set_cells_wrap_pad(buf + got, L->cols - got); } @@ -207,7 +207,7 @@ static const struct cell *line_seg_cells(const struct lines *L, uint64_t id, int return srow->cells; if (srow->len > 0) memcpy(buf, srow->cells, (size_t)srow->len * sizeof(struct cell)); - fill_cells(buf + srow->len, L->cols - srow->len, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(buf + srow->len, L->cols - srow->len, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); return buf; } text_row_cells(srow, buf, L->cols); @@ -217,12 +217,12 @@ static const struct cell *line_seg_cells(const struct lines *L, uint64_t id, int /* A line whose segments may not hold exactly cols cells each. */ static bool line_has_wide(const struct lines *L, uint64_t id) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; if (in_hist(L, id)) { - if (term_hist_line_flags(&t->hist, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER)) + if (wsap_vtcore_hist_line_flags(&t->hist, id) & (HLINE_HAS_WIDE | HLINE_HAS_CLUSTER)) return true; if (is_open_line(L, id) && - term_hist_line_cells(&t->hist, id) != (uint64_t)hist_segs(L, id) * (uint64_t)L->cols) + wsap_vtcore_hist_line_cells(&t->hist, id) != (uint64_t)hist_segs(L, id) * (uint64_t)L->cols) return true; } int rows = lines_rows(L); @@ -254,19 +254,19 @@ static uint32_t line_seg_start_off(const struct lines *L, uint64_t id, int seg) if (!line_has_wide(L, id)) return (uint32_t)seg * (uint32_t)L->cols; - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; int hrows = hist_segs(L, id); if (in_hist(L, id)) { if (seg <= hrows) { uint64_t base = id == t->hist.base_cell_id ? t->hist.base_cell : 0; - return (uint32_t)(term_hist_segment_cell(&t->hist, id, seg, L->cols) - base); + return (uint32_t)(wsap_vtcore_hist_segment_cell(&t->hist, id, seg, L->cols) - base); } } uint32_t off = 0; if (in_hist(L, id) && hrows > 0) { uint64_t base = id == t->hist.base_cell_id ? t->hist.base_cell : 0; - off = (uint32_t)(term_hist_segment_cell(&t->hist, id, hrows, L->cols) - base); + off = (uint32_t)(wsap_vtcore_hist_segment_cell(&t->hist, id, hrows, L->cols) - base); } struct cell stack_buf[512]; struct cell *scratch = L->cols <= 512 ? stack_buf : malloc((size_t)L->cols * sizeof(*scratch)); @@ -283,9 +283,9 @@ static uint32_t line_seg_start_off(const struct lines *L, uint64_t id, int seg) /* The line and segment of view row y. */ static bool view_row_line(const struct lines *L, int y, uint64_t *id, int *seg) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; struct hist_view_pos pos; - if (term_hist_view_row_pos(&t->view, &t->hist, L->cols, t->rows, screen_top_line(t), y, &pos)) { + if (wsap_vtcore_hist_view_row_pos(&t->view, &t->hist, L->cols, t->rows, screen_top_line(t), y, &pos)) { *id = pos.id; *seg = pos.seg; return true; @@ -297,9 +297,9 @@ static bool view_row_line(const struct lines *L, int y, uint64_t *id, int *seg) return true; } -static struct term_sel_point view_to_sel_point(const struct lines *L, int x, int y) +static struct wsap_vtcore_sel_point view_to_sel_point(const struct lines *L, int x, int y) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; if (x < 0) x = 0; if (x >= L->cols) x = L->cols - 1; if (y < 0) y = 0; @@ -308,11 +308,11 @@ static struct term_sel_point view_to_sel_point(const struct lines *L, int x, int uint64_t id; int seg; if (!view_row_line(L, y, &id, &seg)) - return (struct term_sel_point){ .line_id = L->first }; + return (struct wsap_vtcore_sel_point){ .line_id = L->first }; const struct cell *cells = line_seg_cells(L, id, seg, NULL, NULL); if (cells && x > 0 && (cells[x].flags & CELL_WRAP_PAD)) x--; - return (struct term_sel_point){ + return (struct wsap_vtcore_sel_point){ .line_id = id, .cell_off = line_seg_start_off(L, id, seg) + (uint32_t)x, }; @@ -328,7 +328,7 @@ static uint32_t line_total_display_cols(const struct lines *L, uint64_t id, int return start + (uint32_t)seg_display_cols(L->cols, cells, wrapped); } -static struct term_sel_point sel_point_next(const struct lines *L, struct term_sel_point pt) +static struct wsap_vtcore_sel_point sel_point_next(const struct lines *L, struct wsap_vtcore_sel_point pt) { int nsegs = line_total_segs(L, pt.line_id); if (nsegs <= 0) @@ -341,12 +341,12 @@ static struct term_sel_point sel_point_next(const struct lines *L, struct term_s uint64_t max_id = L->pos[lines_rows(L) - 1].id; for (uint64_t next = pt.line_id + 1; next <= max_id; next++) if (line_total_segs(L, next) > 0) - return (struct term_sel_point){ .line_id = next }; + return (struct wsap_vtcore_sel_point){ .line_id = next }; pt.cell_off++; return pt; } -static struct term_sel_point sel_point_prev(const struct lines *L, struct term_sel_point pt) +static struct wsap_vtcore_sel_point sel_point_prev(const struct lines *L, struct wsap_vtcore_sel_point pt) { if (pt.cell_off > 0) { pt.cell_off--; @@ -357,36 +357,36 @@ static struct term_sel_point sel_point_prev(const struct lines *L, struct term_s if (nsegs <= 0) continue; uint32_t cols = line_total_display_cols(L, prev, nsegs); - return (struct term_sel_point){ .line_id = prev, .cell_off = cols > 0 ? cols - 1 : 0 }; + return (struct wsap_vtcore_sel_point){ .line_id = prev, .cell_off = cols > 0 ? cols - 1 : 0 }; } return pt; } static void unit_span(const struct lines *L, int x, int y, bool right_half, - enum term_select_unit unit, - struct term_sel_point *first, struct term_sel_point *last) + enum wsap_vtcore_select_unit unit, + struct wsap_vtcore_sel_point *first, struct wsap_vtcore_sel_point *last) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; int cols = L->cols; if (x < 0) x = 0; if (x >= cols) x = cols - 1; if (y < 0) y = 0; if (y >= t->rows) y = t->rows - 1; - if (unit == TERM_SELECT_CELL) { - struct term_sel_point pt = view_to_sel_point(L, x, y); + if (unit == WSAP_VTCORE_SELECT_CELL) { + struct wsap_vtcore_sel_point pt = view_to_sel_point(L, x, y); if (right_half) pt = sel_point_next(L, pt); *first = *last = pt; return; } - if (unit == TERM_SELECT_LINE) { + if (unit == WSAP_VTCORE_SELECT_LINE) { *first = view_to_sel_point(L, 0, y); *last = sel_point_next(L, view_to_sel_point(L, cols - 1, y)); return; } - const struct cell *row = term_screen_view_row(t, y); + const struct cell *row = wsap_vtcore_screen_view_row(t, y); if (row && x > 0 && (row[x].flags & CELL_WRAP_PAD)) x--; int left = x, right = x; @@ -401,16 +401,16 @@ static void unit_span(const struct lines *L, int x, int y, bool right_half, } /* Clamp the selection to the retained lines. A read does not change it. */ -static bool selection_bounds(const struct lines *L, struct term_sel_point *start, - struct term_sel_point *end) +static bool selection_bounds(const struct lines *L, struct wsap_vtcore_sel_point *start, + struct wsap_vtcore_sel_point *end) { - const struct term *t = L->t; + const struct wsap_vtcore *t = L->t; if (!t->selection || t->sel_end.line_id < L->first) return false; *start = t->sel_start; *end = t->sel_end; if (start->line_id < L->first) - *start = (struct term_sel_point){ .line_id = L->first }; + *start = (struct wsap_vtcore_sel_point){ .line_id = L->first }; return sel_point_cmp(*start, *end) <= 0; } @@ -447,7 +447,7 @@ static bool line_locate_cell(const struct lines *L, uint64_t id, uint32_t cell_o } } else { uint64_t base = id == L->t->hist.base_cell_id ? L->t->hist.base_cell : 0; - int seg = term_hist_cell_segment(&L->t->hist, id, base + (uint64_t)cell_off, L->cols); + int seg = wsap_vtcore_hist_cell_segment(&L->t->hist, id, base + (uint64_t)cell_off, L->cols); if (seg < hrows) { uint32_t seg_start = line_seg_start_off(L, id, seg); if (cell_off >= seg_start) { @@ -479,8 +479,8 @@ static bool line_locate_cell(const struct lines *L, uint64_t id, uint32_t cell_o return false; } -static void select_range(struct term *t, const struct lines *L, - struct term_sel_point start, struct term_sel_point end) +static void select_range(struct wsap_vtcore *t, const struct lines *L, + struct wsap_vtcore_sel_point start, struct wsap_vtcore_sel_point end) { if (sel_point_cmp(start, end) > 0) { t->selection = false; @@ -502,49 +502,49 @@ static void select_range(struct term *t, const struct lines *L, t->selection = true; } -bool term_select_start(struct term *t, struct term_vector2i cell, bool right_half, - enum term_select_unit unit) +bool wsap_vtcore_select_start(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half, + enum wsap_vtcore_select_unit unit) { if (!t) return false; - term_write_begin(t); + wsap_vtcore_write_begin(t); struct lines L; if (!lines_init(&L, t)) { lines_free(&L); - term_write_end(t); + wsap_vtcore_write_end(t); return false; } - struct term_sel_point first, last; + struct wsap_vtcore_sel_point first, last; unit_span(&L, cell.x, cell.y, right_half, unit, &first, &last); lines_free(&L); - enum term_select_unit old_unit = t->select_unit; - struct term_sel_point old_first = t->sel_anchor_first, old_last = t->sel_anchor_last; + enum wsap_vtcore_select_unit old_unit = t->select_unit; + struct wsap_vtcore_sel_point old_first = t->sel_anchor_first, old_last = t->sel_anchor_last; bool old_selection = t->selection; t->select_unit = unit; t->sel_anchor_first = first; t->sel_anchor_last = last; t->selection = false; - bool ok = term_select_extend(t, cell, right_half); + bool ok = wsap_vtcore_select_extend(t, cell, right_half); if (!ok) { t->select_unit = old_unit; t->sel_anchor_first = old_first; t->sel_anchor_last = old_last; t->selection = old_selection; } - term_write_end(t); + wsap_vtcore_write_end(t); return ok; } -bool term_select_extend(struct term *t, struct term_vector2i cell, bool right_half) +bool wsap_vtcore_select_extend(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half) { if (!t) return false; - term_write_begin(t); + wsap_vtcore_write_begin(t); struct lines L; if (!lines_init(&L, t)) { lines_free(&L); - term_write_end(t); + wsap_vtcore_write_end(t); return false; } - struct term_sel_point first, last; + struct wsap_vtcore_sel_point first, last; unit_span(&L, cell.x, cell.y, right_half, t->select_unit, &first, &last); if (sel_point_cmp(first, t->sel_anchor_first) > 0) first = t->sel_anchor_first; if (sel_point_cmp(last, t->sel_anchor_last) < 0) last = t->sel_anchor_last; @@ -553,21 +553,21 @@ bool term_select_extend(struct term *t, struct term_vector2i cell, bool right_ha else select_range(t, &L, first, sel_point_prev(&L, last)); lines_free(&L); - term_write_end(t); + wsap_vtcore_write_end(t); return true; } -bool term_has_selection(const struct term *t) +bool wsap_vtcore_has_selection(const struct wsap_vtcore *t) { if (!t) return false; - term_write_begin((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); bool has = t->selection && t->sel_end.line_id >= first_retained_line(t); - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return has; } -bool term_selection_view_spans(const struct term *t, int *c0, int *c1) +bool wsap_vtcore_selection_view_spans(const struct wsap_vtcore *t, int *c0, int *c1) { int rows = t->rows, cols = t->cols; for (int y = 0; y < rows; y++) { @@ -581,7 +581,7 @@ bool term_selection_view_spans(const struct term *t, int *c0, int *c1) lines_free(&L); return false; } - struct term_sel_point start, end; + struct wsap_vtcore_sel_point start, end; if (!selection_bounds(&L, &start, &end)) { lines_free(&L); return true; @@ -644,8 +644,8 @@ static bool text_reserve(char **text, size_t *cap, size_t need) return true; } -static char *range_text_inner(const struct term *t, - const struct term_sel_point *bounds) +static char *range_text_inner(const struct wsap_vtcore *t, + const struct wsap_vtcore_sel_point *bounds) { if (!t || (!bounds && !t->selection)) return NULL; struct lines L; @@ -653,7 +653,7 @@ static char *range_text_inner(const struct term *t, lines_free(&L); return NULL; } - struct term_sel_point start, end; + struct wsap_vtcore_sel_point start, end; if (bounds) { start = bounds[0]; end = bounds[1]; @@ -697,7 +697,7 @@ static char *range_text_inner(const struct term *t, take = end_seg - seg + 1; if (!batch_cells) batch_cells = malloc((size_t)BATCH_SEGS * (size_t)t->cols * sizeof(struct cell)); - batch_len = batch_cells ? term_hist_decode_segments(&t->hist, id, batch_start, take, + batch_len = batch_cells ? wsap_vtcore_hist_decode_segments(&t->hist, id, batch_start, take, t->cols, batch_cells, batch_lens, t->gstore) : 0; } @@ -707,7 +707,7 @@ static char *range_text_inner(const struct term *t, int got = batch_lens[idx]; row_wrapped = seg + 1 < hrows || is_open_line(&L, id); if (got < t->cols) { - fill_cells(row_buf + got, t->cols - got, TERM_COLOR_FG, TERM_COLOR_BG); + fill_cells(row_buf + got, t->cols - got, WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); if (row_wrapped) set_cells_wrap_pad(row_buf + got, t->cols - got); } @@ -775,17 +775,17 @@ static char *range_text_inner(const struct term *t, uint32_t cp = cells[c].c; if (cells[c].flags & (CELL_TRAIL | CELL_WRAP_PAD)) continue; - /* One cell expands to TERM_GRAPHEME_MAX_LEN code points of up + /* One cell expands to WSAP_VTCORE_GRAPHEME_MAX_LEN code points of up * to 4 bytes each. Leave room for all of them. */ - if (!text_reserve(&text, &cap, n + (size_t)TERM_GRAPHEME_MAX_LEN * 4 + 1)) + if (!text_reserve(&text, &cap, n + (size_t)WSAP_VTCORE_GRAPHEME_MAX_LEN * 4 + 1)) break; if (cp > 0 && cp < 128) { text[n++] = (char)cp; } else { - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; - int len = term_gstore_expand(t->gstore, cp ? cp : ' ', cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int len = wsap_vtcore_gstore_expand(t->gstore, cp ? cp : ' ', cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); for (int k = 0; k < len; k++) - n += (size_t)term_utf8_encode(cps[k], text + n); + n += (size_t)wsap_vtcore_utf8_encode(cps[k], text + n); } } if (text && !is_last && !wrapped && text_reserve(&text, &cap, n + 2)) @@ -799,34 +799,34 @@ static char *range_text_inner(const struct term *t, return text; } -char *term_history_text(struct term *t, int max_rows) +char *wsap_vtcore_history_text(struct wsap_vtcore *t, int max_rows) { if (!t) return NULL; - term_write_begin(t); - term_hist_prepare_rows(&t->hist, t->cols); - if (!term_hist_view_sync(&t->view, &t->hist, t->cols)) { - term_write_end(t); + wsap_vtcore_write_begin(t); + wsap_vtcore_hist_prepare_rows(&t->hist, t->cols); + if (!wsap_vtcore_hist_view_sync(&t->view, &t->hist, t->cols)) { + wsap_vtcore_write_end(t); return NULL; } - int end_row = term_screen_history_rows(t) - term_view_offset(t); + int end_row = wsap_vtcore_screen_history_rows(t) - wsap_vtcore_view_offset(t); if (max_rows <= 0 || end_row <= 0) { - term_write_end(t); - return term_strdup(""); + wsap_vtcore_write_end(t); + return wsap_vtcore_strdup(""); } int begin_row = end_row > max_rows ? end_row - max_rows : 0; struct lines L; if (!lines_init(&L, t)) { lines_free(&L); - term_write_end(t); + wsap_vtcore_write_end(t); return NULL; } - struct term_sel_point bounds[2] = {0}; + struct wsap_vtcore_sel_point bounds[2] = {0}; int first_seg, last_seg; char *text = NULL; - if (term_hist_view_find_row(&t->view, &t->hist, begin_row, t->cols, + if (wsap_vtcore_hist_view_find_row(&t->view, &t->hist, begin_row, t->cols, &bounds[0].line_id, &first_seg) && - term_hist_view_find_row(&t->view, &t->hist, end_row - 1, t->cols, + wsap_vtcore_hist_view_find_row(&t->view, &t->hist, end_row - 1, t->cols, &bounds[1].line_id, &last_seg)) { bounds[0].cell_off = line_seg_start_off(&L, bounds[0].line_id, first_seg); uint32_t last_start = line_seg_start_off(&L, bounds[1].line_id, last_seg); @@ -846,15 +846,15 @@ char *term_history_text(struct term *t, int max_rows) } } lines_free(&L); - term_write_end(t); + wsap_vtcore_write_end(t); return text; } -char *term_selection_text(const struct term *t) +char *wsap_vtcore_selection_text(const struct wsap_vtcore *t) { if (!t) return NULL; - term_write_begin((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); char *text = range_text_inner(t, NULL); - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return text; } @@ -1,5 +1,5 @@ -#ifndef TERM_SIMD_H -#define TERM_SIMD_H +#ifndef WSAP_VTCORE_SIMD_H +#define WSAP_VTCORE_SIMD_H #include "compat.h" @@ -18,91 +18,91 @@ /* * x86-64 kernels come in three levels: base (SSE2), AVX2 (x86-64-v3), and * AVX-512 (x86-64-v4 with VBMI and VBMI2). GCC and Clang compile every - * level with target attributes, and term_isa_init() picks one at run time. + * level with target attributes, and wsap_vtcore_isa_init() picks one at run time. * Other compilers compile the levels that their flags enable. * - * A kernel at a level is a function marked TERM_TARGET_AVX2 or - * TERM_TARGET_AVX512. It exists when TERM_KERNEL_AVX2 or TERM_KERNEL_AVX512 - * is defined. Call it only when term_use_avx2() or term_use_avx512() is + * A kernel at a level is a function marked WSAP_VTCORE_TARGET_AVX2 or + * WSAP_VTCORE_TARGET_AVX512. It exists when WSAP_VTCORE_KERNEL_AVX2 or WSAP_VTCORE_KERNEL_AVX512 + * is defined. Call it only when wsap_vtcore_use_avx2() or wsap_vtcore_use_avx512() is * true. When the compiler flags already enable a level, these checks are * constants and the kernels inline into their callers. */ #if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512CD__) && \ defined(__AVX512DQ__) && defined(__AVX512VL__) && defined(__AVX512VBMI__) && \ defined(__AVX512VBMI2__) && defined(__AVX2__) && defined(__BMI2__) -#define TERM_ISA_FLOOR 2 +#define WSAP_VTCORE_ISA_FLOOR 2 #elif defined(__AVX2__) && defined(__BMI__) && defined(__BMI2__) && defined(__FMA__) && \ defined(__LZCNT__) -#define TERM_ISA_FLOOR 1 +#define WSAP_VTCORE_ISA_FLOOR 1 #else -#define TERM_ISA_FLOOR 0 +#define WSAP_VTCORE_ISA_FLOOR 0 #endif /* Clang 18 to 21 also need evex512 for 512-bit vectors. GCC and Clang 22 * reject the name. Apple Clang 17 is LLVM 19. */ #if defined(__clang__) && ((defined(__apple_build_version__) && __clang_major__ >= 17) || \ (!defined(__apple_build_version__) && __clang_major__ >= 18 && __clang_major__ <= 21)) -#define TERM_EVEX512 ",evex512" +#define WSAP_VTCORE_EVEX512 ",evex512" #else -#define TERM_EVEX512 "" +#define WSAP_VTCORE_EVEX512 "" #endif -#if (defined(__x86_64__) || defined(_M_X64)) && defined(TERM_COMPILER_GNU) -#define TERM_TARGET_AVX2 \ +#if (defined(__x86_64__) || defined(_M_X64)) && defined(WSAP_VTCORE_COMPILER_GNU) +#define WSAP_VTCORE_TARGET_AVX2 \ __attribute__((target("avx2,bmi,bmi2,fma,lzcnt,popcnt,movbe,f16c"))) -#define TERM_TARGET_AVX512 \ +#define WSAP_VTCORE_TARGET_AVX512 \ __attribute__((target("avx2,bmi,bmi2,fma,lzcnt,popcnt,movbe,f16c,avx512f,avx512bw," \ - "avx512cd,avx512dq,avx512vl,avx512vbmi,avx512vbmi2" TERM_EVEX512))) -#define TERM_KERNEL_AVX2 1 -#define TERM_KERNEL_AVX512 1 -#define TERM_ISA_RUNTIME 1 + "avx512cd,avx512dq,avx512vl,avx512vbmi,avx512vbmi2" WSAP_VTCORE_EVEX512))) +#define WSAP_VTCORE_KERNEL_AVX2 1 +#define WSAP_VTCORE_KERNEL_AVX512 1 +#define WSAP_VTCORE_ISA_RUNTIME 1 #else -#define TERM_TARGET_AVX2 -#define TERM_TARGET_AVX512 -#if TERM_ISA_FLOOR >= 1 -#define TERM_KERNEL_AVX2 1 +#define WSAP_VTCORE_TARGET_AVX2 +#define WSAP_VTCORE_TARGET_AVX512 +#if WSAP_VTCORE_ISA_FLOOR >= 1 +#define WSAP_VTCORE_KERNEL_AVX2 1 #endif -#if TERM_ISA_FLOOR >= 2 -#define TERM_KERNEL_AVX512 1 +#if WSAP_VTCORE_ISA_FLOOR >= 2 +#define WSAP_VTCORE_KERNEL_AVX512 1 #endif #endif -enum { TERM_ISA_BASE, TERM_ISA_AVX2, TERM_ISA_AVX512 }; +enum { WSAP_VTCORE_ISA_BASE, WSAP_VTCORE_ISA_AVX2, WSAP_VTCORE_ISA_AVX512 }; -/* The level in use. Zero, the base level, until term_isa_init() runs. It +/* The level in use. Zero, the base level, until wsap_vtcore_isa_init() runs. It * is a plain int, so the compiler can hoist the checks out of loops: it is * written once, before the release that publishes it, and read only after * that. */ -extern int term_isa_level; +extern int wsap_vtcore_isa_level; -/* Pick the level once. Any thread can call it. term_new() calls it before +/* Pick the level once. Any thread can call it. wsap_vtcore_new() calls it before * the first terminal exists. */ -void term_isa_init(void); +void wsap_vtcore_isa_init(void); -static inline bool term_use_avx2(void) +static inline bool wsap_vtcore_use_avx2(void) { -#if TERM_ISA_FLOOR >= 1 +#if WSAP_VTCORE_ISA_FLOOR >= 1 return true; -#elif defined(TERM_ISA_RUNTIME) - return term_isa_level >= TERM_ISA_AVX2; +#elif defined(WSAP_VTCORE_ISA_RUNTIME) + return wsap_vtcore_isa_level >= WSAP_VTCORE_ISA_AVX2; #else return false; #endif } -static inline bool term_use_avx512(void) +static inline bool wsap_vtcore_use_avx512(void) { -#if TERM_ISA_FLOOR >= 2 +#if WSAP_VTCORE_ISA_FLOOR >= 2 return true; -#elif defined(TERM_ISA_RUNTIME) - return term_isa_level >= TERM_ISA_AVX512; +#elif defined(WSAP_VTCORE_ISA_RUNTIME) + return wsap_vtcore_isa_level >= WSAP_VTCORE_ISA_AVX512; #else return false; #endif } #if defined(__aarch64__) -static inline uint16_t term_lane_bits(uint8x16_t m) +static inline uint16_t wsap_vtcore_lane_bits(uint8x16_t m) { const uint8x16_t idx = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128}; diff --git a/src/snapshot.c b/src/snapshot.c index 6f396e2..f7e906c 100644 --- a/src/snapshot.c +++ b/src/snapshot.c @@ -10,16 +10,16 @@ * Cluster cells refer to an arena of [length, code points...] records that * the snapshot owns, so a renderer never reads the terminal's cluster table. */ -struct term_snapshot { - struct term_view view; - uint32_t palette[TERM_PALETTE_SIZE]; +struct wsap_vtcore_snapshot { + struct wsap_vtcore_view view; + uint32_t palette[WSAP_VTCORE_PALETTE_SIZE]; uint64_t source; /* serial of the terminal it copied */ - struct term_cell *cells; /* rows * cols */ - struct term_cell *stage; /* rows * cols: changed rows, before apply() */ + struct wsap_vtcore_cell *cells; /* rows * cols */ + struct wsap_vtcore_cell *stage; /* rows * cols: changed rows, before apply() */ uint64_t *keys; /* per row */ uint32_t *row_clusters; /* arena records each row holds */ - struct term_span *selection; /* per row */ + struct wsap_vtcore_span *selection; /* per row */ size_t cell_cap; int row_cap; @@ -30,15 +30,15 @@ struct term_snapshot { uint32_t spare_cap; }; -struct term_snapshot *term_snapshot_new(void) +struct wsap_vtcore_snapshot *wsap_vtcore_snapshot_new(void) { - struct term_snapshot *s = calloc(1, sizeof(*s)); + struct wsap_vtcore_snapshot *s = calloc(1, sizeof(*s)); if (s) s->view.palette = s->palette; return s; } -void term_snapshot_free(struct term_snapshot *s) +void wsap_vtcore_snapshot_free(struct wsap_vtcore_snapshot *s) { if (!s) return; @@ -54,15 +54,15 @@ void term_snapshot_free(struct term_snapshot *s) /* Make room for cols x rows. A failed call keeps the old contents, so the * snapshot stays readable. */ -static bool reserve(struct term_snapshot *s, int cols, int rows) +static bool reserve(struct wsap_vtcore_snapshot *s, int cols, int rows) { size_t cells = (size_t)cols * (size_t)rows; if (cells > s->cell_cap) { - struct term_cell *c = realloc(s->cells, cells * sizeof(*c)); + struct wsap_vtcore_cell *c = realloc(s->cells, cells * sizeof(*c)); if (!c) return false; s->cells = c; - struct term_cell *st = realloc(s->stage, cells * sizeof(*st)); + struct wsap_vtcore_cell *st = realloc(s->stage, cells * sizeof(*st)); if (!st) return false; s->stage = st; @@ -75,7 +75,7 @@ static bool reserve(struct term_snapshot *s, int cols, int rows) uint32_t *rc = realloc(s->row_clusters, (size_t)rows * sizeof(*rc)); if (rc) s->row_clusters = rc; - struct term_span *sel = realloc(s->selection, (size_t)rows * sizeof(*sel)); + struct wsap_vtcore_span *sel = realloc(s->selection, (size_t)rows * sizeof(*sel)); if (sel) s->selection = sel; if (!k || !rc || !sel) @@ -95,14 +95,14 @@ struct arena_out { }; /* Make room for need words. False when memory runs out or an offset would not - * fit below TERM_TEXT_CLUSTER. */ + * fit below WSAP_VTCORE_TEXT_CLUSTER. */ static bool arena_reserve(struct arena_out *a, uint64_t need) { - if (need > TERM_TEXT_CLUSTER) + if (need > WSAP_VTCORE_TEXT_CLUSTER) return false; if (need <= *a->cap) return true; - uint32_t cap = term_grow_cap32(*a->cap ? *a->cap * 2 : 256, (uint32_t)need); + uint32_t cap = wsap_vtcore_grow_cap32(*a->cap ? *a->cap * 2 : 256, (uint32_t)need); uint32_t *grown = realloc(*a->buf, cap * sizeof(*grown)); if (!grown) return false; @@ -116,8 +116,8 @@ static bool arena_reserve(struct arena_out *a, uint64_t need) static bool arena_add(struct arena_out *a, const struct gstore *g, uint32_t handle, uint32_t *text) { - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; - int n = term_gstore_expand(g, handle, cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + int n = wsap_vtcore_gstore_expand(g, handle, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); if (n <= 0) { *text = ' '; return true; @@ -129,24 +129,24 @@ static bool arena_add(struct arena_out *a, const struct gstore *g, uint32_t hand (*a->buf)[off] = (uint32_t)n; memcpy(&(*a->buf)[off + 1], cps, (size_t)n * sizeof(*cps)); a->len = (uint32_t)need; - *text = TERM_TEXT_CLUSTER | off; + *text = WSAP_VTCORE_TEXT_CLUSTER | off; return true; } /* Convert one stored row into dst. False when a cluster record does not fit. */ static bool convert_row(struct arena_out *a, const struct gstore *g, - struct term_cell *dst, const struct cell *src, int cols) + struct wsap_vtcore_cell *dst, const struct cell *src, int cols) { for (int x = 0; x < cols; x++) { const struct cell *c = &src[x]; uint16_t f = c->flags; uint32_t text = c->c; - if (TERM_EXPECT(text < 0x20, 0)) + if (WSAP_VTCORE_EXPECT(text < 0x20, 0)) text = text ? ' ' : 0; - else if (TERM_EXPECT(term_grapheme_is_handle(text), 0) && + else if (WSAP_VTCORE_EXPECT(wsap_vtcore_grapheme_is_handle(text), 0) && !arena_add(a, g, text, &text)) return false; - dst[x] = (struct term_cell){ + dst[x] = (struct wsap_vtcore_cell){ .text = text, .fg = c->fg, .bg = c->bg, @@ -175,7 +175,7 @@ struct plan { }; /* Phase 2: write the plan into the snapshot. Nothing here can fail. */ -static void apply(struct term_snapshot *s, const struct term *t, const struct plan *p) +static void apply(struct wsap_vtcore_snapshot *s, const struct wsap_vtcore *t, const struct plan *p) { int cols = t->cols, rows = t->rows; int k = p->scrolled; @@ -190,7 +190,7 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl s->arena_len = p->arena_len; bool changed = p->all; - size_t row_bytes = (size_t)cols * sizeof(struct term_cell); + size_t row_bytes = (size_t)cols * sizeof(struct wsap_vtcore_cell); /* Staged rows: copy the smaller part. Either the kept rows go into the * stage, which then becomes the cells, or the staged rows go into the * cells. A scroll moves every kept row anyway, so it swaps. */ @@ -201,7 +201,7 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl for (int y = 0; y < rows; y++) if (p->words[y] == ROW_KEPT) memcpy(s->stage + (size_t)y * cols, s->cells + (size_t)(y + k) * cols, row_bytes); - struct term_cell *cells = s->cells; + struct wsap_vtcore_cell *cells = s->cells; s->cells = s->stage; s->stage = cells; } @@ -225,7 +225,7 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl /* Phase 1 reserved room for the worst case, so this cannot fail. */ struct arena_out a = { &s->arena, &s->arena_cap, s->arena_len }; (void)convert_row(&a, t->gstore, s->cells + (size_t)y * cols, - term_screen_view_row(t, y), cols); + wsap_vtcore_screen_view_row(t, y), cols); s->row_clusters[y] = a.len - s->arena_len; s->arena_len = a.len; } else { @@ -238,19 +238,19 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl } for (int y = 0; y < rows; y++) { - struct term_span span = p->c1[y] >= p->c0[y] ? (struct term_span){ p->c0[y], p->c1[y] + 1 } - : (struct term_span){ 0 }; + struct wsap_vtcore_span span = p->c1[y] >= p->c0[y] ? (struct wsap_vtcore_span){ p->c0[y], p->c1[y] + 1 } + : (struct wsap_vtcore_span){ 0 }; if (p->all || span.begin != s->selection[y].begin || span.end != s->selection[y].end) changed = true; s->selection[y] = span; } - struct term_cursor cursor = term_cursor(t); - int view_offset = term_view_offset(t); + struct wsap_vtcore_cursor cursor = wsap_vtcore_cursor(t); + int view_offset = wsap_vtcore_view_offset(t); cursor.pos.y += view_offset; if (cursor.pos.y >= rows) cursor.visible = false; - const struct term_cursor *old = &s->view.cursor; + const struct wsap_vtcore_cursor *old = &s->view.cursor; if (cursor.pos.x != old->pos.x || cursor.pos.y != old->pos.y || cursor.style != old->style || cursor.visible != old->visible || cursor.blink != old->blink || @@ -264,7 +264,7 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl } s->source = t->serial; - s->view.size = (struct term_vector2i){ .x = cols, .y = rows }; + s->view.size = (struct wsap_vtcore_vector2i){ .x = cols, .y = rows }; s->view.cursor = cursor; s->view.scroll_offset = view_offset; s->view.scrolled = k; @@ -275,7 +275,7 @@ static void apply(struct term_snapshot *s, const struct term *t, const struct pl /* Phase 1 for one update. Allocates and checks everything that can fail, * then hands the plan to apply(). A false return leaves the content as it was. */ -static bool term_snapshot_update_inner(struct term_snapshot *s, struct term *t) +static bool wsap_vtcore_snapshot_update_inner(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t) { if (!s || !t) return false; @@ -311,12 +311,12 @@ static bool term_snapshot_update_inner(struct term_snapshot *s, struct term *t) if (s->arena_dead > 4096 && s->arena_dead * 2 > s->arena_len) all = true; - term_hist_prepare_rows(&t->hist, cols); - if (!term_hist_view_sync(&t->view, &t->hist, cols)) + wsap_vtcore_hist_prepare_rows(&t->hist, cols); + if (!wsap_vtcore_hist_view_sync(&t->view, &t->hist, cols)) goto done; - term_hist_view_refine(&t->view, &t->hist, cols, rows); + wsap_vtcore_hist_view_refine(&t->view, &t->hist, cols, rows); for (int y = 0; y < rows; y++) - new_keys[y] = term_screen_view_row_key(t, y); + new_keys[y] = wsap_vtcore_screen_view_row_key(t, y); if (!all && rows > 1) { int cand_k = 0; @@ -377,7 +377,7 @@ static bool term_snapshot_update_inner(struct term_snapshot *s, struct term *t) * records after the live ones, or in the spare arena for a rebuild. */ struct arena_out a = all ? (struct arena_out){ &s->spare, &s->spare_cap, 0 } : (struct arena_out){ &s->arena, &s->arena_cap, s->arena_len }; - uint64_t worst = (uint64_t)p.staged * (uint64_t)cols * (1 + TERM_GRAPHEME_MAX_LEN); + uint64_t worst = (uint64_t)p.staged * (uint64_t)cols * (1 + WSAP_VTCORE_GRAPHEME_MAX_LEN); if (!all && worst <= DIRECT_MAX_WORDS) { if (!arena_reserve(&a, a.len + worst)) goto done; @@ -388,13 +388,13 @@ static bool term_snapshot_update_inner(struct term_snapshot *s, struct term *t) continue; uint32_t before = a.len; if (!convert_row(&a, t->gstore, s->stage + (size_t)y * cols, - term_screen_view_row(t, y), cols)) + wsap_vtcore_screen_view_row(t, y), cols)) goto done; words[y] = a.len - before; } } - if (!term_selection_view_spans(t, c0, c1)) + if (!wsap_vtcore_selection_view_spans(t, c0, c1)) goto done; p.all = all; p.scrolled = scrolled; @@ -407,52 +407,52 @@ done: return ok; } -bool term_snapshot_update(struct term_snapshot *s, struct term *t) +bool wsap_vtcore_snapshot_update(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t) { if (!s || !t) return false; - term_write_begin(t); - bool ok = term_snapshot_update_inner(s, t); - term_write_end(t); + wsap_vtcore_write_begin(t); + bool ok = wsap_vtcore_snapshot_update_inner(s, t); + wsap_vtcore_write_end(t); return ok; } -const struct term_view *term_snapshot_view(const struct term_snapshot *s) +const struct wsap_vtcore_view *wsap_vtcore_snapshot_view(const struct wsap_vtcore_snapshot *s) { return s ? &s->view : NULL; } -const struct term_cell *term_snapshot_row(const struct term_snapshot *s, int y) +const struct wsap_vtcore_cell *wsap_vtcore_snapshot_row(const struct wsap_vtcore_snapshot *s, int y) { if (!s || y < 0 || y >= s->view.size.y) return NULL; return s->cells + (size_t)y * s->view.size.x; } -uint64_t term_snapshot_row_key(const struct term_snapshot *s, int y) +uint64_t wsap_vtcore_snapshot_row_key(const struct wsap_vtcore_snapshot *s, int y) { if (!s || y < 0 || y >= s->view.size.y) return 0; return s->keys[y]; } -struct term_span term_snapshot_row_selection(const struct term_snapshot *s, int y) +struct wsap_vtcore_span wsap_vtcore_snapshot_row_selection(const struct wsap_vtcore_snapshot *s, int y) { if (!s || y < 0 || y >= s->view.size.y) - return (struct term_span){ 0 }; + return (struct wsap_vtcore_span){ 0 }; return s->selection[y]; } -int term_snapshot_cluster(const struct term_snapshot *s, uint32_t text, uint32_t *cps, int cap) +int wsap_vtcore_snapshot_cluster(const struct wsap_vtcore_snapshot *s, uint32_t text, uint32_t *cps, int cap) { if (!s) return 0; - if (!(text & TERM_TEXT_CLUSTER)) { + if (!(text & WSAP_VTCORE_TEXT_CLUSTER)) { if (cps && cap > 0) cps[0] = text; return 1; } - uint32_t off = text & ~TERM_TEXT_CLUSTER; + uint32_t off = text & ~WSAP_VTCORE_TEXT_CLUSTER; if (off >= s->arena_len) return 0; int n = (int)s->arena[off]; @@ -1,47 +1,47 @@ #include "internal.h" #include "screen.h" -_Thread_local char term_thread_anchor; +_Thread_local char wsap_vtcore_thread_anchor; -const char *term_unicode_version(void) +const char *wsap_vtcore_unicode_version(void) { - return TERM_UNICODE_DATA_VERSION; + return WSAP_VTCORE_UNICODE_DATA_VERSION; } -unsigned term_version(void) +unsigned wsap_vtcore_version(void) { - return TERM_VERSION_CODE; + return WSAP_VTCORE_VERSION_CODE; } -void term_lock(struct term *t) +void wsap_vtcore_lock(struct wsap_vtcore *t) { - term_write_begin(t); + wsap_vtcore_write_begin(t); } -void term_unlock(struct term *t) +void wsap_vtcore_unlock(struct wsap_vtcore *t) { - term_write_end(t); + wsap_vtcore_write_end(t); } -struct term_vector2i term_size(const struct term *t) +struct wsap_vtcore_vector2i wsap_vtcore_size(const struct wsap_vtcore *t) { if (!t) - return (struct term_vector2i){ 0 }; - term_write_begin((struct term *)t); - struct term_vector2i size = { .x = t->cols, .y = t->rows }; - term_write_end((struct term *)t); + return (struct wsap_vtcore_vector2i){ 0 }; + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + struct wsap_vtcore_vector2i size = { .x = t->cols, .y = t->rows }; + wsap_vtcore_write_end((struct wsap_vtcore *)t); return size; } -struct term_modes term_modes(const struct term *t) +struct wsap_vtcore_modes wsap_vtcore_modes(const struct wsap_vtcore *t) { if (!t) - return (struct term_modes){ 0 }; - term_write_begin((struct term *)t); - struct term_modes m = { + return (struct wsap_vtcore_modes){ 0 }; + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + struct wsap_vtcore_modes m = { .keyboard = t->keyboard[t->alternate].flags, - .mouse = (enum term_mouse)t->mouse_mode, - .mouse_encoding = (enum term_mouse_encoding)t->mouse_encoding, + .mouse = (enum wsap_vtcore_mouse)t->mouse_mode, + .mouse_encoding = (enum wsap_vtcore_mouse_encoding)t->mouse_encoding, .grid = { .x = t->cols, .y = t->rows }, .app_cursor = t->application_cursor, .app_keypad = t->application_keypad, @@ -52,82 +52,82 @@ struct term_modes term_modes(const struct term *t) .reverse_video = t->reverse_video, .synchronized = t->synchronized_output, }; - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return m; } -struct term_cursor term_cursor(const struct term *t) +struct wsap_vtcore_cursor wsap_vtcore_cursor(const struct wsap_vtcore *t) { if (!t) - return (struct term_cursor){ .visible = true }; - term_write_begin((struct term *)t); - struct term_cursor c = { + return (struct wsap_vtcore_cursor){ .visible = true }; + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + struct wsap_vtcore_cursor c = { .pos = { .x = t->cursor_x, .y = t->cursor_y }, .style = t->cursor_style, .visible = t->cursor_visible, .blink = t->cursor_blink, }; - term_write_end((struct term *)t); + wsap_vtcore_write_end((struct wsap_vtcore *)t); return c; } -void term_set_cursor_default(struct term *t, enum term_cursor_style style, bool steady) +void wsap_vtcore_set_cursor_default(struct wsap_vtcore *t, enum wsap_vtcore_cursor_style style, bool steady) { if (!t) return; - term_write_begin(t); - if (style > TERM_CURSOR_BAR) - style = TERM_CURSOR_BLOCK; + wsap_vtcore_write_begin(t); + if (style > WSAP_VTCORE_CURSOR_BAR) + style = WSAP_VTCORE_CURSOR_BLOCK; if (t->cursor_style != style || t->cursor_blink == steady) { - struct srow *cur = term_row(t, t->cursor_y); + struct srow *cur = wsap_vtcore_row(t, t->cursor_y); if (cur) cur->version++; } t->default_cursor_style = t->cursor_style = style; t->default_cursor_blink = t->cursor_blink = !steady; - term_write_end(t); + wsap_vtcore_write_end(t); } -void term_set_theme(struct term *t, const struct term_theme *theme) +void wsap_vtcore_set_theme(struct wsap_vtcore *t, const struct wsap_vtcore_theme *theme) { if (!t) return; - term_write_begin(t); + wsap_vtcore_write_begin(t); struct palette next = { .version = t->palette.version }; - term_palette_init(&next, theme); + wsap_vtcore_palette_init(&next, theme); if (memcmp(&next.theme, &t->palette.theme, sizeof(next.theme))) t->palette = next; - term_write_end(t); + wsap_vtcore_write_end(t); } -void term_focus(struct term *t, bool focused) +void wsap_vtcore_focus(struct wsap_vtcore *t, bool focused) { if (!t) return; - term_write_begin(t); + wsap_vtcore_write_begin(t); if (t->focus_events) send_response(t, focused ? "\033[I" : "\033[O"); - term_write_end(t); + wsap_vtcore_write_end(t); } -char *term_cwd(const struct term *t) +char *wsap_vtcore_cwd(const struct wsap_vtcore *t) { if (!t) return NULL; - term_write_begin((struct term *)t); - char *text = t->cwd ? term_strdup(t->cwd) : NULL; - term_write_end((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + char *text = t->cwd ? wsap_vtcore_strdup(t->cwd) : NULL; + wsap_vtcore_write_end((struct wsap_vtcore *)t); return text; } -char *term_pointer_shape(const struct term *t) +char *wsap_vtcore_pointer_shape(const struct wsap_vtcore *t) { if (!t) return NULL; - term_write_begin((struct term *)t); - char *text = t->pointer_shape ? term_strdup(t->pointer_shape) : NULL; - term_write_end((struct term *)t); + wsap_vtcore_write_begin((struct wsap_vtcore *)t); + char *text = t->pointer_shape ? wsap_vtcore_strdup(t->pointer_shape) : NULL; + wsap_vtcore_write_end((struct wsap_vtcore *)t); return text; } -void term_text_free(char *text) +void wsap_vtcore_text_free(char *text) { free(text); } @@ -12,7 +12,7 @@ #include <stdio.h> #include <string.h> -static inline void emit_codepoint(struct term *t, uint32_t cp, int klass, uint16_t flags) +static inline void emit_codepoint(struct wsap_vtcore *t, uint32_t cp, int klass, uint16_t flags) { static const uint32_t dec_graphics[] = { 0x00a0, @@ -28,7 +28,7 @@ static inline void emit_codepoint(struct term *t, uint32_t cp, int klass, uint16 char ch = c1_map[cp - 0x80]; if (ch) { t->state = ST_ESC; - term_escape_byte(t, (unsigned char)ch); + wsap_vtcore_escape_byte(t, (unsigned char)ch); } return; } @@ -39,38 +39,38 @@ static inline void emit_codepoint(struct term *t, uint32_t cp, int klass, uint16 sc_print_cell(t, cp, klass, flags); } -static inline void emit_decoded(struct term *t, uint32_t cp, uint16_t flags) +static inline void emit_decoded(struct wsap_vtcore *t, uint32_t cp, uint16_t flags) { - int klass = term_text_class(cp); - if (!term_sc_extend_cluster(t, cp, klass)) + int klass = wsap_vtcore_text_class(cp); + if (!wsap_vtcore_sc_extend_cluster(t, cp, klass)) emit_codepoint(t, cp, klass, flags); } /* A byte that cannot continue a UTF-8 sequence ends it: the unfinished * sequence prints U+FFFD (Unicode 3.9, maximal subparts). */ -void term_text_utf8_interrupt(struct term *t) +void wsap_vtcore_text_utf8_interrupt(struct wsap_vtcore *t) { - if (TERM_EXPECT(t->utf8_state == TERM_UTF8_ACCEPT, 1)) + if (WSAP_VTCORE_EXPECT(t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT, 1)) return; - t->utf8_state = TERM_UTF8_ACCEPT; - emit_decoded(t, 0xFFFD, term_current_flags(t)); + t->utf8_state = WSAP_VTCORE_UTF8_ACCEPT; + emit_decoded(t, 0xFFFD, wsap_vtcore_current_flags(t)); } -void term_text_ground(struct term *t, unsigned char ch) +void wsap_vtcore_text_ground(struct wsap_vtcore *t, unsigned char ch) { - if (ch >= 0x20 && ch < 0x7f && t->utf8_state == TERM_UTF8_ACCEPT) { - emit_codepoint(t, ch, 1, term_current_flags(t)); + if (ch >= 0x20 && ch < 0x7f && t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT) { + emit_codepoint(t, ch, 1, wsap_vtcore_current_flags(t)); return; } if (ch < 0x20 || ch == 0x7f) - term_text_utf8_interrupt(t); + wsap_vtcore_text_utf8_interrupt(t); - if (TERM_EXPECT(ch == 0x1b, 0)) { - term_escape_begin(t); + if (WSAP_VTCORE_EXPECT(ch == 0x1b, 0)) { + wsap_vtcore_escape_begin(t); } else if (ch == '\n' || ch == 0x0b || ch == 0x0c) { /* VT and FF act as LF (xterm). */ - if (term_lnm(t)) sc_cr(t); + if (wsap_vtcore_lnm(t)) sc_cr(t); sc_linefeed(t, 1); } else if (ch == '\r') { sc_cr(t); @@ -78,9 +78,9 @@ void term_text_ground(struct term *t, unsigned char ch) t->pending_wrap = false; if (t->cursor_x > 0) t->cursor_x--; - term_row(t, t->cursor_y)->version++; + wsap_vtcore_row(t, t->cursor_y)->version++; } else if (ch == '\t') { - term_sc_tab(t, 1); + wsap_vtcore_sc_tab(t, 1); } else if (ch == 0x07) { if (t->cb.bell) t->cb.bell(t->cb.ud); @@ -92,55 +92,55 @@ void term_text_ground(struct term *t, unsigned char ch) t->graphics = t->charsets[0] == '0'; } else if (ch >= 0x20 && ch != 0x7f) { uint32_t before = t->utf8_state; - uint32_t st = term_utf8_decode(&t->utf8_state, &t->utf8_codep, ch); - if (st == TERM_UTF8_ACCEPT) { - emit_decoded(t, t->utf8_codep, term_current_flags(t)); - } else if (st == TERM_UTF8_REJECT) { - t->utf8_state = TERM_UTF8_ACCEPT; - emit_decoded(t, 0xFFFD, term_current_flags(t)); + uint32_t st = wsap_vtcore_utf8_decode(&t->utf8_state, &t->utf8_codep, ch); + if (st == WSAP_VTCORE_UTF8_ACCEPT) { + emit_decoded(t, t->utf8_codep, wsap_vtcore_current_flags(t)); + } else if (st == WSAP_VTCORE_UTF8_REJECT) { + t->utf8_state = WSAP_VTCORE_UTF8_ACCEPT; + emit_decoded(t, 0xFFFD, wsap_vtcore_current_flags(t)); /* The byte that ended an unfinished sequence starts anew. */ - if (before != TERM_UTF8_ACCEPT) - term_text_ground(t, ch); + if (before != WSAP_VTCORE_UTF8_ACCEPT) + wsap_vtcore_text_ground(t, ch); } } } -static inline bool can_stream_bottom(const struct term *t) +static inline bool can_stream_bottom(const struct wsap_vtcore *t) { return t->state == ST_GROUND && !t->graphics && !t->insert_mode && t->autowrap && !t->lr_margin_mode && - t->utf8_state == TERM_UTF8_ACCEPT && !t->inverse && + t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT && !t->inverse && t->scroll_top == 0 && t->scroll_bottom == t->rows - 1 && t->cursor_y == t->rows - 1 && !t->alternate && t->sb_capacity > 0 && using_default_colors(t); } -static inline bool try_text_run(struct term *t, const char *buf, size_t len, +static inline bool try_text_run(struct wsap_vtcore *t, const char *buf, size_t len, size_t *idx) { size_t i = *idx; if (t->pending_wrap || i + 4 > len || ((unsigned char)buf[i] >= 0x80 && ((unsigned char)buf[i] < 0xc2 || (unsigned char)buf[i] > 0xf4)) || - t->last_char == 0x200D || term_grapheme_is_handle(t->last_char)) + t->last_char == 0x200D || wsap_vtcore_grapheme_is_handle(t->last_char)) return false; if (t->cursor_x != 0 && - t->cursor_x != term_row(t, t->cursor_y)->len) + t->cursor_x != wsap_vtcore_row(t, t->cursor_y)->len) return false; if ((unsigned char)buf[i] >= 0x80) { uint32_t cp; - int bytes = term_utf8_decode_one(buf + i, len - i, &cp); - if (!bytes || term_text_class(cp) <= 0) + int bytes = wsap_vtcore_utf8_decode_one(buf + i, len - i, &cp); + if (!bytes || wsap_vtcore_text_class(cp) <= 0) return false; } - struct text_pen pen = term_text_pen(t); + struct text_pen pen = wsap_vtcore_text_pen(t); bool wrote = false; do { struct srow *text = t->insert_mode || t->lr_margin_mode ? NULL : text_append_row(t); if (text) { int x = t->cursor_x, avail = t->cols - x; - struct text_run_bytes r = term_text_run_bytes(text->text.text + text->text.text_len, + struct text_run_bytes r = wsap_vtcore_text_run_bytes(text->text.text + text->text.text_len, buf + i, (int)(len - i), avail, t->last_char, &t->text_width); if (!r.bytes) @@ -156,7 +156,7 @@ static inline bool try_text_run(struct term *t, const char *buf, size_t len, struct span span = sc_span_begin(t, t->cols); if (span.avail < 2) break; - struct text_run_result r = term_text_run(span.cells, buf + i, (int)(len - i), + struct text_run_result r = wsap_vtcore_text_run(span.cells, buf + i, (int)(len - i), span.avail, pen.fg, pen.bg, pen.sl, t->last_char, &t->text_width); if (!r.bytes) @@ -175,45 +175,45 @@ static inline bool try_text_run(struct term *t, const char *buf, size_t len, newline = true; } } else if (i < len && buf[i] == '\n') { - if (term_lnm(t)) sc_cr(t); + if (wsap_vtcore_lnm(t)) sc_cr(t); sc_linefeed(t, 1); i++; newline = true; } if (!newline || i + 4 > len || t->pending_wrap || - t->last_char == 0x200D || term_grapheme_is_handle(t->last_char) || + t->last_char == 0x200D || wsap_vtcore_grapheme_is_handle(t->last_char) || (t->cursor_x != 0 && - t->cursor_x != term_row(t, t->cursor_y)->len)) + t->cursor_x != wsap_vtcore_row(t, t->cursor_y)->len)) break; } while (true); if (wrote) *idx = i - 1; return wrote; } -/* The feed flags this build knows. term_feed() rejects any other bit. */ -#define TERM_FEED_KNOWN TERM_FEED_ONLCR +/* The feed flags this build knows. wsap_vtcore_feed() rejects any other bit. */ +#define WSAP_VTCORE_FEED_KNOWN WSAP_VTCORE_FEED_ONLCR -static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigned flags) +static void wsap_vtcore_feed_inner(struct wsap_vtcore *t, const char *buf, size_t len, unsigned flags) { - t->transport_newline = (flags & TERM_FEED_ONLCR) != 0; - uint16_t cur_flags = term_current_flags(t); + t->transport_newline = (flags & WSAP_VTCORE_FEED_ONLCR) != 0; + uint16_t cur_flags = wsap_vtcore_current_flags(t); for (size_t i = 0; i < len; i++) { while (t->state != ST_GROUND) { if (t->state == ST_CSI) - i += term_escape_csi(t, buf + i, len - i); + i += wsap_vtcore_escape_csi(t, buf + i, len - i); else if (t->state == ST_OSC || t->state == ST_DCS || t->state == ST_IGNORE) - i += term_escape_str(t, buf + i, len - i); + i += wsap_vtcore_escape_str(t, buf + i, len - i); else - term_escape_byte(t, (unsigned char)buf[i++]); - cur_flags = term_current_flags(t); + wsap_vtcore_escape_byte(t, (unsigned char)buf[i++]); + cur_flags = wsap_vtcore_current_flags(t); if (i == len) return; } unsigned char ch = (unsigned char)buf[i]; - if (TERM_EXPECT(ch >= 0x20 && ch < 0x7f && !t->insert_mode && !t->lr_margin_mode && + if (WSAP_VTCORE_EXPECT(ch >= 0x20 && ch < 0x7f && !t->insert_mode && !t->lr_margin_mode && t->state == ST_GROUND && !t->graphics && - t->utf8_state == TERM_UTF8_ACCEPT, 1)) { + t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT, 1)) { int avail = t->pending_wrap ? t->cols : t->cols - t->cursor_x; int rem = (int)(len - i); if (rem > avail) rem = avail; @@ -221,14 +221,14 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne if (rem > 1 && (unsigned char)buf[i + 1] >= 0x20 && (unsigned char)buf[i + 1] < 0x7f) run += scan_ascii_run(buf + i + 1, rem - 1); - if (TERM_EXPECT(can_stream_bottom(t), 1) && + if (WSAP_VTCORE_EXPECT(can_stream_bottom(t), 1) && (run == t->cols || (i + (size_t)run < len && (buf[i + run] == '\r' || buf[i + run] == '\n')))) { - struct srow *row = term_row(t, t->cursor_y); + struct srow *row = wsap_vtcore_row(t, t->cursor_y); if (t->pending_wrap || (t->cursor_x == 0 && row && row->len == 0)) { - size_t done = term_sc_bulk_ascii_lines(t, buf + i, len - i); + size_t done = wsap_vtcore_sc_bulk_ascii_lines(t, buf + i, len - i); if (done > 0) { i += done - 1; continue; @@ -240,8 +240,8 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne (unsigned char)buf[i + 1] <= 0xf4 && (i + 2 == len || ((unsigned char)buf[i + 2] & 0xc0) == 0x80)) { uint32_t next_cp; - if (term_utf8_decode_one(buf + i + 1, len - i - 1, &next_cp) && - term_text_class(next_cp) > 0 && + if (wsap_vtcore_utf8_decode_one(buf + i + 1, len - i - 1, &next_cp) && + wsap_vtcore_text_class(next_cp) > 0 && try_text_run(t, buf, len, &i)) continue; } @@ -250,8 +250,8 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne } if (i + (size_t)run < len && (unsigned char)buf[i + run] >= 0x80) { uint32_t next_cp; - if (term_utf8_decode_one(buf + i + run, len - i - (size_t)run, &next_cp) && - term_text_class(next_cp) > 0 && + if (wsap_vtcore_utf8_decode_one(buf + i + run, len - i - (size_t)run, &next_cp) && + wsap_vtcore_text_class(next_cp) > 0 && try_text_run(t, buf, len, &i)) continue; } @@ -265,7 +265,7 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne i++; } } else if (i < len && buf[i] == '\n') { - if (term_lnm(t)) sc_cr(t); + if (wsap_vtcore_lnm(t)) sc_cr(t); sc_linefeed(t, 1); i++; } @@ -273,38 +273,38 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne continue; } - if (TERM_EXPECT(ch >= 0x80, 1)) { - if (TERM_EXPECT(t->state == ST_GROUND && - t->utf8_state == TERM_UTF8_ACCEPT && !t->graphics, 1)) { + if (WSAP_VTCORE_EXPECT(ch >= 0x80, 1)) { + if (WSAP_VTCORE_EXPECT(t->state == ST_GROUND && + t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT && !t->graphics, 1)) { if (ch >= 0xc2 && ch <= 0xf4 && (i + 1 == len || ((unsigned char)buf[i + 1] & 0xc0) == 0x80)) { if (!t->insert_mode && !t->lr_margin_mode && try_text_run(t, buf, len, &i)) continue; } else { - if (TERM_EXPECT(t->last_char != 0x200D && !term_grapheme_is_handle(t->last_char), 1)) + if (WSAP_VTCORE_EXPECT(t->last_char != 0x200D && !wsap_vtcore_grapheme_is_handle(t->last_char), 1)) sc_print_cell(t, 0xFFFD, 1, cur_flags); else emit_decoded(t, 0xFFFD, cur_flags); continue; } uint32_t cp; - int cp_len = term_utf8_decode_ground(&t->utf8_state, &t->utf8_codep, buf + i, len - i, &cp); + int cp_len = wsap_vtcore_utf8_decode_ground(&t->utf8_state, &t->utf8_codep, buf + i, len - i, &cp); if (cp) emit_decoded(t, cp, cur_flags); i += (size_t)(cp_len - 1); continue; } - if (TERM_EXPECT(t->state == ST_GROUND, 1)) - term_text_ground(t, ch); + if (WSAP_VTCORE_EXPECT(t->state == ST_GROUND, 1)) + wsap_vtcore_text_ground(t, ch); else - term_escape_byte(t, ch); + wsap_vtcore_escape_byte(t, ch); continue; } - if (TERM_EXPECT(ch < 0x20 || ch == 0x7f, 0)) { + if (WSAP_VTCORE_EXPECT(ch < 0x20 || ch == 0x7f, 0)) { if (t->state == ST_GROUND) { - term_text_utf8_interrupt(t); + wsap_vtcore_text_utf8_interrupt(t); if (ch == 0x7f || ((1u << ch) & 0x0800FF80u) == 0) continue; @@ -313,7 +313,7 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne case 0x0b: case 0x0c: { size_t end = i + 1 + scan_byte_run(buf + i + 1, len - i - 1, '\n'); - if (term_lnm(t)) sc_cr(t); + if (wsap_vtcore_lnm(t)) sc_cr(t); sc_linefeed(t, end - i); i = end - 1; continue; @@ -329,66 +329,66 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne } continue; case 0x1b: - if (t->utf8_state == TERM_UTF8_ACCEPT && i + 1 < len && + if (t->utf8_state == WSAP_VTCORE_UTF8_ACCEPT && i + 1 < len && buf[i + 1] == '[' && !t->insert_mode && !t->lr_margin_mode && !t->graphics) { - int fast = term_try_fast_csi(t, buf + i + 2, len - i - 2); + int fast = wsap_vtcore_try_fast_csi(t, buf + i + 2, len - i - 2); if (fast > 0) { - cur_flags = term_current_flags(t); + cur_flags = wsap_vtcore_current_flags(t); i += 1 + (size_t)fast; continue; } t->state = ST_CSI; csi_parser_reset(&t->csi_parser); - i += 1 + term_escape_csi(t, buf + i + 2, len - i - 2); - cur_flags = term_current_flags(t); + i += 1 + wsap_vtcore_escape_csi(t, buf + i + 2, len - i - 2); + cur_flags = wsap_vtcore_current_flags(t); continue; } - term_text_ground(t, ch); - cur_flags = term_current_flags(t); + wsap_vtcore_text_ground(t, ch); + cur_flags = wsap_vtcore_current_flags(t); continue; default: - term_text_ground(t, ch); - cur_flags = term_current_flags(t); + wsap_vtcore_text_ground(t, ch); + cur_flags = wsap_vtcore_current_flags(t); continue; } } else { - term_escape_byte(t, ch); - cur_flags = term_current_flags(t); + wsap_vtcore_escape_byte(t, ch); + cur_flags = wsap_vtcore_current_flags(t); continue; } } - if (TERM_EXPECT(t->state == ST_GROUND, 1)) - term_text_ground(t, ch); + if (WSAP_VTCORE_EXPECT(t->state == ST_GROUND, 1)) + wsap_vtcore_text_ground(t, ch); else - term_escape_byte(t, ch); - cur_flags = term_current_flags(t); + wsap_vtcore_escape_byte(t, ch); + cur_flags = wsap_vtcore_current_flags(t); } } -bool term_feed(struct term *t, const char *buf, size_t len, unsigned flags) +bool wsap_vtcore_feed(struct wsap_vtcore *t, const char *buf, size_t len, unsigned flags) { - if (!t || (!buf && len > 0) || (flags & ~TERM_FEED_KNOWN)) + if (!t || (!buf && len > 0) || (flags & ~WSAP_VTCORE_FEED_KNOWN)) return false; if (len == 0) return true; - term_write_begin(t); - term_feed_inner(t, buf, len, flags); - term_write_end(t); + wsap_vtcore_write_begin(t); + wsap_vtcore_feed_inner(t, buf, len, flags); + wsap_vtcore_write_end(t); return true; } -void term_text_repeat(struct term *t, int count) +void wsap_vtcore_text_repeat(struct wsap_vtcore *t, int count) { int screen = t->cols * t->rows; if (count > screen) count = screen; if (count <= 0 || !t->last_char) return; if (count == 1) { - term_sc_print_glyph(t, t->last_char, -1, term_current_flags(t)); + wsap_vtcore_sc_print_glyph(t, t->last_char, -1, wsap_vtcore_current_flags(t)); return; } for (int j = 0; j < count && t->last_char; j++) - term_sc_print_glyph(t, t->last_char, -1, term_current_flags(t)); + wsap_vtcore_sc_print_glyph(t, t->last_char, -1, wsap_vtcore_current_flags(t)); } @@ -1,10 +1,10 @@ -#ifndef TERM_TEXT_H -#define TERM_TEXT_H +#ifndef WSAP_VTCORE_TEXT_H +#define WSAP_VTCORE_TEXT_H #include "internal.h" -void term_text_ground(struct term *t, unsigned char ch); +void wsap_vtcore_text_ground(struct wsap_vtcore *t, unsigned char ch); /* End an unfinished UTF-8 sequence: it prints U+FFFD. */ -void term_text_utf8_interrupt(struct term *t); -void term_text_repeat(struct term *t, int count); +void wsap_vtcore_text_utf8_interrupt(struct wsap_vtcore *t); +void wsap_vtcore_text_repeat(struct wsap_vtcore *t, int count); #endif diff --git a/src/text_run.c b/src/text_run.c index c48b73e..872c8de 100644 --- a/src/text_run.c +++ b/src/text_run.c @@ -10,16 +10,16 @@ static uint8_t unicode_fast_class[65536]; static int8_t unicode_width_bmp[65536]; /* Runs of code points with one fast class, for the AVX-512 width cache. */ -#define TERM_WIDTH_RUNS_MAX 1024 -static uint16_t width_run_lo[TERM_WIDTH_RUNS_MAX]; -static uint16_t width_run_hi[TERM_WIDTH_RUNS_MAX]; -static uint8_t width_run_class[TERM_WIDTH_RUNS_MAX]; +#define WSAP_VTCORE_WIDTH_RUNS_MAX 1024 +static uint16_t width_run_lo[WSAP_VTCORE_WIDTH_RUNS_MAX]; +static uint16_t width_run_hi[WSAP_VTCORE_WIDTH_RUNS_MAX]; +static uint8_t width_run_class[WSAP_VTCORE_WIDTH_RUNS_MAX]; static int width_run_count; -void term_text_tables_init(void) +void wsap_vtcore_text_tables_init(void) { for (uint32_t cp = 0; cp < 65536; cp++) { - int w = term_unicode_width(cp); + int w = wsap_vtcore_unicode_width(cp); unicode_fast_class[cp] = (w == 1 || w == 2) && !cluster_contextual(cp) ? (uint8_t)w : 0; unicode_width_bmp[cp] = (int8_t)w; @@ -28,7 +28,7 @@ void term_text_tables_init(void) uint8_t k = unicode_fast_class[cp]; uint32_t lo = cp; while (cp < 65536 && unicode_fast_class[cp] == k) cp++; - if (width_run_count == TERM_WIDTH_RUNS_MAX) { + if (width_run_count == WSAP_VTCORE_WIDTH_RUNS_MAX) { width_run_count = 0; break; } @@ -39,7 +39,7 @@ void term_text_tables_init(void) } } -static TERM_MAYBE_UNUSED int width_run_find(uint32_t cp) +static WSAP_VTCORE_MAYBE_UNUSED int width_run_find(uint32_t cp) { int lo = 0, hi = width_run_count - 1; while (lo < hi) { @@ -50,24 +50,24 @@ static TERM_MAYBE_UNUSED int width_run_find(uint32_t cp) return width_run_count > 0 ? lo : -1; } -static TERM_MAYBE_UNUSED uint16_t width_cache_covers(const struct width_cache *wc, +static WSAP_VTCORE_MAYBE_UNUSED uint16_t width_cache_covers(const struct width_cache *wc, const uint32_t *cp) { uint16_t covered = 0; for (int l = 0; l < 16; l++) { bool hit = false; - for (int k = 0; k < TERM_WIDTH_SLOTS; k++) + for (int k = 0; k < WSAP_VTCORE_WIDTH_SLOTS; k++) hit |= cp[l] - wc->lo[k] <= wc->span[k]; covered |= (uint16_t)(hit << l); } return covered; } -static TERM_MAYBE_UNUSED bool width_cache_extend(struct width_cache *wc, const uint32_t *cp, +static WSAP_VTCORE_MAYBE_UNUSED bool width_cache_extend(struct width_cache *wc, const uint32_t *cp, uint16_t covered) { unsigned miss = (unsigned)~covered & 0xFFFFu; - int r = width_run_find(cp[miss ? term_ctz32(miss) : 0]); + int r = width_run_find(cp[miss ? wsap_vtcore_ctz32(miss) : 0]); if (r < 0) return false; uint8_t k = width_run_class[r]; if (k != 1 && k != 2) return false; @@ -77,25 +77,25 @@ static TERM_MAYBE_UNUSED bool width_cache_extend(struct width_cache *wc, const u wc->klass = k; wc->next = 0; } - for (int added = 0; added < TERM_WIDTH_SLOTS; added++) { + for (int added = 0; added < WSAP_VTCORE_WIDTH_SLOTS; added++) { wc->lo[wc->next] = width_run_lo[r]; wc->span[wc->next] = (uint32_t)(width_run_hi[r] - width_run_lo[r]); - wc->next = (uint8_t)((wc->next + 1) % TERM_WIDTH_SLOTS); + wc->next = (uint8_t)((wc->next + 1) % WSAP_VTCORE_WIDTH_SLOTS); covered = width_cache_covers(wc, cp); if (covered == 0xFFFF) return true; - r = width_run_find(cp[term_ctz32((unsigned)~covered & 0xFFFFu)]); + r = width_run_find(cp[wsap_vtcore_ctz32((unsigned)~covered & 0xFFFFu)]); if (r < 0 || width_run_class[r] != k) return false; } return false; } -int term_text_class(uint32_t cp) +int wsap_vtcore_text_class(uint32_t cp) { - assert(term_tables_ready()); - return TERM_EXPECT(cp < 65536, 1) ? (int)unicode_width_bmp[cp] : term_unicode_width(cp); + assert(wsap_vtcore_tables_ready()); + return WSAP_VTCORE_EXPECT(cp < 65536, 1) ? (int)unicode_width_bmp[cp] : wsap_vtcore_unicode_width(cp); } -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) static const uint8_t utf8_3byte_shuffle[64] = { 2, 1, 0, 48, 5, 4, 3, 48, 8, 7, 6, 48, 11, 10, 9, 48, @@ -122,7 +122,7 @@ static const uint8_t utf8_3byte_want[64] = { }; #define UTF8_3BYTE_SPAN 0x0000FFFFFFFFFFFFull -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline __m512i utf8_3byte_decode(__m512i packed) { __m512i b2 = _mm512_and_si512(packed, _mm512_set1_epi32(0x003F)); @@ -132,70 +132,70 @@ static inline __m512i utf8_3byte_decode(__m512i packed) } struct width_ranges { - __m512i lo[TERM_WIDTH_SLOTS]; - __m512i span[TERM_WIDTH_SLOTS]; + __m512i lo[WSAP_VTCORE_WIDTH_SLOTS]; + __m512i span[WSAP_VTCORE_WIDTH_SLOTS]; }; -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline struct width_ranges width_ranges_load(const struct width_cache *wc) { struct width_ranges r; - for (int k = 0; k < TERM_WIDTH_SLOTS; k++) { + for (int k = 0; k < WSAP_VTCORE_WIDTH_SLOTS; k++) { r.lo[k] = _mm512_set1_epi32((int)wc->lo[k]); r.span[k] = _mm512_set1_epi32((int)wc->span[k]); } return r; } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline __mmask16 width_ranges_cover(const struct width_ranges *r, __m512i cps) { __mmask16 covered = 0; - for (int k = 0; k < TERM_WIDTH_SLOTS; k++) + for (int k = 0; k < WSAP_VTCORE_WIDTH_SLOTS; k++) covered |= _mm512_cmple_epu32_mask(_mm512_sub_epi32(cps, r->lo[k]), r->span[k]); return covered; } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline void store_wide_cells(uint64_t * restrict dst, __m512i base, __m512i cps) { -#define TERM_WIDE_PAIR(k) _mm512_storeu_si512((void *)(dst + 8 * (k)), \ +#define WSAP_VTCORE_WIDE_PAIR(k) _mm512_storeu_si512((void *)(dst + 8 * (k)), \ _mm512_mask_permutexvar_epi32(base, 0x0101, \ _mm512_setr_epi32((k) * 2, 0, 0, 0, 0, 0, 0, 0, \ (k) * 2 + 1, 0, 0, 0, 0, 0, 0, 0), cps)) - TERM_WIDE_PAIR(0); TERM_WIDE_PAIR(1); TERM_WIDE_PAIR(2); TERM_WIDE_PAIR(3); - TERM_WIDE_PAIR(4); TERM_WIDE_PAIR(5); TERM_WIDE_PAIR(6); TERM_WIDE_PAIR(7); -#undef TERM_WIDE_PAIR + WSAP_VTCORE_WIDE_PAIR(0); WSAP_VTCORE_WIDE_PAIR(1); WSAP_VTCORE_WIDE_PAIR(2); WSAP_VTCORE_WIDE_PAIR(3); + WSAP_VTCORE_WIDE_PAIR(4); WSAP_VTCORE_WIDE_PAIR(5); WSAP_VTCORE_WIDE_PAIR(6); WSAP_VTCORE_WIDE_PAIR(7); +#undef WSAP_VTCORE_WIDE_PAIR } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline void store_narrow_cells(uint64_t * restrict dst, __m512i base, __m512i cps) { -#define TERM_NARROW_QUAD(k) _mm512_storeu_si512((void *)(dst + 8 * (k)), \ +#define WSAP_VTCORE_NARROW_QUAD(k) _mm512_storeu_si512((void *)(dst + 8 * (k)), \ _mm512_mask_permutexvar_epi32(base, 0x1111, \ _mm512_setr_epi32((k) * 4, 0, 0, 0, (k) * 4 + 1, 0, 0, 0, \ (k) * 4 + 2, 0, 0, 0, (k) * 4 + 3, 0, 0, 0), cps)) - TERM_NARROW_QUAD(0); TERM_NARROW_QUAD(1); TERM_NARROW_QUAD(2); TERM_NARROW_QUAD(3); -#undef TERM_NARROW_QUAD + WSAP_VTCORE_NARROW_QUAD(0); WSAP_VTCORE_NARROW_QUAD(1); WSAP_VTCORE_NARROW_QUAD(2); WSAP_VTCORE_NARROW_QUAD(3); +#undef WSAP_VTCORE_NARROW_QUAD } /* Both cell and history writers validate and classify the same UTF-8 block. */ -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline bool classify_3byte_block(__m512i in, struct width_ranges *ranges, struct width_cache *wc, __m512i *cps) { - if (TERM_EXPECT(_mm512_test_epi8_mask( + if (WSAP_VTCORE_EXPECT(_mm512_test_epi8_mask( _mm512_xor_si512(in, _mm512_loadu_si512(utf8_3byte_want)), _mm512_loadu_si512(utf8_3byte_bits)) & UTF8_3BYTE_SPAN, 0)) return false; *cps = utf8_3byte_decode(_mm512_permutexvar_epi8(_mm512_loadu_si512(utf8_3byte_shuffle), in)); - if (_mm512_cmplt_epu32_mask(*cps, _mm512_set1_epi32((int)TERM_UTF8_3BYTE_MIN)) || + if (_mm512_cmplt_epu32_mask(*cps, _mm512_set1_epi32((int)WSAP_VTCORE_UTF8_3BYTE_MIN)) || _mm512_cmple_epu32_mask( - _mm512_sub_epi32(*cps, _mm512_set1_epi32((int)TERM_UTF8_SURROGATE_LO)), - _mm512_set1_epi32((int)(TERM_UTF8_SURROGATE_HI - TERM_UTF8_SURROGATE_LO)))) + _mm512_sub_epi32(*cps, _mm512_set1_epi32((int)WSAP_VTCORE_UTF8_SURROGATE_LO)), + _mm512_set1_epi32((int)(WSAP_VTCORE_UTF8_SURROGATE_HI - WSAP_VTCORE_UTF8_SURROGATE_LO)))) return false; __mmask16 covered = width_ranges_cover(ranges, *cps); - if (TERM_EXPECT(covered != 0xFFFF || wc->klass == 0, 0)) { + if (WSAP_VTCORE_EXPECT(covered != 0xFFFF || wc->klass == 0, 0)) { uint32_t cp[16]; _mm512_storeu_si512(cp, *cps); if (!width_cache_extend(wc, cp, covered)) return false; @@ -204,8 +204,8 @@ static inline bool classify_3byte_block(__m512i in, struct width_ranges *ranges, return true; } -TERM_TARGET_AVX512 -static TERM_NOINLINE int +WSAP_VTCORE_TARGET_AVX512 +static WSAP_VTCORE_NOINLINE int decode_3byte_blocks(uint64_t * restrict dst, const char * restrict buf, int len, int cols_left, __m512i base_wide_pair, __m512i base_narrow_quad, struct width_cache * restrict wc, @@ -241,8 +241,8 @@ decode_3byte_blocks(uint64_t * restrict dst, const char * restrict buf, int len, /* decode_3byte_blocks() that writes the history format: a narrow block * copies its 48 bytes, a wide block puts 0xF5 before each character. */ -TERM_TARGET_AVX512 -static TERM_NOINLINE int +WSAP_VTCORE_TARGET_AVX512 +static WSAP_VTCORE_NOINLINE int text_3byte_blocks(uint8_t * restrict dst, const char * restrict buf, int len, int cols_left, struct width_cache * restrict wc, int * restrict out_cols, int * restrict out_bytes, bool * restrict wide, uint32_t * restrict last_cp) @@ -286,19 +286,19 @@ text_3byte_blocks(uint8_t * restrict dst, const char * restrict buf, int len, in } #endif -struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *restrict buf, int len, +struct text_run_bytes wsap_vtcore_text_run_bytes(uint8_t *restrict dst, const char *restrict buf, int len, int max_cols, uint32_t last, struct width_cache *restrict wc) { - if (TERM_EXPECT(last == 0x200D || term_grapheme_is_handle(last), 0)) + if (WSAP_VTCORE_EXPECT(last == 0x200D || wsap_vtcore_grapheme_is_handle(last), 0)) return (struct text_run_bytes){ .last = last, .narrow = true }; - /* Unlike term_text_run(), this fills up to the edge and up to the end of + /* Unlike wsap_vtcore_text_run(), this fills up to the edge and up to the end of * buf: the cells path writes those characters one by one with the same * result, and a text row should not settle for them. */ int i = 0, cx = 0, o = 0, chars = 0; bool wide = false, narrow = true; (void)wc; -#if defined(TERM_KERNEL_AVX512) - bool blocks = term_use_avx512(); +#if defined(WSAP_VTCORE_KERNEL_AVX512) + bool blocks = wsap_vtcore_use_avx512(); #endif while (i < len && cx < max_cols) { unsigned char c = (unsigned char)buf[i]; @@ -316,7 +316,7 @@ struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *res } if (c < 0x20) break; -#if defined(TERM_KERNEL_AVX512) +#if defined(WSAP_VTCORE_KERNEL_AVX512) if ((c & UTF8_LEAD3_MASK) == UTF8_LEAD3_TAG && len - i >= 48 && max_cols - cx >= 32 && ((unsigned char)buf[i + 21] & UTF8_LEAD3_MASK) == UTF8_LEAD3_TAG && blocks) { int cols, bytes; @@ -335,10 +335,10 @@ struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *res } #endif uint32_t cp; - int bytes = term_utf8_decode_one(buf + i, (size_t)(len - i), &cp); + int bytes = wsap_vtcore_utf8_decode_one(buf + i, (size_t)(len - i), &cp); if (!bytes) break; - int w = bytes < 4 ? unicode_fast_class[cp] : term_text_class(cp); + int w = bytes < 4 ? unicode_fast_class[cp] : wsap_vtcore_text_class(cp); if (w <= 0 || (bytes == 4 && can_extend_cluster(last, cp, w)) || cx + w > max_cols) break; if (w == 2) { @@ -356,8 +356,8 @@ struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *res return (struct text_run_bytes){ i, cx, o, chars, last, wide, narrow }; } -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 static inline __m512i wide_pair_base(uint32_t fg, uint32_t bg, uint32_t flags) { return _mm512_setr_epi32( @@ -367,7 +367,7 @@ static inline __m512i wide_pair_base(uint32_t fg, uint32_t bg, uint32_t flags) 0, fg, bg, (flags & ~CELL_WIDE) | CELL_TRAIL); } -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline int try_3byte_blocks(uint64_t * restrict dst, const char * restrict buf, int len, int cols_left, uint32_t fg, uint32_t bg, uint32_t flags, struct width_cache * restrict wc, @@ -384,7 +384,7 @@ static inline int try_3byte_blocks(uint64_t * restrict dst, const char * restric } /* Two wide cells side by side: cp and next_cp. */ -TERM_TARGET_AVX512 +WSAP_VTCORE_TARGET_AVX512 static inline void store_wide_pair(uint64_t *dst, uint32_t fg, uint32_t bg, uint32_t flags, uint32_t cp, uint32_t next_cp) { @@ -457,14 +457,14 @@ static inline uint64_t *store_cell_wide(uint64_t * restrict dst, return dst + 4; } -#if defined(TERM_KERNEL_AVX2) +#if defined(WSAP_VTCORE_KERNEL_AVX2) /* * Decode runs of 3-byte UTF-8 four code points at a time. A quad stops the * run when a byte is not a 3-byte sequence, a code point is overlong or a * surrogate, or a code point has no fast width class. The scalar loop then * handles that code point, so both paths store the same cells. */ -TERM_TARGET_AVX2 +WSAP_VTCORE_TARGET_AVX2 static inline int decode_3byte_quads(uint64_t **dst_io, const char *buf, int len, int cols_left, const struct cell_bases *b, int *out_cols, uint32_t *last) @@ -493,9 +493,9 @@ static inline int decode_3byte_quads(uint64_t **dst_io, const char *buf, int len _mm_and_si128(_mm_srli_epi32(packed, 2), _mm_set1_epi32(0x0FC0))), _mm_and_si128(_mm_srli_epi32(packed, 4), _mm_set1_epi32(0xF000))); __m128i bad = _mm_or_si128( - _mm_cmplt_epi32(cps, _mm_set1_epi32((int)TERM_UTF8_3BYTE_MIN)), + _mm_cmplt_epi32(cps, _mm_set1_epi32((int)WSAP_VTCORE_UTF8_3BYTE_MIN)), _mm_cmpeq_epi32(_mm_and_si128(cps, _mm_set1_epi32(0xF800)), - _mm_set1_epi32((int)TERM_UTF8_SURROGATE_LO))); + _mm_set1_epi32((int)WSAP_VTCORE_UTF8_SURROGATE_LO))); if (_mm_movemask_epi8(bad)) break; alignas(16) uint32_t cp[4]; @@ -523,14 +523,14 @@ static inline int decode_3byte_quads(uint64_t **dst_io, const char *buf, int len /* One body for every level. isa is a constant in each copy below, so each * copy keeps only its own kernels. */ -static inline TERM_ALWAYS_INLINE struct text_run_result +static inline WSAP_VTCORE_ALWAYS_INLINE struct text_run_result text_run_body(struct cell *restrict row, const char *restrict buf, int len, int max_cols, uint32_t fg, uint32_t bg, uint32_t flags, uint32_t last, struct width_cache *restrict wc, int isa) { int i = 0; int cx = 0; - if (TERM_EXPECT(last == 0x200D || term_grapheme_is_handle(last), 0)) + if (WSAP_VTCORE_EXPECT(last == 0x200D || wsap_vtcore_grapheme_is_handle(last), 0)) return (struct text_run_result){0, 0, last}; const struct cell_bases bases = cell_bases_make(fg, bg, flags); @@ -538,8 +538,8 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int (void)wc; (void)isa; -#if defined(TERM_KERNEL_AVX512) - if (isa == TERM_ISA_AVX512) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (isa == WSAP_VTCORE_ISA_AVX512) { int cols; i += try_3byte_blocks(dst, buf, len, max_cols, fg, bg, flags, wc, &cols, &last); cx += cols; @@ -563,8 +563,8 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int cx++; i++; } -#if defined(TERM_KERNEL_AVX512) - if (isa == TERM_ISA_AVX512 && ascii_at == 0) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (isa == WSAP_VTCORE_ISA_AVX512 && ascii_at == 0) { int cols; i += try_3byte_blocks(dst, buf + i, len - i, max_cols - cx, fg, bg, flags, wc, &cols, &last); @@ -579,9 +579,9 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int break; } -#if defined(TERM_KERNEL_AVX2) - if (isa == TERM_ISA_AVX2 && - TERM_EXPECT((c & UTF8_LEAD3_MASK) == UTF8_LEAD3_TAG && i + 16 <= len && +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (isa == WSAP_VTCORE_ISA_AVX2 && + WSAP_VTCORE_EXPECT((c & UTF8_LEAD3_MASK) == UTF8_LEAD3_TAG && i + 16 <= len && ((unsigned char)buf[i + 9] & UTF8_LEAD3_MASK) == UTF8_LEAD3_TAG, 0)) { int cols; int used = decode_3byte_quads(&dst, buf + i, len - i, max_cols - cx, @@ -593,14 +593,14 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int } #endif uint32_t cp; - int bytes = term_utf8_decode_one(buf + i, (size_t)(len - i), &cp); + int bytes = wsap_vtcore_utf8_decode_one(buf + i, (size_t)(len - i), &cp); if (!bytes) break; - int w = bytes < 4 ? unicode_fast_class[cp] : term_text_class(cp); + int w = bytes < 4 ? unicode_fast_class[cp] : wsap_vtcore_text_class(cp); if (w <= 0 || (bytes == 4 && can_extend_cluster(last, cp, w))) break; -#if defined(TERM_KERNEL_AVX512) - if (isa == TERM_ISA_AVX512 && bytes == 3 && w == 2 && i + 6 <= len && cx + 4 <= max_cols) { +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (isa == WSAP_VTCORE_ISA_AVX512 && bytes == 3 && w == 2 && i + 6 <= len && cx + 4 <= max_cols) { uint32_t next_cp; - if (term_utf8_decode_one(buf + i + 3, (size_t)(len - i - 3), &next_cp) == 3 && + if (wsap_vtcore_utf8_decode_one(buf + i + 3, (size_t)(len - i - 3), &next_cp) == 3 && unicode_fast_class[next_cp] == 2) { store_wide_pair(dst, fg, bg, flags, cp, next_cp); dst += 8; @@ -630,35 +630,35 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int struct width_cache *restrict wc #define TEXT_RUN_ARGS row, buf, len, max_cols, fg, bg, flags, last, wc -#if defined(TERM_KERNEL_AVX512) -TERM_TARGET_AVX512 -static TERM_NOINLINE struct text_run_result text_run_avx512(TEXT_RUN_PARAMS) +#if defined(WSAP_VTCORE_KERNEL_AVX512) +WSAP_VTCORE_TARGET_AVX512 +static WSAP_VTCORE_NOINLINE struct text_run_result text_run_avx512(TEXT_RUN_PARAMS) { - return text_run_body(TEXT_RUN_ARGS, TERM_ISA_AVX512); + return text_run_body(TEXT_RUN_ARGS, WSAP_VTCORE_ISA_AVX512); } #endif -#if defined(TERM_KERNEL_AVX2) -TERM_TARGET_AVX2 -static TERM_NOINLINE struct text_run_result text_run_avx2(TEXT_RUN_PARAMS) +#if defined(WSAP_VTCORE_KERNEL_AVX2) +WSAP_VTCORE_TARGET_AVX2 +static WSAP_VTCORE_NOINLINE struct text_run_result text_run_avx2(TEXT_RUN_PARAMS) { - return text_run_body(TEXT_RUN_ARGS, TERM_ISA_AVX2); + return text_run_body(TEXT_RUN_ARGS, WSAP_VTCORE_ISA_AVX2); } #endif -static TERM_NOINLINE struct text_run_result text_run_base(TEXT_RUN_PARAMS) +static WSAP_VTCORE_NOINLINE struct text_run_result text_run_base(TEXT_RUN_PARAMS) { - return text_run_body(TEXT_RUN_ARGS, TERM_ISA_BASE); + return text_run_body(TEXT_RUN_ARGS, WSAP_VTCORE_ISA_BASE); } -struct text_run_result term_text_run(TEXT_RUN_PARAMS) +struct text_run_result wsap_vtcore_text_run(TEXT_RUN_PARAMS) { -#if defined(TERM_KERNEL_AVX512) - if (term_use_avx512()) +#if defined(WSAP_VTCORE_KERNEL_AVX512) + if (wsap_vtcore_use_avx512()) return text_run_avx512(TEXT_RUN_ARGS); #endif -#if defined(TERM_KERNEL_AVX2) - if (term_use_avx2()) +#if defined(WSAP_VTCORE_KERNEL_AVX2) + if (wsap_vtcore_use_avx2()) return text_run_avx2(TEXT_RUN_ARGS); #endif return text_run_base(TEXT_RUN_ARGS); diff --git a/src/text_run.h b/src/text_run.h index 3ff432b..630c1c7 100644 --- a/src/text_run.h +++ b/src/text_run.h @@ -1,5 +1,5 @@ -#ifndef TERM_TEXT_RUN_H -#define TERM_TEXT_RUN_H +#ifndef WSAP_VTCORE_TEXT_RUN_H +#define WSAP_VTCORE_TEXT_RUN_H #include "cell.h" #include "unicode/unicode.h" @@ -10,19 +10,19 @@ #define UTF8_LEAD3_TAG 0xE0 #define UTF8_LEAD3_MASK 0xF0 -#define TERM_WIDTH_SLOTS 4 +#define WSAP_VTCORE_WIDTH_SLOTS 4 struct width_cache { - uint32_t lo[TERM_WIDTH_SLOTS]; - uint32_t span[TERM_WIDTH_SLOTS]; + uint32_t lo[WSAP_VTCORE_WIDTH_SLOTS]; + uint32_t span[WSAP_VTCORE_WIDTH_SLOTS]; uint8_t klass; uint8_t next; }; -/* term_new() builds the shared tables before any terminal can use them. */ -bool term_tables_ready(void); -void term_text_tables_init(void); +/* wsap_vtcore_new() builds the shared tables before any terminal can use them. */ +bool wsap_vtcore_tables_ready(void); +void wsap_vtcore_text_tables_init(void); -int term_text_class(uint32_t cp); +int wsap_vtcore_text_class(uint32_t cp); struct text_run_result { int bytes; @@ -30,7 +30,7 @@ struct text_run_result { uint32_t last; }; -struct text_run_result term_text_run(struct cell *restrict row, const char *restrict buf, +struct text_run_result wsap_vtcore_text_run(struct cell *restrict row, const char *restrict buf, int len, int max_cols, uint32_t fg, uint32_t bg, uint32_t flags, uint32_t last, struct width_cache *restrict wc); @@ -43,35 +43,35 @@ struct text_run_bytes { bool wide, narrow; /* narrow: every character was one ASCII byte */ }; -/* term_text_run() with the same rules, that writes the text in the history +/* wsap_vtcore_text_run() with the same rules, that writes the text in the history * format instead of cells: raw UTF-8, a wide character after 0xF5. dst has * room for 4 bytes per column. */ -struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *restrict buf, int len, +struct text_run_bytes wsap_vtcore_text_run_bytes(uint8_t *restrict dst, const char *restrict buf, int len, int max_cols, uint32_t last, struct width_cache *restrict wc); static inline bool joins_cluster(uint32_t cp, int klass) { if (cp < 0x0300) return false; - if (klass == 0 || term_grapheme_emoji_modifier(cp)) + if (klass == 0 || wsap_vtcore_grapheme_emoji_modifier(cp)) return true; - return klass == 1 && term_unicode_spacing_mark(cp); + return klass == 1 && wsap_vtcore_unicode_spacing_mark(cp); } static inline bool can_extend_cluster(uint32_t last_char, uint32_t cp, int klass) { if (klass == 0) return true; - if (last_char == 0x200D || term_grapheme_is_handle(last_char)) return true; - if (cp - 0x1F1E6u <= 0x19u && term_grapheme_regional_indicator(cp)) + if (last_char == 0x200D || wsap_vtcore_grapheme_is_handle(last_char)) return true; + if (cp - 0x1F1E6u <= 0x19u && wsap_vtcore_grapheme_regional_indicator(cp)) return true; return joins_cluster(cp, klass); } static inline bool cluster_contextual(uint32_t cp) { - return term_unicode_spacing_mark(cp) || term_grapheme_emoji_modifier(cp) || - (cp - 0x1F1E6u <= 0x19u && term_grapheme_regional_indicator(cp)); + return wsap_vtcore_unicode_spacing_mark(cp) || wsap_vtcore_grapheme_emoji_modifier(cp) || + (cp - 0x1F1E6u <= 0x19u && wsap_vtcore_grapheme_regional_indicator(cp)); } static inline bool cluster_joins(const uint32_t *cps, int len, @@ -80,10 +80,10 @@ static inline bool cluster_joins(const uint32_t *cps, int len, if (joins_cluster(cp, klass)) return true; if (cps[len - 1] == 0x200D) - return term_unicode_extended_pictographic(cp); + return wsap_vtcore_unicode_extended_pictographic(cp); return len == 1 && cp - 0x1F1E6u <= 0x19u && - term_grapheme_regional_indicator(cp) && - term_grapheme_regional_indicator(cps[0]); + wsap_vtcore_grapheme_regional_indicator(cp) && + wsap_vtcore_grapheme_regional_indicator(cps[0]); } #endif diff --git a/tests/api_args_test.c b/tests/api_args_test.c index 6c7dfc7..309ee6e 100644 --- a/tests/api_args_test.c +++ b/tests/api_args_test.c @@ -4,7 +4,7 @@ #include <string.h> /* A feed that returns false must not move the cursor or change a cell. */ -static void expect_unchanged(struct term *t, int x, int y, uint32_t cp) +static void expect_unchanged(struct wsap_vtcore *t, int x, int y, uint32_t cp) { assert(tt_cursor_x(t) == x); assert(tt_cursor_y(t) == y); @@ -13,117 +13,117 @@ static void expect_unchanged(struct term *t, int x, int y, uint32_t cp) static void test_feed_unknown_flag(void) { - struct term *t = tt_new(10, 3); + struct wsap_vtcore *t = tt_new(10, 3); assert(t); - assert(term_feed(t, "abc", 3, 0)); + assert(wsap_vtcore_feed(t, "abc", 3, 0)); expect_unchanged(t, 3, 0, 'a'); - assert(!term_feed(t, "xy", 2, 1u << 1)); + assert(!wsap_vtcore_feed(t, "xy", 2, 1u << 1)); expect_unchanged(t, 3, 0, 'a'); - assert(!term_feed(t, "xy", 2, TERM_FEED_ONLCR | (1u << 4))); + assert(!wsap_vtcore_feed(t, "xy", 2, WSAP_VTCORE_FEED_ONLCR | (1u << 4))); expect_unchanged(t, 3, 0, 'a'); - assert(!term_feed(t, "xy", 2, 1u << 31)); + assert(!wsap_vtcore_feed(t, "xy", 2, 1u << 31)); expect_unchanged(t, 3, 0, 'a'); /* Unknown bits are rejected even when there are no bytes. */ - assert(!term_feed(t, "", 0, 1u << 1)); + assert(!wsap_vtcore_feed(t, "", 0, 1u << 1)); - assert(term_feed(t, "\nz", 2, TERM_FEED_ONLCR)); + assert(wsap_vtcore_feed(t, "\nz", 2, WSAP_VTCORE_FEED_ONLCR)); assert(tt_cursor_x(t) == 1); assert(tt_cursor_y(t) == 1); - term_free(t); + wsap_vtcore_free(t); } static void test_feed_null_buffer(void) { - struct term *t = tt_new(10, 3); + struct wsap_vtcore *t = tt_new(10, 3); assert(t); - assert(term_feed(t, "abc", 3, 0)); + assert(wsap_vtcore_feed(t, "abc", 3, 0)); - assert(!term_feed(t, NULL, 1, 0)); + assert(!wsap_vtcore_feed(t, NULL, 1, 0)); expect_unchanged(t, 3, 0, 'a'); - assert(!term_feed(t, NULL, 4096, TERM_FEED_ONLCR)); + assert(!wsap_vtcore_feed(t, NULL, 4096, WSAP_VTCORE_FEED_ONLCR)); expect_unchanged(t, 3, 0, 'a'); /* A zero length is a no-op, so a NULL buffer is fine. */ - assert(term_feed(t, NULL, 0, 0)); - assert(term_feed(t, "", 0, TERM_FEED_ONLCR)); + assert(wsap_vtcore_feed(t, NULL, 0, 0)); + assert(wsap_vtcore_feed(t, "", 0, WSAP_VTCORE_FEED_ONLCR)); expect_unchanged(t, 3, 0, 'a'); - assert(!term_feed(NULL, "a", 1, 0)); - assert(!term_feed(NULL, NULL, 0, 0)); - term_free(t); + assert(!wsap_vtcore_feed(NULL, "a", 1, 0)); + assert(!wsap_vtcore_feed(NULL, NULL, 0, 0)); + wsap_vtcore_free(t); } static void test_new_rejects_bad_options(void) { - struct term_options opt; + struct wsap_vtcore_options opt; memset(&opt, 0, sizeof(opt)); opt.size.x = -1; - assert(!term_new(&opt)); + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); opt.size.y = -1; - assert(!term_new(&opt)); + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); - opt.size.x = TERM_MAX_COLS + 1; - assert(!term_new(&opt)); + opt.size.x = WSAP_VTCORE_MAX_COLS + 1; + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); opt.scrollback = -1; - assert(!term_new(&opt)); + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); - opt.scrollback = TERM_SCROLLBACK_MAX + 1; - assert(!term_new(&opt)); + opt.scrollback = WSAP_VTCORE_SCROLLBACK_MAX + 1; + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); - opt.scrollback = TERM_SCROLLBACK_MAX; - struct term *max = term_new(&opt); + opt.scrollback = WSAP_VTCORE_SCROLLBACK_MAX; + struct wsap_vtcore *max = wsap_vtcore_new(&opt); assert(max); - term_free(max); + wsap_vtcore_free(max); memset(&opt, 0, sizeof(opt)); - opt.cursor_style = (enum term_cursor_style)3; - assert(!term_new(&opt)); + opt.cursor_style = (enum wsap_vtcore_cursor_style)3; + assert(!wsap_vtcore_new(&opt)); memset(&opt, 0, sizeof(opt)); - opt.cursor_style = (enum term_cursor_style)-1; - assert(!term_new(&opt)); + opt.cursor_style = (enum wsap_vtcore_cursor_style)-1; + assert(!wsap_vtcore_new(&opt)); } static void test_new_accepts_defaults(void) { - struct term_options opt; + struct wsap_vtcore_options opt; memset(&opt, 0, sizeof(opt)); - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); assert(tt_cols(t) == 80); assert(tt_rows(t) == 24); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK); - term_free(t); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK); + wsap_vtcore_free(t); memset(&opt, 0, sizeof(opt)); - opt.size.x = TERM_MAX_COLS; + opt.size.x = WSAP_VTCORE_MAX_COLS; opt.size.y = 1; - opt.cursor_style = TERM_CURSOR_BAR; - t = term_new(&opt); + opt.cursor_style = WSAP_VTCORE_CURSOR_BAR; + t = wsap_vtcore_new(&opt); assert(t); - assert(tt_cols(t) == TERM_MAX_COLS); + assert(tt_cols(t) == WSAP_VTCORE_MAX_COLS); assert(tt_rows(t) == 1); - assert(term_cursor(t).style == TERM_CURSOR_BAR); - term_free(t); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR); + wsap_vtcore_free(t); } static void test_resize_rejects_too_wide(void) { - struct term *t = tt_new(10, 3); + struct wsap_vtcore *t = tt_new(10, 3); assert(t); - assert(term_feed(t, "abc", 3, 0)); + assert(wsap_vtcore_feed(t, "abc", 3, 0)); - assert(!tt_resize(t, TERM_MAX_COLS + 1, 3)); + assert(!tt_resize(t, WSAP_VTCORE_MAX_COLS + 1, 3)); assert(tt_cols(t) == 10); assert(tt_rows(t) == 3); expect_unchanged(t, 3, 0, 'a'); @@ -133,10 +133,10 @@ static void test_resize_rejects_too_wide(void) assert(tt_cols(t) == 10); assert(tt_rows(t) == 3); - assert(tt_resize(t, TERM_MAX_COLS, 3)); - assert(tt_cols(t) == TERM_MAX_COLS); + assert(tt_resize(t, WSAP_VTCORE_MAX_COLS, 3)); + assert(tt_cols(t) == WSAP_VTCORE_MAX_COLS); assert(tt_rows(t) == 3); - term_free(t); + wsap_vtcore_free(t); } int main(void) diff --git a/tests/correctness_probe.c b/tests/correctness_probe.c index 9ac74ca..47548a3 100644 --- a/tests/correctness_probe.c +++ b/tests/correctness_probe.c @@ -27,60 +27,60 @@ void *__wrap_realloc(void *ptr, size_t size) int main(void) { bool failed = false; - struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); - assert(t && s && term_snapshot_update(s, t)); + struct wsap_vtcore_options options = { .size = { 8, 3 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); + assert(t && s && wsap_vtcore_snapshot_update(s, t)); const char accented[] = "e\xcc\x81"; - term_feed(t, accented, sizeof(accented) - 1, 0); + wsap_vtcore_feed(t, accented, sizeof(accented) - 1, 0); fail_realloc = 1; - bool ok = term_snapshot_update(s, t); + bool ok = wsap_vtcore_snapshot_update(s, t); uint32_t cps[16]; printf("snapshot arena allocation failure: update=%d size=%dx%d (expected false and the previous 8x3 view)\n", - ok, term_snapshot_view(s)->size.x, term_snapshot_view(s)->size.y); - failed |= ok || term_snapshot_view(s)->size.x != 8 || term_snapshot_view(s)->size.y != 3; - assert(term_snapshot_update(s, t)); - int n = term_snapshot_cluster(s, term_snapshot_row(s, 0)[0].text, cps, 16); + ok, wsap_vtcore_snapshot_view(s)->size.x, wsap_vtcore_snapshot_view(s)->size.y); + failed |= ok || wsap_vtcore_snapshot_view(s)->size.x != 8 || wsap_vtcore_snapshot_view(s)->size.y != 3; + assert(wsap_vtcore_snapshot_update(s, t)); + int n = wsap_vtcore_snapshot_cluster(s, wsap_vtcore_snapshot_row(s, 0)[0].text, cps, 16); printf("retry after allocation recovers: cluster_length=%d (expected 2)\n", n); failed |= n != 2 || cps[0] != 'e' || cps[1] != 0x301; - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); options.size.y = 24; - t = term_new(&options); - s = term_snapshot_new(); + t = wsap_vtcore_new(&options); + s = wsap_vtcore_snapshot_new(); assert(t && s); const char line[] = "e\xcc\x81\r\n"; for (int i = 1; i <= 10000; i++) { - term_feed(t, line, sizeof(line) - 1, 0); - assert(term_snapshot_update(s, t)); + wsap_vtcore_feed(t, line, sizeof(line) - 1, 0); + assert(wsap_vtcore_snapshot_update(s, t)); if (i == 1000 || i == 10000) printf("after %d lines: arena_words=%u dead_words=%u history_rows=%d\n", - i, s->arena_len, s->arena_dead, term_history_rows(t)); + i, s->arena_len, s->arena_dead, wsap_vtcore_history_rows(t)); } - failed |= s->arena_len >= 8192 || term_history_rows(t) != 5; - term_snapshot_free(s); - term_free(t); + failed |= s->arena_len >= 8192 || wsap_vtcore_history_rows(t) != 5; + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); - options.size = (struct term_vector2i){ 8, 4 }; - t = term_new(&options); - s = term_snapshot_new(); + options.size = (struct wsap_vtcore_vector2i){ 8, 4 }; + t = wsap_vtcore_new(&options); + s = wsap_vtcore_snapshot_new(); assert(t && s); const char rows[] = "A\r\nB\r\nC\r\nD"; - term_feed(t, rows, sizeof(rows) - 1, 0); - assert(term_snapshot_update(s, t)); + wsap_vtcore_feed(t, rows, sizeof(rows) - 1, 0); + assert(wsap_vtcore_snapshot_update(s, t)); printf("before failed height shrink: top=%c cursor_y=%d history=%d\n", - (char)term_snapshot_row(s, 0)[0].text, term_cursor(t).pos.y, term_history_rows(t)); + (char)wsap_vtcore_snapshot_row(s, 0)[0].text, wsap_vtcore_cursor(t).pos.y, wsap_vtcore_history_rows(t)); fail_resize_calloc = 1; - ok = term_resize(t, (struct term_vector2i){ 8, 2 }); + ok = wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ 8, 2 }); assert(!fail_resize_calloc); - assert(term_snapshot_update(s, t)); + assert(wsap_vtcore_snapshot_update(s, t)); printf("after failed height shrink: resize=%d height=%d top=%c cursor_y=%d history=%d\n", - ok, term_size(t).y, (char)term_snapshot_row(s, 0)[0].text, - term_cursor(t).pos.y, term_history_rows(t)); - failed |= ok || term_size(t).y != 4 || term_snapshot_row(s, 0)[0].text != 'A' || - term_cursor(t).pos.y != 3 || term_history_rows(t) != 0; - term_snapshot_free(s); - term_free(t); + ok, wsap_vtcore_size(t).y, (char)wsap_vtcore_snapshot_row(s, 0)[0].text, + wsap_vtcore_cursor(t).pos.y, wsap_vtcore_history_rows(t)); + failed |= ok || wsap_vtcore_size(t).y != 4 || wsap_vtcore_snapshot_row(s, 0)[0].text != 'A' || + wsap_vtcore_cursor(t).pos.y != 3 || wsap_vtcore_history_rows(t) != 0; + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return failed ? 1 : 0; } diff --git a/tests/cross_test.sh b/tests/cross_test.sh index 6c0efa2..bc46a8e 100644 --- a/tests/cross_test.sh +++ b/tests/cross_test.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# The term core compiles as strict C11 for the platforms a host may embed +# The core compiles as strict C11 for the platforms a host may embed # it on. zig cc supplies the cross compilers. The aarch64 targets build the # NEON paths, and windows-gnu builds the Windows path of compat.h. The -# amalgamation, one term.c, compiles the same way. +# amalgamation, one wsap_vtcore.c, compiles the same way. set -euo pipefail root=${1:-$(dirname "$0")/..} cd "$root/src" @@ -15,10 +15,10 @@ status=0 for target in aarch64-linux-gnu x86_64-macos aarch64-macos x86_64-windows-gnu; do for src in *.c osc/*.c; do zig cc -target "$target" -std=c11 -O2 -Wall -Wextra -Wpedantic -Werror \ - -I. -I../include/term -c "$src" -o "$out/obj.o" || { echo "$target: $src fails" >&2; status=1; } + -I. -I../include/wsap_vtcore -c "$src" -o "$out/obj.o" || { echo "$target: $src fails" >&2; status=1; } done zig cc -target "$target" -std=c11 -O2 -Wall -Wextra -Wpedantic -Werror \ - -c "$out/amalgamation/term.c" -o "$out/obj.o" || + -c "$out/amalgamation/wsap_vtcore.c" -o "$out/obj.o" || { echo "$target: the amalgamation fails" >&2; status=1; } done exit $status diff --git a/tests/dcs_test.c b/tests/dcs_test.c index d9455be..c76b73b 100644 --- a/tests/dcs_test.c +++ b/tests/dcs_test.c @@ -14,11 +14,11 @@ static void respond(void *ud, const char *data, size_t len) response[len] = 0; response_len = len; } -static void write_seq(struct term *t, const char *s) +static void write_seq(struct wsap_vtcore *t, const char *s) { for (; *s; s++) tt_write(t, s, 1); } -static const char *row_text(struct term *t, int r, char *buf) +static const char *row_text(struct wsap_vtcore *t, int r, char *buf) { int n = 0; for (int c = 0; c < tt_cols(t); c++) @@ -27,18 +27,18 @@ static const char *row_text(struct term *t, int r, char *buf) buf[n] = 0; return buf; } -static bool row_is(struct term *t, int r, const char *want) +static bool row_is(struct wsap_vtcore *t, int r, const char *want) { - char got[TERM_MAX_COLS + 1]; + char got[WSAP_VTCORE_MAX_COLS + 1]; if (strcmp(row_text(t, r, got), want)) { fprintf(stderr, "row %d: got \"%s\" want \"%s\"\n", r, got, want); return false; } return true; } -static struct term *new_term(int cols, int rows) +static struct wsap_vtcore *new_term(int cols, int rows) { - struct term *t = tt_new_opts(cols, rows, &(struct term_callbacks){ .reply = respond }); + struct wsap_vtcore *t = tt_new_opts(cols, rows, &(struct wsap_vtcore_callbacks){ .reply = respond }); assert(t); response_len = 0; response[0] = 0; @@ -66,7 +66,7 @@ static void hex_encode(char *out, const char *s) *out = 0; } -static void assert_rqss(struct term *t, const char *spec, const char *payload) +static void assert_rqss(struct wsap_vtcore *t, const char *spec, const char *payload) { char req[128], want[256]; snprintf(req, sizeof(req), "\033P$q%s\033\\", spec); @@ -75,7 +75,7 @@ static void assert_rqss(struct term *t, const char *spec, const char *payload) write_seq(t, req); expect_response(want); } -static void assert_rqss_invalid(struct term *t, const char *spec) +static void assert_rqss_invalid(struct wsap_vtcore *t, const char *spec) { char req[128]; snprintf(req, sizeof(req), "\033P$q%s\033\\", spec); @@ -86,55 +86,55 @@ static void assert_rqss_invalid(struct term *t, const char *spec) static void test_decrqss_sgr(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); assert_rqss(t, "m", "m"); write_seq(t, "\033[1;31m"); assert_rqss(t, "m", "0;1;31m"); - term_free(t); + wsap_vtcore_free(t); t = new_term(80, 24); write_seq(t, "\033[4:3m"); assert_rqss(t, "m", "0;4:3m"); - term_free(t); + wsap_vtcore_free(t); t = new_term(80, 24); write_seq(t, "\033[38;2;10;20;30m"); assert_rqss(t, "m", "0;38:2:10:20:30m"); - term_free(t); + wsap_vtcore_free(t); } static void test_decrqss_margins_and_page(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); assert_rqss(t, "r", "1;24r"); assert_rqss(t, "t", "24t"); assert_rqss(t, "$|", "80$|"); assert_rqss(t, "*|", "24*|"); write_seq(t, "\033[3;10r"); assert_rqss(t, "r", "3;10r"); - term_free(t); + wsap_vtcore_free(t); t = new_term(80, 24); assert_rqss(t, "s", "1;80s"); write_seq(t, "\033[?69h\033[5;20s"); assert_rqss(t, "s", "5;20s"); - term_free(t); + wsap_vtcore_free(t); } static void test_decrqss_cursor_style(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); assert_rqss(t, " q", "1 q"); write_seq(t, "\033[5 q"); assert_rqss(t, " q", "5 q"); write_seq(t, "\033[4 q"); assert_rqss(t, " q", "4 q"); - term_free(t); + wsap_vtcore_free(t); } static void test_decrqss_misc(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); assert_rqss(t, "\"p", "64;1\"p"); assert_rqss(t, "\"q", "0\"q"); assert_rqss(t, "$}", "0$}"); @@ -142,12 +142,12 @@ static void test_decrqss_misc(void) assert_rqss(t, "*x", "0*x"); write_seq(t, "\033[2*x"); assert_rqss(t, "*x", "2*x"); - term_free(t); + wsap_vtcore_free(t); } static void test_decrqss_invalid(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); static const char *bad[] = { "){", ",|", ",}", ">0f", ">0m", ">0t", "z", "ABC", }; @@ -157,10 +157,10 @@ static void test_decrqss_invalid(void) response_len = 0; write_seq(t, "\033P$x\033\\"); expect_no_response(); - term_free(t); + wsap_vtcore_free(t); } -static void assert_tcap(struct term *t, const char *name, const char *value) +static void assert_tcap(struct wsap_vtcore *t, const char *name, const char *value) { char hn[128], hv[512], req[256], want[1024]; hex_encode(hn, name); @@ -174,10 +174,10 @@ static void assert_tcap(struct term *t, const char *name, const char *value) static void test_xtgettcap(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); assert_tcap(t, "kind", "\033[1;2B"); - assert_tcap(t, "TN", "term"); - assert_tcap(t, "name", "term"); + assert_tcap(t, "TN", "wsap_vtcore"); + assert_tcap(t, "name", "wsap_vtcore"); assert_tcap(t, "Co", "16777216"); assert_tcap(t, "colors", "16777216"); assert_tcap(t, "RGB", "8/8/8"); @@ -216,12 +216,12 @@ static void test_xtgettcap(void) assert_tcap(t, "kri", "\033[1;2A"); assert_tcap(t, "kxIN", "\033[I"); assert_tcap(t, "kxOUT", "\033[O"); - term_free(t); + wsap_vtcore_free(t); } static void test_xtgettcap_multi(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); char hk[16], htn[16], hb[16], hv[32], req[256], want[1024]; hex_encode(hk, "kind"); hex_encode(htn, "TN"); @@ -230,7 +230,7 @@ static void test_xtgettcap_multi(void) snprintf(req, sizeof(req), "\033P+q%s;%s\033\\", hk, htn); snprintf(want, sizeof(want), "\033P1+r%s=%s;%s=%s\033\\", - hk, hv, htn, "7465726d"); + hk, hv, htn, "777361705f7674636f7265"); response_len = 0; write_seq(t, req); expect_response(want); @@ -247,12 +247,12 @@ static void test_xtgettcap_multi(void) response_len = 0; write_seq(t, req); expect_response(want); - term_free(t); + wsap_vtcore_free(t); } static void test_xtgettcap_malformed(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); static const char *bad[] = {"6b696", "zz", "6g", "6b69 6e"}; for (size_t i = 0; i < sizeof(bad) / sizeof(bad[0]); i++) { char req[128]; @@ -264,12 +264,12 @@ static void test_xtgettcap_malformed(void) assert(response[response_len - 2] == '\033'); assert(response[response_len - 1] == '\\'); } - term_free(t); + wsap_vtcore_free(t); } static void test_xtsettcap(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); char hn[32]; hex_encode(hn, "myterm"); char req[128]; @@ -278,12 +278,12 @@ static void test_xtsettcap(void) write_seq(t, req); expect_no_response(); assert_tcap(t, "TN", "myterm"); - term_free(t); + wsap_vtcore_free(t); } static void test_xtgetxres(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); char hn[64], req[128], want[256]; hex_encode(hn, "allowTcapOps"); snprintf(req, sizeof(req), "\033P+Q%s\033\\", hn); @@ -291,40 +291,40 @@ static void test_xtgetxres(void) response_len = 0; write_seq(t, req); expect_response(want); - term_free(t); + wsap_vtcore_free(t); } static void test_decrsps_cir(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); write_seq(t, "\033P1$t3;5;1;I;@;H;00;@;BBBB\033\\"); assert(tt_cursor_y(t) == 2 && tt_cursor_x(t) == 4); write_seq(t, "Z"); - const struct term_cell *cell = tt_cell(t, 4, 2); + const struct wsap_vtcore_cell *cell = tt_cell(t, 4, 2); assert(cell->text == 'Z'); - assert(cell->attrs & TERM_ATTR_BOLD); - assert(cell->fg == TERM_COLOR_BG); - term_free(t); + assert(cell->attrs & WSAP_VTCORE_ATTR_BOLD); + assert(cell->fg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); t = new_term(80, 24); write_seq(t, "\033P1$t3;5;1;@;@;H;00;@;BBBB\033\\"); write_seq(t, "\033[1;80Hab"); assert(tt_cell(t, 79, 0)->text == 'a'); assert(tt_cell(t, 0, 1)->text == 'b'); - term_free(t); + wsap_vtcore_free(t); t = new_term(80, 24); write_seq(t, "\033[5;15r"); write_seq(t, "\033P1$t3;5;1;@;@;I;00;@;BBBB\033\\"); write_seq(t, "\033[1;1H"); assert(tt_cursor_y(t) == 4 && tt_cursor_x(t) == 0); - term_free(t); + wsap_vtcore_free(t); } static void test_decrsps_tabsr(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); write_seq(t, "\033P2$t4/10\033\\"); write_seq(t, "\033[1;1H"); write_seq(t, "\t"); @@ -333,26 +333,26 @@ static void test_decrsps_tabsr(void) assert(tt_cursor_x(t) == 9); write_seq(t, "\t"); assert(tt_cursor_x(t) == 79); - term_free(t); + wsap_vtcore_free(t); } static void test_synchronized_output(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); write_seq(t, "\033P=1s\033\\"); - assert(term_modes(t).synchronized); + assert(wsap_vtcore_modes(t).synchronized); write_seq(t, "\033P=2s\033\\"); - assert(!term_modes(t).synchronized); + assert(!wsap_vtcore_modes(t).synchronized); write_seq(t, "\033P=10s\033\\"); - assert(!term_modes(t).synchronized); + assert(!wsap_vtcore_modes(t).synchronized); write_seq(t, "\033P=1;s\033\\"); - assert(term_modes(t).synchronized); + assert(wsap_vtcore_modes(t).synchronized); write_seq(t, "\033P=xs\033\\"); - assert(term_modes(t).synchronized); + assert(wsap_vtcore_modes(t).synchronized); write_seq(t, "\033P=2;s\033\\"); - assert(!term_modes(t).synchronized); - term_free(t); + assert(!wsap_vtcore_modes(t).synchronized); + wsap_vtcore_free(t); } static void test_ignored_dcs(void) @@ -367,36 +367,36 @@ static void test_ignored_dcs(void) "\033P?~junk\033\\", }; for (size_t i = 0; i < sizeof(seqs) / sizeof(seqs[0]); i++) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); write_seq(t, "A"); write_seq(t, seqs[i]); write_seq(t, "B"); assert(row_is(t, 0, "AB")); assert(tt_cursor_x(t) == 2 && tt_cursor_y(t) == 0); expect_no_response(); - term_free(t); + wsap_vtcore_free(t); } } static void test_xtversion(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); response_len = 0; write_seq(t, "\033[>0q"); - expect_response("\033P>|term\033\\"); - term_free(t); + expect_response("\033P>|wsap_vtcore\033\\"); + wsap_vtcore_free(t); } -/* term_options.name feeds XTVERSION and the TN and name capabilities. */ +/* wsap_vtcore_options.name feeds XTVERSION and the TN and name capabilities. */ static void test_host_name(void) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = 80, .y = 24 }, .scrollback = TEST_SCROLLBACK, .name = "myterm", .callbacks = { .reply = respond }, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); response_len = 0; write_seq(t, "\033[>0q"); @@ -412,28 +412,28 @@ static void test_host_name(void) response_len = 0; write_seq(t, "\033[>0q"); expect_response("\033P>|myterm\033\\"); - term_free(t); + wsap_vtcore_free(t); /* NULL and "" both select the default. */ opt.name = ""; - t = term_new(&opt); + t = wsap_vtcore_new(&opt); assert(t); response_len = 0; write_seq(t, "\033[>0q"); - expect_response("\033P>|term\033\\"); - term_free(t); + expect_response("\033P>|wsap_vtcore\033\\"); + wsap_vtcore_free(t); opt.name = NULL; - t = term_new(&opt); + t = wsap_vtcore_new(&opt); assert(t); response_len = 0; write_seq(t, "\033[>0q"); - expect_response("\033P>|term\033\\"); - term_free(t); + expect_response("\033P>|wsap_vtcore\033\\"); + wsap_vtcore_free(t); } static void test_bel_terminator(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); response_len = 0; write_seq(t, "\033P+q6b696e64\007"); expect_response("\033P1+r6b696e64=1b5b313b3242\033\\"); @@ -441,7 +441,7 @@ static void test_bel_terminator(void) response_len = 0; write_seq(t, "\033P$qm\007"); expect_response("\033P1$rm\033\\"); - term_free(t); + wsap_vtcore_free(t); } /* A query far past the old 256-byte DCS buffer is answered in full, @@ -464,7 +464,7 @@ static void test_dcs_long_query(void) snprintf(want + wn, sizeof(want) - (size_t)wn, "\033\\"); assert(strlen(req) > 256); - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); write_seq(t, req); expect_response(want); response_len = 0; @@ -472,26 +472,26 @@ static void test_dcs_long_query(void) expect_response(want); write_seq(t, "X"); assert(row_is(t, 0, "X")); - term_free(t); + wsap_vtcore_free(t); } static void test_dcs_abort_c0(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); response_len = 0; write_seq(t, "\033P+q6b69\nX"); expect_no_response(); assert(row_is(t, 1, "X")); - term_free(t); + wsap_vtcore_free(t); } static void test_dcs_abort_esc(void) { - struct term *t = new_term(80, 24); + struct wsap_vtcore *t = new_term(80, 24); response_len = 0; write_seq(t, "\033P$qm\033[5n"); expect_response("\033[0n"); - term_free(t); + wsap_vtcore_free(t); } int main(void) diff --git a/tests/extern/README.md b/tests/extern/README.md index 2a52e29..e1aa03d 100644 --- a/tests/extern/README.md +++ b/tests/extern/README.md @@ -27,7 +27,7 @@ Kitty parser test suite against it via a Python compatibility layer. - `kitty_parser.py` — Pure-Python VT parser that emits Kitty-style callback events while feeding every byte to the C terminal via `screen.write()`. Maintains state across calls for split-write (threading) tests. -- `screen.py` — `ctypes` wrapper around `libterm.so` providing the Kitty +- `screen.py` — `ctypes` wrapper around the bridge `libkitty_bridge.so` providing the Kitty `Screen`, `Cursor`, `Line`, `CellCursor`, and `Callbacks` API. - `fast_data_types.py` — Pure-Python replacements for Kitty's C-extension helpers (base64, UTF-8 decode, constants). diff --git a/tests/extern/kitty/.gitignore b/tests/extern/kitty/.gitignore index 79a6f1c..42be567 100644 --- a/tests/extern/kitty/.gitignore +++ b/tests/extern/kitty/.gitignore @@ -1,2 +1,2 @@ __pycache__/ -libterm.so +libkitty_bridge.so diff --git a/tests/extern/kitty/screen.py b/tests/extern/kitty/screen.py index a3336d8..1b66234 100644 --- a/tests/extern/kitty/screen.py +++ b/tests/extern/kitty/screen.py @@ -1,9 +1,9 @@ """ctypes wrapper providing the Kitty ``Screen`` API on top of our C terminal. -The shared library ``libterm.so`` is loaded via :mod:`ctypes`. Python calls -only the ``kitty_*`` functions of ``screen_bridge.c``, which wrap the public -API (declared in ``src/term/term.h``). Python classes on top of them match the -subset of Kitty's test API used by ``parser.py``. +The bridge library ``libkitty_bridge.so`` is loaded via :mod:`ctypes`. Python +calls only the ``kitty_*`` functions of ``screen_bridge.c``, which wrap the +public API (declared in ``include/wsap_vtcore/wsap_vtcore.h``). Python classes +on top of them match the subset of Kitty's test API used by ``parser.py``. """ import ctypes @@ -15,7 +15,7 @@ import os _lib = ctypes.CDLL(os.environ.get('WSAP_KITTY_LIB', os.path.join(os.path.dirname(__file__), 'libkitty_bridge.so'))) -# struct term_cell { uint32_t text, fg, bg; uint16_t attrs; uint8_t width, reserved; } +# struct wsap_vtcore_cell { uint32_t text, fg, bg; uint16_t attrs; uint8_t width, reserved; } class TermCell(ctypes.Structure): _fields_ = [ ('text', ctypes.c_uint32), @@ -65,19 +65,19 @@ for _name, _type in { # Constants # --------------------------------------------------------------------------- -TERM_DEFAULT_FG = 0xFFFFFFFF -TERM_DEFAULT_BG = 0xFF1E1E2E +WSAP_VTCORE_DEFAULT_FG = 0xFFFFFFFF +WSAP_VTCORE_DEFAULT_BG = 0xFF1E1E2E -# Cell attributes (must match enum term_attr in term.h) -TERM_ATTR_BOLD = 1 << 0 -TERM_ATTR_ITALIC = 1 << 1 -TERM_ATTR_FAINT = 1 << 10 -TERM_ATTR_STRIKE = 1 << 3 -TERM_ATTR_OVERLINE = 1 << 4 -TERM_ATTR_LINK = 1 << 15 -TERM_ATTR_EMOJI = 1 << 5 -TERM_ATTR_TEXT = 1 << 6 -TERM_UNDERLINE_FLAGS = (1 << 2, 1 << 11, 1 << 12, 1 << 13, 1 << 14) +# Cell attributes (must match enum wsap_vtcore_attr in wsap_vtcore.h) +WSAP_VTCORE_ATTR_BOLD = 1 << 0 +WSAP_VTCORE_ATTR_ITALIC = 1 << 1 +WSAP_VTCORE_ATTR_FAINT = 1 << 10 +WSAP_VTCORE_ATTR_STRIKE = 1 << 3 +WSAP_VTCORE_ATTR_OVERLINE = 1 << 4 +WSAP_VTCORE_ATTR_LINK = 1 << 15 +WSAP_VTCORE_ATTR_EMOJI = 1 << 5 +WSAP_VTCORE_ATTR_TEXT = 1 << 6 +WSAP_VTCORE_UNDERLINE_FLAGS = (1 << 2, 1 << 11, 1 << 12, 1 << 13, 1 << 14) # The longest grapheme cluster that a cell's text is read with. _CLUSTER_CAP = 32 @@ -105,7 +105,7 @@ _lib.kitty_screen_cell_is_tab.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes. _lib.kitty_screen_cell_is_tab.restype = ctypes.c_bool # ANSI color table from escape.c — used for reverse-mapping to Kitty indices. -# Must match the built-in default palette in src/term/palette.c. +# Must match the built-in default palette in src/palette.c. _ANSI_COLORS = [ 0xFF585B70, 0xFFCC6666, 0xFFB5BD68, 0xFFF0C674, 0xFF81A2BE, 0xFFB294BB, 0xFF8ABEB7, 0xFFC5C8C6, @@ -135,7 +135,7 @@ def _build_color_table(): _COLOR_TO_KITTY = _build_color_table() -TERM_COLOR_REF = 0x01000000 +WSAP_VTCORE_COLOR_REF = 0x01000000 def _convert_color(color): @@ -149,10 +149,10 @@ def _convert_color(color): index<<8|1 = indexed (0-255) r<<24|g<<16|b<<8|2 = RGB """ - if (color >> 24) == (TERM_COLOR_REF >> 24): + if (color >> 24) == (WSAP_VTCORE_COLOR_REF >> 24): slot = color & 0x1FF return 0 if slot >= 0x100 else (slot << 8) | 1 - if color == TERM_DEFAULT_FG or color == TERM_DEFAULT_BG: + if color == WSAP_VTCORE_DEFAULT_FG or color == WSAP_VTCORE_DEFAULT_BG: return 0 kitty = _COLOR_TO_KITTY.get(color) if kitty is not None: @@ -251,15 +251,15 @@ class CellCursor: @property def bold(self): - return bool(self._cell.attrs & TERM_ATTR_BOLD) + return bool(self._cell.attrs & WSAP_VTCORE_ATTR_BOLD) @property def italic(self): - return bool(self._cell.attrs & TERM_ATTR_ITALIC) + return bool(self._cell.attrs & WSAP_VTCORE_ATTR_ITALIC) @property def dim(self): - return bool(self._cell.attrs & TERM_ATTR_FAINT) + return bool(self._cell.attrs & WSAP_VTCORE_ATTR_FAINT) @property def reverse(self): @@ -269,13 +269,13 @@ class CellCursor: @property def strikethrough(self): - return bool(self._cell.attrs & TERM_ATTR_STRIKE) + return bool(self._cell.attrs & WSAP_VTCORE_ATTR_STRIKE) @property def decoration(self): - # enum term_underline uses Kitty's numbers: 0=none, 1=straight, + # enum wsap_vtcore_underline uses Kitty's numbers: 0=none, 1=straight, # 2=double, 3=curly, 4=dotted, 5=dashed. - return next((i for i, flag in enumerate(TERM_UNDERLINE_FLAGS, 1) + return next((i for i, flag in enumerate(WSAP_VTCORE_UNDERLINE_FLAGS, 1) if self._cell.attrs & flag), 0) @property diff --git a/tests/extern/kitty/screen_bridge.c b/tests/extern/kitty/screen_bridge.c index 50f86a7..c307c1a 100644 --- a/tests/extern/kitty/screen_bridge.c +++ b/tests/extern/kitty/screen_bridge.c @@ -1,87 +1,87 @@ /* Test-only entry points for the Kitty screen wrapper in screen.py. * Python calls only these functions, so it needs no struct layouts other - * than the public struct term_cell. The kitty_screen_* accessors read - * properties that term.h does not expose. They compile against the current + * than the public struct wsap_vtcore_cell. The kitty_screen_* accessors read + * properties that wsap_vtcore.h does not expose. They compile against the current * terminal layout rather than duplicating byte offsets in Python. */ #include "internal.h" #include "screen.h" typedef void (*kitty_reply_fn)(void *ud, const char *bytes, size_t len); -struct term *kitty_term_new(int cols, int rows, kitty_reply_fn reply, void *ud) +struct wsap_vtcore *kitty_term_new(int cols, int rows, kitty_reply_fn reply, void *ud) { - return term_new(&(struct term_options){ + return wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = cols, .y = rows }, .callbacks = { .ud = ud, .reply = reply }, }); } /* One snapshot serves every cell read. */ -static struct term_snapshot *snap; +static struct wsap_vtcore_snapshot *snap; -void kitty_term_free(struct term *t) +void kitty_term_free(struct wsap_vtcore *t) { /* A new terminal can get the address of the freed one. The snapshot * would then keep its rows, so it goes away too. */ - term_snapshot_free(snap); + wsap_vtcore_snapshot_free(snap); snap = NULL; - term_free(t); + wsap_vtcore_free(t); } -void kitty_term_write(struct term *t, const char *bytes, size_t len) +void kitty_term_write(struct wsap_vtcore *t, const char *bytes, size_t len) { - term_feed(t, bytes, len, 0); + wsap_vtcore_feed(t, bytes, len, 0); } -bool kitty_term_resize(struct term *t, int cols, int rows) +bool kitty_term_resize(struct wsap_vtcore *t, int cols, int rows) { - return term_resize(t, (struct term_vector2i){ .x = cols, .y = rows }); + return wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ .x = cols, .y = rows }); } -int kitty_term_cols(struct term *t) { return term_size(t).x; } -int kitty_term_rows(struct term *t) { return term_size(t).y; } -int kitty_term_cursor_x(struct term *t) { return term_cursor(t).pos.x; } -int kitty_term_cursor_y(struct term *t) { return term_cursor(t).pos.y; } -int kitty_term_cursor_style(struct term *t) { return (int)term_cursor(t).style; } -bool kitty_term_cursor_blink(struct term *t) { return term_cursor(t).blink; } -bool kitty_term_application_cursor(struct term *t) { return term_modes(t).app_cursor; } +int kitty_term_cols(struct wsap_vtcore *t) { return wsap_vtcore_size(t).x; } +int kitty_term_rows(struct wsap_vtcore *t) { return wsap_vtcore_size(t).y; } +int kitty_term_cursor_x(struct wsap_vtcore *t) { return wsap_vtcore_cursor(t).pos.x; } +int kitty_term_cursor_y(struct wsap_vtcore *t) { return wsap_vtcore_cursor(t).pos.y; } +int kitty_term_cursor_style(struct wsap_vtcore *t) { return (int)wsap_vtcore_cursor(t).style; } +bool kitty_term_cursor_blink(struct wsap_vtcore *t) { return wsap_vtcore_cursor(t).blink; } +bool kitty_term_application_cursor(struct wsap_vtcore *t) { return wsap_vtcore_modes(t).app_cursor; } /* Update the snapshot from the live screen, as a renderer reads it. * Returns NULL when the cell is out of range or memory runs out. */ -static struct term_snapshot *cell_snapshot(struct term *t, int col, int row) +static struct wsap_vtcore_snapshot *cell_snapshot(struct wsap_vtcore *t, int col, int row) { - struct term_vector2i size = term_size(t); + struct wsap_vtcore_vector2i size = wsap_vtcore_size(t); if (col < 0 || col >= size.x || row < 0 || row >= size.y) return NULL; if (!snap) - snap = term_snapshot_new(); - term_scroll_to(t, 0); - if (!snap || !term_snapshot_update(snap, t)) + snap = wsap_vtcore_snapshot_new(); + wsap_vtcore_scroll_to(t, 0); + if (!snap || !wsap_vtcore_snapshot_update(snap, t)) return NULL; return snap; } -bool kitty_term_cell(struct term *t, int col, int row, struct term_cell *out) +bool kitty_term_cell(struct wsap_vtcore *t, int col, int row, struct wsap_vtcore_cell *out) { - struct term_snapshot *s = cell_snapshot(t, col, row); + struct wsap_vtcore_snapshot *s = cell_snapshot(t, col, row); if (!s) return false; - *out = term_snapshot_row(s, row)[col]; + *out = wsap_vtcore_snapshot_row(s, row)[col]; return true; } /* The code points of a cell's text: one, or a whole grapheme cluster. * Returns the number of code points and writes at most cap of them. */ -int kitty_term_cell_text(struct term *t, int col, int row, uint32_t *cps, int cap) +int kitty_term_cell_text(struct wsap_vtcore *t, int col, int row, uint32_t *cps, int cap) { - struct term_snapshot *s = cell_snapshot(t, col, row); + struct wsap_vtcore_snapshot *s = cell_snapshot(t, col, row); if (!s) return 0; - return term_snapshot_cluster(s, term_snapshot_row(s, row)[col].text, cps, cap); + return wsap_vtcore_snapshot_cluster(s, wsap_vtcore_snapshot_row(s, row)[col].text, cps, cap); } #define PROPERTY(type, name) \ - type kitty_screen_##name(struct term *t) { return t->name; } + type kitty_screen_##name(struct wsap_vtcore *t) { return t->name; } PROPERTY(int, scroll_top) PROPERTY(int, scroll_bottom) @@ -94,20 +94,20 @@ PROPERTY(bool, strike) PROPERTY(bool, inverse) PROPERTY(uint8_t, underline) -int kitty_screen_row_length(struct term *t, int row) +int kitty_screen_row_length(struct wsap_vtcore *t, int row) { if (!t || row < 0 || row >= t->rows) return 0; - const struct srow *r = term_row(t, row); + const struct srow *r = wsap_vtcore_row(t, row); return r ? (int)r->len : 0; } /* A tab stores a marker cell that a snapshot shows as a blank. Kitty keeps * the tab in its line text, so the wrapper asks for the marker. */ -bool kitty_screen_cell_is_tab(struct term *t, int col, int row) +bool kitty_screen_cell_is_tab(struct wsap_vtcore *t, int col, int row) { if (col < 0 || col >= t->cols || row < 0 || row >= t->rows) return false; - term_scroll_to(t, 0); - const struct cell *cells = term_screen_view_row(t, row); + wsap_vtcore_scroll_to(t, 0); + const struct cell *cells = wsap_vtcore_screen_view_row(t, row); return cells && cells[col].c == '\t'; } diff --git a/tests/gstore_test.c b/tests/gstore_test.c index ea582f3..1ffeaad 100644 --- a/tests/gstore_test.c +++ b/tests/gstore_test.c @@ -10,8 +10,8 @@ */ #include "gstore.h" #include "internal.h" -#include "term/term.h" -#include "term/unicode/utf8.h" +#include "wsap_vtcore/wsap_vtcore.h" +#include "wsap_vtcore/unicode/utf8.h" #include <assert.h> #include <stdio.h> @@ -20,151 +20,151 @@ static void test_direct_unit(void) { - struct gstore *g = term_gstore_new(NULL); + struct gstore *g = wsap_vtcore_gstore_new(NULL); assert(g != NULL); - assert(term_gstore_count(g) == 0); + assert(wsap_vtcore_gstore_count(g) == 0); /* Single code point returns the code point itself. */ uint32_t single = 'A'; - assert(term_gstore_intern(g, &single, 1) == 'A'); - assert(term_gstore_count(g) == 0); + assert(wsap_vtcore_gstore_intern(g, &single, 1) == 'A'); + assert(wsap_vtcore_gstore_count(g) == 0); /* Cluster returns a handle. */ uint32_t c1[2] = { 'e', 0x0301 }; - uint32_t h1 = term_gstore_intern(g, c1, 2); - assert(term_grapheme_is_handle(h1)); - assert(term_gstore_count(g) == 1); + uint32_t h1 = wsap_vtcore_gstore_intern(g, c1, 2); + assert(wsap_vtcore_grapheme_is_handle(h1)); + assert(wsap_vtcore_gstore_count(g) == 1); /* Identical cluster deduplicates to the same handle. */ - uint32_t h1_dup = term_gstore_intern(g, c1, 2); + uint32_t h1_dup = wsap_vtcore_gstore_intern(g, c1, 2); assert(h1_dup == h1); - assert(term_gstore_count(g) == 1); + assert(wsap_vtcore_gstore_count(g) == 1); /* Different cluster gets a distinct handle. */ uint32_t c2[2] = { 'a', 0x0300 }; - uint32_t h2 = term_gstore_intern(g, c2, 2); - assert(term_grapheme_is_handle(h2)); + uint32_t h2 = wsap_vtcore_gstore_intern(g, c2, 2); + assert(wsap_vtcore_grapheme_is_handle(h2)); assert(h2 != h1); - assert(term_gstore_count(g) == 2); + assert(wsap_vtcore_gstore_count(g) == 2); /* Expand both handles. */ - uint32_t out[TERM_GRAPHEME_MAX_LEN] = {0}; - int n = term_gstore_expand(g, h1, out, TERM_GRAPHEME_MAX_LEN); + uint32_t out[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + int n = wsap_vtcore_gstore_expand(g, h1, out, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(out[0] == 'e' && out[1] == 0x0301); - n = term_gstore_expand(g, h2, out, TERM_GRAPHEME_MAX_LEN); + n = wsap_vtcore_gstore_expand(g, h2, out, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(out[0] == 'a' && out[1] == 0x0300); /* Sweep with h1 marked and h2 unmarked. */ - term_gstore_mark(g, h1); - term_gstore_sweep(g, NULL); - assert(term_gstore_count(g) == 1); + wsap_vtcore_gstore_mark(g, h1); + wsap_vtcore_gstore_sweep(g, NULL); + assert(wsap_vtcore_gstore_count(g) == 1); /* h1 is still valid. */ - n = term_gstore_expand(g, h1, out, TERM_GRAPHEME_MAX_LEN); + n = wsap_vtcore_gstore_expand(g, h1, out, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(out[0] == 'e' && out[1] == 0x0301); /* h2 was reclaimed. */ - n = term_gstore_expand(g, h2, out, TERM_GRAPHEME_MAX_LEN); + n = wsap_vtcore_gstore_expand(g, h2, out, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 1 && out[0] == 0xFFFD); /* New cluster can reuse the reclaimed slot. */ uint32_t c3[3] = { 'o', 0x0308, 0x0301 }; - uint32_t h3 = term_gstore_intern(g, c3, 3); - assert(term_grapheme_is_handle(h3)); - assert(term_gstore_count(g) == 2); - n = term_gstore_expand(g, h3, out, TERM_GRAPHEME_MAX_LEN); + uint32_t h3 = wsap_vtcore_gstore_intern(g, c3, 3); + assert(wsap_vtcore_grapheme_is_handle(h3)); + assert(wsap_vtcore_gstore_count(g) == 2); + n = wsap_vtcore_gstore_expand(g, h3, out, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 3); assert(out[0] == 'o' && out[1] == 0x0308 && out[2] == 0x0301); - term_gstore_free(g); + wsap_vtcore_gstore_free(g); } static void test_two_terminals_isolation(void) { - struct term_options opt = { .size = { .x = 20, .y = 4 } }; - struct term *t1 = term_new(&opt); - struct term *t2 = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 20, .y = 4 } }; + struct wsap_vtcore *t1 = wsap_vtcore_new(&opt); + struct wsap_vtcore *t2 = wsap_vtcore_new(&opt); assert(t1 && t2); const char *cluster_text = "e\xcc\x81"; /* 'e' with acute */ - term_feed(t1, cluster_text, strlen(cluster_text), 0); - term_feed(t2, cluster_text, strlen(cluster_text), 0); + wsap_vtcore_feed(t1, cluster_text, strlen(cluster_text), 0); + wsap_vtcore_feed(t2, cluster_text, strlen(cluster_text), 0); /* Free terminal 1. */ - term_free(t1); + wsap_vtcore_free(t1); /* Terminal 2 must still expand its cluster correctly. */ - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); assert(snap); - assert(term_snapshot_update(snap, t2)); + assert(wsap_vtcore_snapshot_update(snap, t2)); - const struct term_cell *row = term_snapshot_row(snap, 0); - assert(row[0].text & TERM_TEXT_CLUSTER); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(snap, 0); + assert(row[0].text & WSAP_VTCORE_TEXT_CLUSTER); - uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0}; - int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + int n = wsap_vtcore_snapshot_cluster(snap, row[0].text, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(cps[0] == 'e' && cps[1] == 0x0301); - term_snapshot_free(snap); - term_free(t2); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t2); } static void test_screen_clusters_survive_sweep(void) { - struct term_options opt = { .size = { .x = 40, .y = 10 }, .scrollback = 10 }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 40, .y = 10 }, .scrollback = 10 }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); /* Write 5 clusters on the top row. */ - term_feed(t, "a\xcc\x80" "b\xcc\x81" "c\xcc\x82" "d\xcc\x83" "e\xcc\x84", 15, 0); + wsap_vtcore_feed(t, "a\xcc\x80" "b\xcc\x81" "c\xcc\x82" "d\xcc\x83" "e\xcc\x84", 15, 0); /* Write ephemeral clusters on row 1, then overwrite them. */ for (int i = 0; i < 50; i++) { - term_feed(t, "\033[2;1H\033[2K", 8, 0); + wsap_vtcore_feed(t, "\033[2;1H\033[2K", 8, 0); char buf[32]; int len = snprintf(buf, sizeof(buf), "z\xcc\x80\xcc\x81%d", i); - term_feed(t, buf, (size_t)len, 0); + wsap_vtcore_feed(t, buf, (size_t)len, 0); } - term_feed(t, "\033[2;1H\033[2K", 8, 0); + wsap_vtcore_feed(t, "\033[2;1H\033[2K", 8, 0); /* Explicit sweep. The clusters on row 0 are on screen and must survive. */ - term_gstore_sweep(t->gstore, t); + wsap_vtcore_gstore_sweep(t->gstore, t); - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); assert(snap); - assert(term_snapshot_update(snap, t)); + assert(wsap_vtcore_snapshot_update(snap, t)); /* Row 0 of screen has "a\xcc\x80...". */ - const struct term_cell *row = term_snapshot_row(snap, 0); - assert(row[0].text & TERM_TEXT_CLUSTER); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(snap, 0); + assert(row[0].text & WSAP_VTCORE_TEXT_CLUSTER); - uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0}; - int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + int n = wsap_vtcore_snapshot_cluster(snap, row[0].text, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(cps[0] == 'a' && cps[1] == 0x0300); - n = term_snapshot_cluster(snap, row[1].text, cps, TERM_GRAPHEME_MAX_LEN); + n = wsap_vtcore_snapshot_cluster(snap, row[1].text, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(cps[0] == 'b' && cps[1] == 0x0301); - n = term_snapshot_cluster(snap, row[2].text, cps, TERM_GRAPHEME_MAX_LEN); + n = wsap_vtcore_snapshot_cluster(snap, row[2].text, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 2); assert(cps[0] == 'c' && cps[1] == 0x0302); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); } static void test_more_than_65536_clusters(void) { /* Bounded history so old lines scroll out. */ - struct term_options opt = { .size = { .x = 80, .y = 24 }, .scrollback = 10 }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 80, .y = 24 }, .scrollback = 10 }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); /* @@ -183,37 +183,37 @@ static void test_more_than_65536_clusters(void) size_t len = 0; buf[len++] = base; - len += (size_t)term_utf8_encode(cp1, buf + len); - len += (size_t)term_utf8_encode(cp2, buf + len); + len += (size_t)wsap_vtcore_utf8_encode(cp1, buf + len); + len += (size_t)wsap_vtcore_utf8_encode(cp2, buf + len); buf[len++] = '\r'; buf[len++] = '\n'; - term_feed(t, buf, len, 0); + wsap_vtcore_feed(t, buf, len, 0); total++; } assert(total >= 65536); /* Verify the latest cluster on screen reads back correctly. */ - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); assert(snap); - assert(term_snapshot_update(snap, t)); + assert(wsap_vtcore_snapshot_update(snap, t)); - struct term_cursor c = term_cursor(t); + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t); int y = c.pos.y > 0 ? c.pos.y - 1 : 0; - const struct term_cell *row = term_snapshot_row(snap, y); - assert(row[0].text & TERM_TEXT_CLUSTER); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(snap, y); + assert(row[0].text & WSAP_VTCORE_TEXT_CLUSTER); - uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0}; - int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN); + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + int n = wsap_vtcore_snapshot_cluster(snap, row[0].text, cps, WSAP_VTCORE_GRAPHEME_MAX_LEN); assert(n == 3); /* Live cluster count must be small (only bounded screen and history). */ - uint32_t count = term_gstore_count(t->gstore); + uint32_t count = wsap_vtcore_gstore_count(t->gstore); assert(count < 2000); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); } int main(void) diff --git a/tests/header_test.sh b/tests/header_test.sh index 9fd1041..299a950 100644 --- a/tests/header_test.sh +++ b/tests/header_test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# A host includes <term/term.h> and nothing else. The package puts only the -# parent of term/ on the include path. The headers compile alone as strict +# A host includes <wsap_vtcore/wsap_vtcore.h> and nothing else. The package puts only the +# parent of wsap_vtcore/ on the include path. The headers compile alone as strict # C11 and as C++. set -euo pipefail cd "${1:-$(dirname "$0")/..}" @@ -22,18 +22,18 @@ check() { fi } -check term.h <<'EOF' -#include <term/term.h> +check wsap_vtcore.h <<'EOF' +#include <wsap_vtcore/wsap_vtcore.h> EOF # Apple headers define wide before a host includes the Unicode API. check "unicode/width.h: conflicts with host types" <<'EOF' typedef struct wide { int value; } wide; -#include <term/unicode/width.h> +#include <wsap_vtcore/unicode/width.h> EOF -# A host that uses the names the Unicode API had before the term_ and -# TERM_ prefixes. The API must not clash with them in either order. +# A host that uses the names the Unicode API had before the wsap_vtcore_ and +# WSAP_VTCORE_ prefixes. The API must not clash with them in either order. check "unicode API: host names declared first" <<'EOF' int unicode_width(int); static int in_ranges; @@ -45,9 +45,9 @@ struct unicode_range { int lo; }; #define IN_TABLE 1 #define UNICODE_DATA_VERSION "host" #define UTF_8_H -#include <term/unicode/utf8.h> -#include <term/unicode/width.h> -#include <term/unicode/grapheme.h> +#include <wsap_vtcore/unicode/utf8.h> +#include <wsap_vtcore/unicode/width.h> +#include <wsap_vtcore/unicode/grapheme.h> int host_use(void) { return in_ranges + zero_width + utf8d + unicode_width(1) + UTF8_ACCEPT + GRAPHEME_MAX_LEN; @@ -55,9 +55,9 @@ int host_use(void) EOF check "unicode API: host names declared after" <<'EOF' -#include <term/unicode/utf8.h> -#include <term/unicode/width.h> -#include <term/unicode/grapheme.h> +#include <wsap_vtcore/unicode/utf8.h> +#include <wsap_vtcore/unicode/width.h> +#include <wsap_vtcore/unicode/grapheme.h> int unicode_width(int); static int in_ranges; #define UTF8_ACCEPT 7 diff --git a/tests/helpers/term_api.h b/tests/helpers/term_api.h index f2d6a5d..17a29ae 100644 --- a/tests/helpers/term_api.h +++ b/tests/helpers/term_api.h @@ -7,7 +7,7 @@ * terminal shows. */ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <stdbool.h> #include <stddef.h> @@ -17,149 +17,149 @@ /* The history size the tests assume. */ #define TEST_SCROLLBACK 4096 -static inline struct term *tt_new_opts(int cols, int rows, const struct term_callbacks *cb) +static inline struct wsap_vtcore *tt_new_opts(int cols, int rows, const struct wsap_vtcore_callbacks *cb) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = cols, .y = rows }, .scrollback = TEST_SCROLLBACK, }; if (cb) opt.callbacks = *cb; - return term_new(&opt); + return wsap_vtcore_new(&opt); } -static inline struct term *tt_new(int cols, int rows) +static inline struct wsap_vtcore *tt_new(int cols, int rows) { return tt_new_opts(cols, rows, NULL); } -static inline void tt_write(struct term *t, const char *s, size_t len) +static inline void tt_write(struct wsap_vtcore *t, const char *s, size_t len) { - term_feed(t, s, len, 0); + wsap_vtcore_feed(t, s, len, 0); } -static inline void tt_puts(struct term *t, const char *s) +static inline void tt_puts(struct wsap_vtcore *t, const char *s) { - term_feed(t, s, strlen(s), 0); + wsap_vtcore_feed(t, s, strlen(s), 0); } -static inline int tt_cols(const struct term *t) { return term_size(t).x; } -static inline int tt_rows(const struct term *t) { return term_size(t).y; } -static inline int tt_cursor_x(const struct term *t) { return term_cursor(t).pos.x; } -static inline int tt_cursor_y(const struct term *t) { return term_cursor(t).pos.y; } -static inline int tt_history(const struct term *t) { return term_scrollback(t).total; } -static inline int tt_view_offset(const struct term *t) { return term_scrollback(t).offset; } +static inline int tt_cols(const struct wsap_vtcore *t) { return wsap_vtcore_size(t).x; } +static inline int tt_rows(const struct wsap_vtcore *t) { return wsap_vtcore_size(t).y; } +static inline int tt_cursor_x(const struct wsap_vtcore *t) { return wsap_vtcore_cursor(t).pos.x; } +static inline int tt_cursor_y(const struct wsap_vtcore *t) { return wsap_vtcore_cursor(t).pos.y; } +static inline int tt_history(const struct wsap_vtcore *t) { return wsap_vtcore_scrollback(t).total; } +static inline int tt_view_offset(const struct wsap_vtcore *t) { return wsap_vtcore_scrollback(t).offset; } /* One snapshot serves every read. It follows whichever terminal a test * reads last. */ -static struct term_snapshot *tt_snapshot_for(struct term *t) +static struct wsap_vtcore_snapshot *tt_snapshot_for(struct wsap_vtcore *t) { - static struct term_snapshot *snap; + static struct wsap_vtcore_snapshot *snap; if (!snap) - snap = term_snapshot_new(); - term_snapshot_update(snap, t); + snap = wsap_vtcore_snapshot_new(); + wsap_vtcore_snapshot_update(snap, t); return snap; } -static const struct term_cell tt_blank_cell = { - .text = ' ', .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .width = 1, +static const struct wsap_vtcore_cell tt_blank_cell = { + .text = ' ', .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .width = 1, }; /* A cell of the viewport. Out-of-range columns read as a blank cell. */ -static inline const struct term_cell *tt_view_cell(struct term *t, int col, int row) +static inline const struct wsap_vtcore_cell *tt_view_cell(struct wsap_vtcore *t, int col, int row) { - struct term_snapshot *s = tt_snapshot_for(t); - const struct term_cell *cells = term_snapshot_row(s, row); + struct wsap_vtcore_snapshot *s = tt_snapshot_for(t); + const struct wsap_vtcore_cell *cells = wsap_vtcore_snapshot_row(s, row); if (!cells) return NULL; - if (col < 0 || col >= term_snapshot_view(s)->size.x) + if (col < 0 || col >= wsap_vtcore_snapshot_view(s)->size.x) return &tt_blank_cell; return &cells[col]; } /* A cell of the live screen, whatever the viewport shows. */ -static inline const struct term_cell *tt_cell(struct term *t, int col, int row) +static inline const struct wsap_vtcore_cell *tt_cell(struct wsap_vtcore *t, int col, int row) { int offset = tt_view_offset(t); if (offset) - term_scroll_to(t, 0); - const struct term_cell *cell = tt_view_cell(t, col, row); + wsap_vtcore_scroll_to(t, 0); + const struct wsap_vtcore_cell *cell = tt_view_cell(t, col, row); if (offset) - term_scroll_to(t, offset); + wsap_vtcore_scroll_to(t, offset); return cell; } /* The code points of a cell's text: one, or a whole cluster. The snapshot * that the last read used must still describe the terminal. */ -static inline int tt_cell_cps(struct term *t, const struct term_cell *cell, +static inline int tt_cell_cps(struct wsap_vtcore *t, const struct wsap_vtcore_cell *cell, uint32_t *cps, int cap) { - return term_snapshot_cluster(tt_snapshot_for(t), cell->text, cps, cap); + return wsap_vtcore_snapshot_cluster(tt_snapshot_for(t), cell->text, cps, cap); } /* The first code point of a cell's text. */ -static inline uint32_t tt_cell_cp(struct term *t, const struct term_cell *cell) +static inline uint32_t tt_cell_cp(struct wsap_vtcore *t, const struct wsap_vtcore_cell *cell) { uint32_t cp = 0; - if (!(cell->text & TERM_TEXT_CLUSTER)) + if (!(cell->text & WSAP_VTCORE_TEXT_CLUSTER)) return cell->text; tt_cell_cps(t, cell, &cp, 1); return cp; } -static inline bool tt_is_cluster(const struct term_cell *cell) +static inline bool tt_is_cluster(const struct wsap_vtcore_cell *cell) { - return (cell->text & TERM_TEXT_CLUSTER) != 0; + return (cell->text & WSAP_VTCORE_TEXT_CLUSTER) != 0; } /* The selected columns [begin, end) of a viewport row. */ -static inline struct term_span tt_row_selection(struct term *t, int row) +static inline struct wsap_vtcore_span tt_row_selection(struct wsap_vtcore *t, int row) { - return term_snapshot_row_selection(tt_snapshot_for(t), row); + return wsap_vtcore_snapshot_row_selection(tt_snapshot_for(t), row); } -static inline bool tt_selected(struct term *t, int col, int row) +static inline bool tt_selected(struct wsap_vtcore *t, int col, int row) { - struct term_span span = tt_row_selection(t, row); + struct wsap_vtcore_span span = tt_row_selection(t, row); return col >= span.begin && col < span.end; } /* Select from one viewport cell to another, both inclusive. */ -static inline void tt_select(struct term *t, int x1, int y1, int x2, int y2) +static inline void tt_select(struct wsap_vtcore *t, int x1, int y1, int x2, int y2) { bool forward = y1 < y2 || (y1 == y2 && x1 <= x2); - struct term_vector2i a = { .x = x1, .y = y1 }, b = { .x = x2, .y = y2 }; - term_select_start(t, forward ? a : b, false, TERM_SELECT_CELL); - term_select_extend(t, forward ? b : a, true); + struct wsap_vtcore_vector2i a = { .x = x1, .y = y1 }, b = { .x = x2, .y = y2 }; + wsap_vtcore_select_start(t, forward ? a : b, false, WSAP_VTCORE_SELECT_CELL); + wsap_vtcore_select_extend(t, forward ? b : a, true); } /* The helpers below return new strings. The caller frees them. */ /* NULL when nothing is selected. */ -static inline char *tt_selection_text(const struct term *t) +static inline char *tt_selection_text(const struct wsap_vtcore *t) { - return term_selection_text(t); + return wsap_vtcore_selection_text(t); } -static inline char *tt_history_text(struct term *t, int max_rows) +static inline char *tt_history_text(struct wsap_vtcore *t, int max_rows) { - return term_history_text(t, max_rows); + return wsap_vtcore_history_text(t, max_rows); } /* NULL when there is no link. */ -static inline char *tt_link_at(struct term *t, int col, int row) +static inline char *tt_link_at(struct wsap_vtcore *t, int col, int row) { - return term_link_at(t, (struct term_vector2i){ .x = col, .y = row }); + return wsap_vtcore_link_at(t, (struct wsap_vtcore_vector2i){ .x = col, .y = row }); } -static inline bool tt_resize(struct term *t, int cols, int rows) +static inline bool tt_resize(struct wsap_vtcore *t, int cols, int rows) { - return term_resize(t, (struct term_vector2i){ .x = cols, .y = rows }); + return wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ .x = cols, .y = rows }); } /* The ARGB value of a color in the terminal's current palette. */ -static inline uint32_t tt_color(struct term *t, term_color c) +static inline uint32_t tt_color(struct wsap_vtcore *t, wsap_vtcore_color c) { - return term_view_color(term_snapshot_view(tt_snapshot_for(t)), c); + return wsap_vtcore_view_color(wsap_vtcore_snapshot_view(tt_snapshot_for(t)), c); } #endif diff --git a/tests/hist_test.c b/tests/hist_test.c index 691ae3c..1cf807c 100644 --- a/tests/hist_test.c +++ b/tests/hist_test.c @@ -1,6 +1,6 @@ #include "hist.h" #include "hist_view.h" -#include "term/unicode/grapheme.h" +#include "wsap_vtcore/unicode/grapheme.h" #include <assert.h> #include <limits.h> @@ -15,70 +15,70 @@ static uint64_t lines(const struct hist *h) static struct cell dc(uint32_t c) { - return (struct cell){ .c = c, .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }; + return (struct cell){ .c = c, .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }; } static void test_init_free(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); assert(lines(&h) == 0); assert(hist_first_id(&h) == 0); assert(!hist_is_open(&h)); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_ascii_roundtrip(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); const char *msg = "Hello, world!"; - term_hist_push_ascii(&h, msg, (int)strlen(msg), NULL, false); + wsap_vtcore_hist_push_ascii(&h, msg, (int)strlen(msg), NULL, false); assert(lines(&h) == 1); - assert(term_hist_line_rows(&h, 0, 80) == 1); - assert(term_hist_line_rows(&h, 0, 5) == 3); + assert(wsap_vtcore_hist_line_rows(&h, 0, 80) == 1); + assert(wsap_vtcore_hist_line_rows(&h, 0, 5) == 3); struct cell out[80]; - int n = term_hist_decode_segment(&h, 0, 0, 80, out, NULL); + int n = wsap_vtcore_hist_decode_segment(&h, 0, 0, 80, out, NULL); assert(n == (int)strlen(msg)); for (int i = 0; i < n; i++) { assert(out[i].c == (uint32_t)msg[i]); - assert(out[i].fg == TERM_COLOR_FG); - assert(out[i].bg == TERM_COLOR_BG); + assert(out[i].fg == WSAP_VTCORE_COLOR_FG); + assert(out[i].bg == WSAP_VTCORE_COLOR_BG); assert(out[i].flags == 0); } - assert(term_hist_decode_segment(&h, 0, 0, 5, out, NULL) == 5); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 5, out, NULL) == 5); assert(out[0].c == 'H' && out[4].c == 'o'); - assert(term_hist_decode_segment(&h, 0, 1, 5, out, NULL) == 5); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 1, 5, out, NULL) == 5); assert(out[0].c == ',' && out[4].c == 'r'); - assert(term_hist_decode_segment(&h, 0, 2, 5, out, NULL) == 3); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 2, 5, out, NULL) == 3); assert(out[0].c == 'l' && out[2].c == '!'); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_attributes_roundtrip(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell row[10]; for (int i = 0; i < 10; i++) { row[i] = (struct cell){ .c = 'A' + i, - .fg = term_color_rgb(i * 10, i * 20, i * 25), - .bg = term_color_rgb(255 - i * 10, 0, 0), + .fg = wsap_vtcore_color_rgb(i * 10, i * 20, i * 25), + .bg = wsap_vtcore_color_rgb(255 - i * 10, 0, 0), .flags = (i % 2 == 0) ? CELL_BOLD : CELL_ITALIC, .pad = (uint16_t)(100 + i), }; } - term_hist_push_row(&h, row, 10, false, NULL); + wsap_vtcore_hist_push_row(&h, row, 10, false, NULL); assert(lines(&h) == 1); struct cell out[10]; - assert(term_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 10); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 10); for (int i = 0; i < 10; i++) { assert(out[i].c == row[i].c); assert(out[i].fg == row[i].fg); @@ -86,252 +86,252 @@ static void test_attributes_roundtrip(void) assert(out[i].flags == row[i].flags); assert(out[i].pad == row[i].pad); } - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_wide_and_wrap(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell row[4] = { dc('A'), dc(0x4e16), dc(' '), dc('B') }; row[1].flags = CELL_WIDE; row[2].flags = CELL_TRAIL; - term_hist_push_row(&h, row, 4, false, NULL); + wsap_vtcore_hist_push_row(&h, row, 4, false, NULL); - assert(term_hist_line_rows(&h, 0, 4) == 1); + assert(wsap_vtcore_hist_line_rows(&h, 0, 4) == 1); /* Width 2: 'A' and a pad, then the wide cell, then 'B'. */ - assert(term_hist_line_rows(&h, 0, 2) == 3); + assert(wsap_vtcore_hist_line_rows(&h, 0, 2) == 3); struct cell out[4]; - assert(term_hist_decode_segment(&h, 0, 0, 2, out, NULL) == 2); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 2, out, NULL) == 2); assert(out[0].c == 'A'); assert(out[1].flags & CELL_WRAP_PAD); - assert(term_hist_decode_segment(&h, 0, 1, 2, out, NULL) == 2); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 1, 2, out, NULL) == 2); assert(out[0].c == 0x4e16 && (out[0].flags & CELL_WIDE)); assert(out[1].flags & CELL_TRAIL); - assert(term_hist_decode_segment(&h, 0, 2, 2, out, NULL) == 1); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 2, 2, out, NULL) == 1); assert(out[0].c == 'B'); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_clusters_roundtrip(void) { - struct gstore *g = term_gstore_new(NULL); + struct gstore *g = wsap_vtcore_gstore_new(NULL); assert(g); uint32_t cps[3] = { 'e', 0x0301, 0x0300 }; - uint32_t handle = term_gstore_intern(g, cps, 3); + uint32_t handle = wsap_vtcore_gstore_intern(g, cps, 3); struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell row[2] = { dc(handle), dc('X') }; - term_hist_push_row(&h, row, 2, false, g); + wsap_vtcore_hist_push_row(&h, row, 2, false, g); struct cell out[2]; - assert(term_hist_decode_segment(&h, 0, 0, 2, out, g) == 2); - assert(term_grapheme_is_handle(out[0].c)); - uint32_t got[TERM_GRAPHEME_MAX_LEN]; - assert(term_gstore_expand(g, out[0].c, got, TERM_GRAPHEME_MAX_LEN) == 3); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 2, out, g) == 2); + assert(wsap_vtcore_grapheme_is_handle(out[0].c)); + uint32_t got[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + assert(wsap_vtcore_gstore_expand(g, out[0].c, got, WSAP_VTCORE_GRAPHEME_MAX_LEN) == 3); assert(got[0] == cps[0] && got[1] == cps[1] && got[2] == cps[2]); assert(out[1].c == 'X'); - term_hist_free(&h); - term_gstore_free(g); + wsap_vtcore_hist_free(&h); + wsap_vtcore_gstore_free(g); } static void test_open_lines_and_pop(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell part1[3] = { dc('1'), dc('2'), dc('3') }; - term_hist_push_row(&h, part1, 3, true, NULL); + wsap_vtcore_hist_push_row(&h, part1, 3, true, NULL); assert(lines(&h) == 1 && hist_is_open(&h)); struct cell part2[2] = { dc('4'), dc('5') }; - term_hist_push_row(&h, part2, 2, false, NULL); + wsap_vtcore_hist_push_row(&h, part2, 2, false, NULL); assert(lines(&h) == 1 && !hist_is_open(&h)); struct cell out[5]; - assert(term_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 5); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 5); for (int i = 0; i < 5; i++) assert(out[i].c == (uint32_t)('1' + i)); struct cell popped[2]; - assert(term_hist_pop_tail_cells(&h, 2, popped, NULL) == 2); + assert(wsap_vtcore_hist_pop_tail_cells(&h, 2, popped, NULL) == 2); assert(popped[0].c == '4' && popped[1].c == '5'); - assert(term_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 3); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 3); assert(out[0].c == '1' && out[2].c == '3'); /* Pop from an open line with a pen. */ - term_hist_close_open_line(&h); + wsap_vtcore_hist_close_open_line(&h); struct cell color[2] = { { .c = 'A', .fg = 0xff0000, .bg = 0x00ff00, .flags = CELL_BOLD }, { .c = 'B', .fg = 0xff0000, .bg = 0x00ff00, .flags = CELL_BOLD }, }; - term_hist_push_row(&h, color, 2, true, NULL); + wsap_vtcore_hist_push_row(&h, color, 2, true, NULL); assert(lines(&h) == 2); struct cell pop_color[1]; - assert(term_hist_pop_tail_cells(&h, 1, pop_color, NULL) == 1); + assert(wsap_vtcore_hist_pop_tail_cells(&h, 1, pop_color, NULL) == 1); assert(pop_color[0].c == 'B' && pop_color[0].fg == 0xff0000 && pop_color[0].bg == 0x00ff00); assert(pop_color[0].flags & CELL_BOLD); - assert(term_hist_decode_segment(&h, 1, 0, 10, out, NULL) == 1); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 10, out, NULL) == 1); assert(out[0].c == 'A' && out[0].fg == 0xff0000 && (out[0].flags & CELL_BOLD)); /* Popping a whole line returns its cells and removes it. */ struct cell all[4]; - assert(term_hist_pop_line(&h, all, 4, NULL) == 1); + assert(wsap_vtcore_hist_pop_line(&h, all, 4, NULL) == 1); assert(all[0].c == 'A'); assert(lines(&h) == 1 && !hist_is_open(&h)); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_open_line_joins(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell line1[2] = { dc('X'), dc('Y') }; - term_hist_push_row(&h, line1, 2, true, NULL); - term_hist_close_open_line(&h); + wsap_vtcore_hist_push_row(&h, line1, 2, true, NULL); + wsap_vtcore_hist_close_open_line(&h); struct cell line2[2] = { dc('Z'), dc('W') }; - term_hist_push_row(&h, line2, 2, false, NULL); + wsap_vtcore_hist_push_row(&h, line2, 2, false, NULL); assert(lines(&h) == 2); struct cell out[16]; - assert(term_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 2); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 2); assert(out[0].c == 'X' && out[1].c == 'Y'); - assert(term_hist_decode_segment(&h, 1, 0, 10, out, NULL) == 2); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 10, out, NULL) == 2); assert(out[0].c == 'Z' && out[1].c == 'W'); /* ASCII joins a wide open line. */ - struct cell wide[2] = { { .c = 0x4e2d, .fg = 0x123456, .bg = TERM_COLOR_BG, .flags = CELL_WIDE }, - { .c = 0, .fg = 0x123456, .bg = TERM_COLOR_BG, .flags = CELL_TRAIL } }; - term_hist_push_row(&h, wide, 2, true, NULL); - term_hist_push_ascii(&h, "hello", 5, NULL, false); + struct cell wide[2] = { { .c = 0x4e2d, .fg = 0x123456, .bg = WSAP_VTCORE_COLOR_BG, .flags = CELL_WIDE }, + { .c = 0, .fg = 0x123456, .bg = WSAP_VTCORE_COLOR_BG, .flags = CELL_TRAIL } }; + wsap_vtcore_hist_push_row(&h, wide, 2, true, NULL); + wsap_vtcore_hist_push_ascii(&h, "hello", 5, NULL, false); assert(lines(&h) == 3); - assert(term_hist_decode_segment(&h, 2, 0, 10, out, NULL) == 7); + assert(wsap_vtcore_hist_decode_segment(&h, 2, 0, 10, out, NULL) == 7); assert(out[0].c == 0x4e2d && out[0].fg == 0x123456); - assert(out[2].c == 'h' && out[2].fg == TERM_COLOR_FG); - term_hist_free(&h); + assert(out[2].c == 'h' && out[2].fg == WSAP_VTCORE_COLOR_FG); + wsap_vtcore_hist_free(&h); } static void test_eviction(void) { struct hist h; - assert(term_hist_init(&h, 5, 64 * 1024 * 2)); + assert(wsap_vtcore_hist_init(&h, 5, 64 * 1024 * 2)); for (int i = 0; i < 10; i++) { char buf[16]; snprintf(buf, sizeof(buf), "line%d", i); - term_hist_push_ascii(&h, buf, (int)strlen(buf), NULL, false); + wsap_vtcore_hist_push_ascii(&h, buf, (int)strlen(buf), NULL, false); } assert(lines(&h) == 5); assert(hist_first_id(&h) == 5 && hist_end_id(&h) == 10); struct cell out[16]; - assert(term_hist_decode_segment(&h, 5, 0, 16, out, NULL) == 5); + assert(wsap_vtcore_hist_decode_segment(&h, 5, 0, 16, out, NULL) == 5); assert(out[0].c == 'l' && out[4].c == '5'); - assert(term_hist_decode_segment(&h, 9, 0, 16, out, NULL) == 5); + assert(wsap_vtcore_hist_decode_segment(&h, 9, 0, 16, out, NULL) == 5); assert(out[4].c == '9'); - assert(term_hist_decode_segment(&h, 4, 0, 16, out, NULL) == 0); - term_hist_free(&h); + assert(wsap_vtcore_hist_decode_segment(&h, 4, 0, 16, out, NULL) == 0); + wsap_vtcore_hist_free(&h); } static void test_emoji_and_text_presentation(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell row[3] = { dc(0x2764), dc(' '), dc(0x2600) }; row[0].flags = CELL_WIDE | CELL_EMOJI; row[1].flags = CELL_TRAIL; row[2].flags = CELL_TEXT; - term_hist_push_row(&h, row, 3, false, NULL); + wsap_vtcore_hist_push_row(&h, row, 3, false, NULL); struct cell out[3]; - assert(term_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 3); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 10, out, NULL) == 3); assert(out[0].c == 0x2764 && (out[0].flags & CELL_WIDE) && (out[0].flags & CELL_EMOJI)); assert(out[1].flags & CELL_TRAIL); assert(out[2].c == 0x2600 && (out[2].flags & CELL_TEXT)); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_width_one(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); - term_hist_push_ascii(&h, "ABC", 3, NULL, false); - assert(term_hist_line_rows(&h, 0, 1) == 3); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); + wsap_vtcore_hist_push_ascii(&h, "ABC", 3, NULL, false); + assert(wsap_vtcore_hist_line_rows(&h, 0, 1) == 3); struct cell out[2]; - assert(term_hist_decode_segment(&h, 0, 0, 1, out, NULL) == 1 && out[0].c == 'A'); - assert(term_hist_decode_segment(&h, 0, 1, 1, out, NULL) == 1 && out[0].c == 'B'); - assert(term_hist_decode_segment(&h, 0, 2, 1, out, NULL) == 1 && out[0].c == 'C'); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 1, out, NULL) == 1 && out[0].c == 'A'); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 1, 1, out, NULL) == 1 && out[0].c == 'B'); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 2, 1, out, NULL) == 1 && out[0].c == 'C'); struct cell wide[2] = { dc(0x4e16), dc(' ') }; wide[0].flags = CELL_WIDE; wide[1].flags = CELL_TRAIL; - term_hist_push_row(&h, wide, 2, false, NULL); - assert(term_hist_line_rows(&h, 1, 1) == 1); - assert(term_hist_decode_segment(&h, 1, 0, 1, out, NULL) == 1); + wsap_vtcore_hist_push_row(&h, wide, 2, false, NULL); + assert(wsap_vtcore_hist_line_rows(&h, 1, 1) == 1); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 1, out, NULL) == 1); assert(out[0].c == 0x4e16 && (out[0].flags & CELL_WIDE)); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_blank_lines(void) { struct hist h; - assert(term_hist_init(&h, 10, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 10, 64 * 1024 * 4)); const char *first = "First line on page 0"; - term_hist_push_ascii(&h, first, (int)strlen(first), NULL, false); - term_hist_push_blank(&h, 10); + wsap_vtcore_hist_push_ascii(&h, first, (int)strlen(first), NULL, false); + wsap_vtcore_hist_push_blank(&h, 10); assert(lines(&h) == 10); assert(hist_first_id(&h) == 1); for (int i = 0; i < 20; i++) { char buf[32]; snprintf(buf, sizeof(buf), "line %d", i); - term_hist_push_ascii(&h, buf, (int)strlen(buf), NULL, false); + wsap_vtcore_hist_push_ascii(&h, buf, (int)strlen(buf), NULL, false); } struct cell out[32]; - assert(term_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 32, out, NULL) == 7); + assert(wsap_vtcore_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 32, out, NULL) == 7); assert(out[5].c == '1' && out[6].c == '9'); /* A blank row closes an open line and adds no line. */ - term_hist_push_ascii(&h, "open", 4, NULL, true); + wsap_vtcore_hist_push_ascii(&h, "open", 4, NULL, true); uint64_t before = hist_end_id(&h); - term_hist_push_blank(&h, 1); + wsap_vtcore_hist_push_blank(&h, 1); assert(!hist_is_open(&h) && hist_end_id(&h) == before); /* More blank rows than the limit keep the id count going. */ - term_hist_push_blank(&h, 1000); + wsap_vtcore_hist_push_blank(&h, 1000); assert(lines(&h) == 10 && hist_end_id(&h) == before + 1000); - term_hist_push_blank(&h, 5); + wsap_vtcore_hist_push_blank(&h, 5); assert(lines(&h) == 10 && hist_end_id(&h) == before + 1005); - assert(term_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 32, out, NULL) == 0); - assert(term_hist_line_rows(&h, hist_end_id(&h) - 1, 32) == 1); - term_hist_free(&h); + assert(wsap_vtcore_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 32, out, NULL) == 0); + assert(wsap_vtcore_hist_line_rows(&h, hist_end_id(&h) - 1, 32) == 1); + wsap_vtcore_hist_free(&h); } static void test_open_line_attrs_continuation(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell r1[5], r2[10]; for (int i = 0; i < 5; i++) - r1[i] = (struct cell){ .c = '1' + i, .fg = term_color_rgb(255, 0, 0), .bg = TERM_COLOR_BG }; + r1[i] = (struct cell){ .c = '1' + i, .fg = wsap_vtcore_color_rgb(255, 0, 0), .bg = WSAP_VTCORE_COLOR_BG }; for (int i = 0; i < 10; i++) - r2[i] = (struct cell){ .c = 'a' + i, .fg = i < 5 ? term_color_rgb(255, 0, 0) : term_color_rgb(0, 0, 255), - .bg = TERM_COLOR_BG }; - term_hist_push_row(&h, r1, 5, true, NULL); - term_hist_push_row(&h, r2, 10, false, NULL); + r2[i] = (struct cell){ .c = 'a' + i, .fg = i < 5 ? wsap_vtcore_color_rgb(255, 0, 0) : wsap_vtcore_color_rgb(0, 0, 255), + .bg = WSAP_VTCORE_COLOR_BG }; + wsap_vtcore_hist_push_row(&h, r1, 5, true, NULL); + wsap_vtcore_hist_push_row(&h, r2, 10, false, NULL); assert(lines(&h) == 1); struct cell out[15]; - assert(term_hist_decode_segment(&h, 0, 0, 15, out, NULL) == 15); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 15, out, NULL) == 15); for (int i = 0; i < 10; i++) - assert(out[i].fg == term_color_rgb(255, 0, 0)); + assert(out[i].fg == wsap_vtcore_color_rgb(255, 0, 0)); for (int i = 10; i < 15; i++) - assert(out[i].fg == term_color_rgb(0, 0, 255)); - term_hist_free(&h); + assert(out[i].fg == wsap_vtcore_color_rgb(0, 0, 255)); + wsap_vtcore_hist_free(&h); } static void mark_link(void *ud, uint16_t link) @@ -342,76 +342,76 @@ static void mark_link(void *ud, uint16_t link) static void test_hyperlinks(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct pen_attr pen = pen_attr_default(); pen.link = 42; - term_hist_push_ascii(&h, "Link text", 9, &pen, false); + wsap_vtcore_hist_push_ascii(&h, "Link text", 9, &pen, false); struct cell row[2] = { dc('a'), dc('b') }; row[1].pad = 7; row[1].flags = CELL_LINK; - term_hist_push_row(&h, row, 2, true, NULL); + wsap_vtcore_hist_push_row(&h, row, 2, true, NULL); struct cell out[16]; - assert(term_hist_decode_segment(&h, 0, 0, 16, out, NULL) == 9); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 16, out, NULL) == 9); for (int i = 0; i < 9; i++) assert(out[i].pad == 42); int marks[64] = { 0 }; - term_hist_mark_links(&h, mark_link, marks); + wsap_vtcore_hist_mark_links(&h, mark_link, marks); assert(marks[42] && marks[7]); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_long_lines(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); /* A line past the part limit keeps one id. */ char chunk[1024]; memset(chunk, 'X', sizeof(chunk)); for (int i = 0; i < 64; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); - term_hist_push_ascii(&h, chunk, 100, NULL, false); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); + wsap_vtcore_hist_push_ascii(&h, chunk, 100, NULL, false); assert(lines(&h) == 1); - assert(term_hist_line_cells(&h, 0) == 65636); - assert(term_hist_line_rows(&h, 0, 1000) == 66); + assert(wsap_vtcore_hist_line_cells(&h, 0) == 65636); + assert(wsap_vtcore_hist_line_rows(&h, 0, 1000) == 66); struct cell out[1000]; - assert(term_hist_decode_segment(&h, 0, 64, 1000, out, NULL) == 1000); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 64, 1000, out, NULL) == 1000); for (int i = 0; i < 1000; i++) assert(out[i].c == 'X'); - assert(term_hist_decode_segment(&h, 0, 65, 1000, out, NULL) == 636); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 65, 1000, out, NULL) == 636); memset(chunk, 'Y', sizeof(chunk)); for (int i = 0; i < 64; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); - term_hist_push_ascii(&h, chunk, 100, NULL, false); - term_hist_push_ascii(&h, "tail", 4, NULL, false); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); + wsap_vtcore_hist_push_ascii(&h, chunk, 100, NULL, false); + wsap_vtcore_hist_push_ascii(&h, "tail", 4, NULL, false); assert(lines(&h) == 3); - assert(term_hist_line_rows(&h, 1, 1000) == 66); - assert(term_hist_decode_segment(&h, 1, 0, 1000, out, NULL) == 1000 && out[0].c == 'Y'); - assert(term_hist_decode_segment(&h, 2, 0, 1000, out, NULL) == 4 && out[0].c == 't'); - assert(term_hist_rows(&h, 1000) == 133); + assert(wsap_vtcore_hist_line_rows(&h, 1, 1000) == 66); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 1000, out, NULL) == 1000 && out[0].c == 'Y'); + assert(wsap_vtcore_hist_decode_segment(&h, 2, 0, 1000, out, NULL) == 4 && out[0].c == 't'); + assert(wsap_vtcore_hist_rows(&h, 1000) == 133); /* One long ASCII push splits into parts but reads back whole. */ - term_hist_free(&h); - assert(term_hist_init(&h, 100, 64 * 1024 * 8)); + wsap_vtcore_hist_free(&h); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 8)); int big_len = 150000; char *big = malloc((size_t)big_len); assert(big); for (int i = 0; i < big_len; i++) big[i] = (char)('A' + (i % 26)); - term_hist_push_ascii(&h, big, big_len, NULL, false); + wsap_vtcore_hist_push_ascii(&h, big, big_len, NULL, false); assert(lines(&h) == 1); - assert(term_hist_line_rows(&h, 0, 1000) == 150); + assert(wsap_vtcore_hist_line_rows(&h, 0, 1000) == 150); for (int s = 0; s < 150; s++) { - assert(term_hist_decode_segment(&h, 0, s, 1000, out, NULL) == 1000); + assert(wsap_vtcore_hist_decode_segment(&h, 0, s, 1000, out, NULL) == 1000); for (int x = 0; x < 1000; x++) assert(out[x].c == (uint32_t)big[s * 1000 + x]); } free(big); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_page_limits(void) @@ -420,143 +420,143 @@ static void test_page_limits(void) struct cell out[1000]; /* One page: old lines leave to make room. */ - assert(term_hist_init(&h, 10000, HIST_PAGE_SIZE)); + assert(wsap_vtcore_hist_init(&h, 10000, HIST_PAGE_SIZE)); char line64[64]; memset(line64, 'M', sizeof(line64)); for (int i = 0; i < 1200; i++) - term_hist_push_ascii(&h, line64, sizeof(line64), NULL, false); + wsap_vtcore_hist_push_ascii(&h, line64, sizeof(line64), NULL, false); assert(lines(&h) > 0 && lines(&h) < 1200); - assert(term_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 64, out, NULL) == 64); + assert(wsap_vtcore_hist_decode_segment(&h, hist_end_id(&h) - 1, 0, 64, out, NULL) == 64); assert(out[0].c == 'M'); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); /* A line limit of one keeps the long line as one line. */ - assert(term_hist_init(&h, 1, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 1, 64 * 1024 * 4)); char chunk[1024]; memset(chunk, 'Z', sizeof(chunk)); for (int i = 0; i < 65; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); assert(lines(&h) == 1 && hist_is_open(&h)); - term_hist_push_ascii(&h, "new", 3, NULL, false); - term_hist_push_ascii(&h, "next", 4, NULL, false); + wsap_vtcore_hist_push_ascii(&h, "new", 3, NULL, false); + wsap_vtcore_hist_push_ascii(&h, "next", 4, NULL, false); assert(lines(&h) == 1); - assert(term_hist_decode_segment(&h, hist_first_id(&h), 0, 10, out, NULL) == 4); - term_hist_free(&h); + assert(wsap_vtcore_hist_decode_segment(&h, hist_first_id(&h), 0, 10, out, NULL) == 4); + wsap_vtcore_hist_free(&h); /* A line longer than the arena drops its head but keeps its id. */ - assert(term_hist_init(&h, 10, HIST_PAGE_SIZE)); - term_hist_push_ascii(&h, "PREFIX", 6, NULL, true); + assert(wsap_vtcore_hist_init(&h, 10, HIST_PAGE_SIZE)); + wsap_vtcore_hist_push_ascii(&h, "PREFIX", 6, NULL, true); for (int i = 0; i < 100; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); - term_hist_close_open_line(&h); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); + wsap_vtcore_hist_close_open_line(&h); assert(lines(&h) == 1 && hist_first_id(&h) == 0); - assert(term_hist_line_cells(&h, 0) > 0 && term_hist_line_cells(&h, 0) < 100 * 1024); - assert(term_hist_decode_segment(&h, 0, 0, 6, out, NULL) == 6 && out[0].c == 'Z'); - term_hist_free(&h); + assert(wsap_vtcore_hist_line_cells(&h, 0) > 0 && wsap_vtcore_hist_line_cells(&h, 0) < 100 * 1024); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 6, out, NULL) == 6 && out[0].c == 'Z'); + wsap_vtcore_hist_free(&h); /* A small open line moves to a new page instead of splitting. */ - assert(term_hist_init(&h, 10, HIST_PAGE_SIZE)); + assert(wsap_vtcore_hist_init(&h, 10, HIST_PAGE_SIZE)); for (int i = 0; i < 60; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, false); - term_hist_push_ascii(&h, "PREFIX", 6, NULL, true); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, false); + wsap_vtcore_hist_push_ascii(&h, "PREFIX", 6, NULL, true); for (int i = 0; i < 10; i++) - term_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); - term_hist_close_open_line(&h); + wsap_vtcore_hist_push_ascii(&h, chunk, sizeof(chunk), NULL, true); + wsap_vtcore_hist_close_open_line(&h); uint64_t id = hist_end_id(&h) - 1; - assert(term_hist_decode_segment(&h, id, 0, 6, out, NULL) == 6); + assert(wsap_vtcore_hist_decode_segment(&h, id, 0, 6, out, NULL) == 6); assert(out[0].c == 'P' && out[5].c == 'X'); - assert(term_hist_line_rows(&h, id, 1000) == 11); - term_hist_free(&h); + assert(wsap_vtcore_hist_line_rows(&h, id, 1000) == 11); + wsap_vtcore_hist_free(&h); } static void test_nul_and_wide_pop(void) { struct hist h; struct cell out[8]; - assert(term_hist_init(&h, 10, 64 * 1024)); + assert(wsap_vtcore_hist_init(&h, 10, 64 * 1024)); struct cell nul_row[4] = { dc('A'), dc(0), dc('B'), dc('C') }; - term_hist_push_row(&h, nul_row, 4, false, NULL); - assert(term_hist_decode_segment(&h, 0, 0, 4, out, NULL) == 4); + wsap_vtcore_hist_push_row(&h, nul_row, 4, false, NULL); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 4, out, NULL) == 4); assert(out[0].c == 'A' && out[1].c == ' ' && out[2].c == 'B' && out[3].c == 'C'); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); /* A pop does not split a wide cell. */ - assert(term_hist_init(&h, 10, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 10, 64 * 1024 * 4)); struct cell wide[4] = { dc('A'), dc(0x4E2D), dc(0), dc('B') }; wide[1].flags = CELL_WIDE; wide[2].flags = CELL_TRAIL; - term_hist_push_row(&h, wide, 4, true, NULL); + wsap_vtcore_hist_push_row(&h, wide, 4, true, NULL); struct cell popped[2]; - assert(term_hist_pop_tail_cells(&h, 2, popped, NULL) == 1); + assert(wsap_vtcore_hist_pop_tail_cells(&h, 2, popped, NULL) == 1); assert(popped[0].c == 'B'); - assert(term_hist_decode_segment(&h, 0, 0, 4, out, NULL) == 3); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 4, out, NULL) == 3); assert(out[0].c == 'A' && out[1].c == 0x4E2D && (out[2].flags & CELL_TRAIL)); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } static void test_default_prefix_attributes(void) { struct hist h; - assert(term_hist_init(&h, 100, 64 * 1024 * 4)); + assert(wsap_vtcore_hist_init(&h, 100, 64 * 1024 * 4)); struct cell row[8]; for (int i = 0; i < 8; i++) { row[i] = dc('a' + i); if (i >= 4) { - row[i].fg = term_color_rgb(10, 20, 30); - row[i].bg = term_color_rgb(40, 50, 60); + row[i].fg = wsap_vtcore_color_rgb(10, 20, 30); + row[i].bg = wsap_vtcore_color_rgb(40, 50, 60); row[i].flags = CELL_BOLD; } } - term_hist_push_row(&h, row, 8, false, NULL); + wsap_vtcore_hist_push_row(&h, row, 8, false, NULL); struct cell out[8]; - assert(term_hist_decode_segment(&h, 0, 0, 8, out, NULL) == 8); + assert(wsap_vtcore_hist_decode_segment(&h, 0, 0, 8, out, NULL) == 8); for (int i = 0; i < 8; i++) { assert(out[i].c == (uint32_t)('a' + i)); assert(out[i].fg == row[i].fg && out[i].bg == row[i].bg && out[i].flags == row[i].flags); } struct pen_attr colored = pen_attr_default(); - colored.fg = term_color_rgb(200, 100, 50); - term_hist_push_ascii(&h, "0123", 4, NULL, true); - term_hist_push_ascii(&h, "4567", 4, &colored, false); - assert(term_hist_decode_segment(&h, 1, 0, 8, out, NULL) == 8); + colored.fg = wsap_vtcore_color_rgb(200, 100, 50); + wsap_vtcore_hist_push_ascii(&h, "0123", 4, NULL, true); + wsap_vtcore_hist_push_ascii(&h, "4567", 4, &colored, false); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 8, out, NULL) == 8); for (int i = 0; i < 8; i++) - assert(out[i].fg == (i < 4 ? TERM_COLOR_FG : term_color_rgb(200, 100, 50))); - term_hist_free(&h); + assert(out[i].fg == (i < 4 ? WSAP_VTCORE_COLOR_FG : wsap_vtcore_color_rgb(200, 100, 50))); + wsap_vtcore_hist_free(&h); } static void test_utf8_and_disabled(void) { struct hist h; - assert(term_hist_init(&h, 2, 64 * 1024 * 2)); - term_hist_push_ascii(&h, "first", 5, NULL, false); + assert(wsap_vtcore_hist_init(&h, 2, 64 * 1024 * 2)); + wsap_vtcore_hist_push_ascii(&h, "first", 5, NULL, false); struct cell p1[2] = { dc('A'), dc('B') }; struct cell p2[2] = { dc(0x00e9), dc('C') }; - term_hist_push_row(&h, p1, 2, true, NULL); - term_hist_push_row(&h, p2, 2, false, NULL); + wsap_vtcore_hist_push_row(&h, p1, 2, true, NULL); + wsap_vtcore_hist_push_row(&h, p2, 2, false, NULL); assert(lines(&h) == 2 && hist_first_id(&h) == 0); struct cell out[8]; - assert(term_hist_decode_segment(&h, 1, 0, 8, out, NULL) == 4); + assert(wsap_vtcore_hist_decode_segment(&h, 1, 0, 8, out, NULL) == 4); assert(out[0].c == 'A' && out[1].c == 'B' && out[2].c == 0x00e9 && out[3].c == 'C'); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); - assert(term_hist_init(&h, 0, 0)); - term_hist_push_ascii(&h, "ignored", 7, NULL, false); - term_hist_push_row(&h, p1, 2, false, NULL); - term_hist_push_blank(&h, 3); + assert(wsap_vtcore_hist_init(&h, 0, 0)); + wsap_vtcore_hist_push_ascii(&h, "ignored", 7, NULL, false); + wsap_vtcore_hist_push_row(&h, p1, 2, false, NULL); + wsap_vtcore_hist_push_blank(&h, 3); assert(lines(&h) == 0); - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } /* Random rows of every kind, pushed and compared with a plain copy. */ static void test_fuzz_rows(void) { enum { LIMIT = 40, COLS = 24, ITER = 4000 }; - struct gstore *g = term_gstore_new(NULL); + struct gstore *g = wsap_vtcore_gstore_new(NULL); uint32_t cps[2] = { 'a', 0x0301 }; - uint32_t cluster = term_gstore_intern(g, cps, 2); + uint32_t cluster = wsap_vtcore_gstore_intern(g, cps, 2); struct hist h; - assert(term_hist_init(&h, LIMIT, 64 * 1024 * 2)); + assert(wsap_vtcore_hist_init(&h, LIMIT, 64 * 1024 * 2)); static struct cell ref[LIMIT + 1][COLS * 8]; static int ref_len[LIMIT + 1]; @@ -574,7 +574,7 @@ static void test_fuzz_rows(void) unsigned k = (state >> 16) % 10; struct cell c = dc('a' + (state >> 20) % 26); if (k == 1) - c.fg = term_color_index((int)(state >> 24) % 16); + c.fg = wsap_vtcore_color_index((int)(state >> 24) % 16); if (k == 2) c.flags = CELL_BOLD; if (k == 3) @@ -603,7 +603,7 @@ static void test_fuzz_rows(void) memcpy(&ref[slot][ref_len[slot]], row, (size_t)n * sizeof(row[0])); ref_len[slot] += n; } - term_hist_push_row(&h, row, n, wrapped, g); + wsap_vtcore_hist_push_row(&h, row, n, wrapped, g); open = wrapped; assert(hist_first_id(&h) == ref_first && hist_end_id(&h) == ref_end); } @@ -612,10 +612,10 @@ static void test_fuzz_rows(void) for (uint64_t id = ref_first; id < ref_end; id++) { int slot = (int)(id % (LIMIT + 1)); int want = ref_len[slot]; - assert((int)term_hist_line_cells(&h, id) == want); + assert((int)wsap_vtcore_hist_line_cells(&h, id) == want); if (!want) continue; - assert(term_hist_decode_segment(&h, id, 0, COLS * 8, out, g) == want); + assert(wsap_vtcore_hist_decode_segment(&h, id, 0, COLS * 8, out, g) == want); for (int x = 0; x < want; x++) { const struct cell *a = &ref[slot][x], *b = &out[x]; if (a->flags & CELL_TRAIL) { @@ -623,87 +623,87 @@ static void test_fuzz_rows(void) continue; } assert(a->fg == b->fg && a->flags == b->flags); - if (term_grapheme_is_handle(a->c)) { - uint32_t got[TERM_GRAPHEME_MAX_LEN]; - assert(term_gstore_expand(g, b->c, got, TERM_GRAPHEME_MAX_LEN) == 2 && got[1] == 0x0301); + if (wsap_vtcore_grapheme_is_handle(a->c)) { + uint32_t got[WSAP_VTCORE_GRAPHEME_MAX_LEN]; + assert(wsap_vtcore_gstore_expand(g, b->c, got, WSAP_VTCORE_GRAPHEME_MAX_LEN) == 2 && got[1] == 0x0301); } else { assert(a->c == b->c); } } } - term_hist_free(&h); - term_gstore_free(g); + wsap_vtcore_hist_free(&h); + wsap_vtcore_gstore_free(g); } static void test_large_wide_count(void) { struct hist h; struct hist_view view = {0}; - assert(term_hist_init(&h, 600, 4 * HIST_PAGE_SIZE)); + assert(wsap_vtcore_hist_init(&h, 600, 4 * HIST_PAGE_SIZE)); struct cell row[4] = { dc('A'), dc(0x65e5), dc(0), dc('B') }; row[1].flags = CELL_WIDE; row[2].flags = CELL_TRAIL; for (int i = 0; i < 400; i++) - term_hist_push_row(&h, row, 4, true, NULL); - term_hist_close_open_line(&h); - uint64_t exact = term_hist_rows(&h, 3); - term_hist_prepare_rows(&h, 3); - assert(term_hist_estimated_rows(&h, 3) < exact); - assert(term_hist_view_sync(&view, &h, 3)); - term_hist_view_scroll_to(&view, &h, 3, (struct line_pos){0}, INT_MAX); - term_hist_view_refine(&view, &h, 3, 3); + wsap_vtcore_hist_push_row(&h, row, 4, true, NULL); + wsap_vtcore_hist_close_open_line(&h); + uint64_t exact = wsap_vtcore_hist_rows(&h, 3); + wsap_vtcore_hist_prepare_rows(&h, 3); + assert(wsap_vtcore_hist_estimated_rows(&h, 3) < exact); + assert(wsap_vtcore_hist_view_sync(&view, &h, 3)); + wsap_vtcore_hist_view_scroll_to(&view, &h, 3, (struct line_pos){0}, INT_MAX); + wsap_vtcore_hist_view_refine(&view, &h, 3, 3); assert(exact > 254); - assert(term_hist_estimated_rows(&h, 3) == exact); + assert(wsap_vtcore_hist_estimated_rows(&h, 3) == exact); for (int i = 0; i < 300; i++) - term_hist_push_ascii(&h, "x", 1, NULL, false); - assert(term_hist_estimated_rows(&h, 3) == exact + 300); - assert(term_hist_view_sync(&view, &h, 3)); + wsap_vtcore_hist_push_ascii(&h, "x", 1, NULL, false); + assert(wsap_vtcore_hist_estimated_rows(&h, 3) == exact + 300); + assert(wsap_vtcore_hist_view_sync(&view, &h, 3)); for (int i = 0; i < 300; i++) - term_hist_push_ascii(&h, "x", 1, NULL, false); - assert(term_hist_estimated_rows(&h, 3) == 600); - term_hist_view_free(&view); - term_hist_free(&h); + wsap_vtcore_hist_push_ascii(&h, "x", 1, NULL, false); + assert(wsap_vtcore_hist_estimated_rows(&h, 3) == 600); + wsap_vtcore_hist_view_free(&view); + wsap_vtcore_hist_free(&h); } static void test_view_after_prefix_eviction(void) { struct hist h; struct hist_view view = {0}; - assert(term_hist_init(&h, 10, 2 * HIST_PAGE_SIZE)); + assert(wsap_vtcore_hist_init(&h, 10, 2 * HIST_PAGE_SIZE)); char bytes[1000]; for (int i = 0; i < 100; i++) { memset(bytes, 'A' + i % 26, sizeof(bytes)); - term_hist_push_ascii(&h, bytes, sizeof(bytes), NULL, true); + wsap_vtcore_hist_push_ascii(&h, bytes, sizeof(bytes), NULL, true); } - term_hist_view_scroll_to(&view, &h, 1000, (struct line_pos){0}, 10); + wsap_vtcore_hist_view_scroll_to(&view, &h, 1000, (struct line_pos){0}, 10); struct hist_view_pos pos; struct cell before[1000], after[1000]; - assert(term_hist_view_row_pos(&view, &h, 1000, 3, (struct line_pos){0}, 0, &pos)); - assert(term_hist_decode_segment(&h, pos.id, pos.seg, 1000, before, NULL) == 1000); + assert(wsap_vtcore_hist_view_row_pos(&view, &h, 1000, 3, (struct line_pos){0}, 0, &pos)); + assert(wsap_vtcore_hist_decode_segment(&h, pos.id, pos.seg, 1000, before, NULL) == 1000); for (int i = 100; i < 140; i++) { memset(bytes, 'A' + i % 26, sizeof(bytes)); - term_hist_push_ascii(&h, bytes, sizeof(bytes), NULL, true); - term_hist_view_note_push(&view, &h, 1000); + wsap_vtcore_hist_push_ascii(&h, bytes, sizeof(bytes), NULL, true); + wsap_vtcore_hist_view_note_push(&view, &h, 1000); } - assert(term_hist_line_cells(&h, 0) < 140000); - assert(term_hist_view_row_pos(&view, &h, 1000, 3, (struct line_pos){0}, 0, &pos)); - assert(term_hist_decode_segment(&h, pos.id, pos.seg, 1000, after, NULL) == 1000); + assert(wsap_vtcore_hist_line_cells(&h, 0) < 140000); + assert(wsap_vtcore_hist_view_row_pos(&view, &h, 1000, 3, (struct line_pos){0}, 0, &pos)); + assert(wsap_vtcore_hist_decode_segment(&h, pos.id, pos.seg, 1000, after, NULL) == 1000); for (int i = 0; i < 1000; i++) assert(before[i].c == after[i].c); - term_hist_view_rewrap(&view, &h, 500); - assert(term_hist_view_row_pos(&view, &h, 500, 3, (struct line_pos){0}, 0, &pos)); - assert(term_hist_decode_segment(&h, pos.id, pos.seg, 500, after, NULL) == 500); + wsap_vtcore_hist_view_rewrap(&view, &h, 500); + assert(wsap_vtcore_hist_view_row_pos(&view, &h, 500, 3, (struct line_pos){0}, 0, &pos)); + assert(wsap_vtcore_hist_decode_segment(&h, pos.id, pos.seg, 500, after, NULL) == 500); for (int i = 0; i < 500; i++) assert(before[i].c == after[i].c); - term_hist_view_free(&view); - term_hist_free(&h); + wsap_vtcore_hist_view_free(&view); + wsap_vtcore_hist_free(&h); } static void test_short_lines_after_eviction(void) { struct hist h; - assert(term_hist_init(&h, 64, 64 * 1024 * 4)); - term_hist_prepare_rows(&h, 80); + assert(wsap_vtcore_hist_init(&h, 64, 64 * 1024 * 4)); + wsap_vtcore_hist_prepare_rows(&h, 80); const char text[] = "abc\n\nx\npqrs\n\nz\n"; const int offsets[] = {0, 4, 5, 7, 12, 13}; const int lengths[] = {3, 0, 1, 4, 0, 1}; @@ -713,20 +713,20 @@ static void test_short_lines_after_eviction(void) .ptr = text + offsets[i], .len = (uint16_t)lengths[i], }; for (int pass = 0; pass < 20000; pass++) - term_hist_push_ascii_lines(&h, batch, 6, NULL); + wsap_vtcore_hist_push_ascii_lines(&h, batch, 6, NULL); assert(lines(&h) == 64); - assert(term_hist_rows(&h, 80) == 64); + assert(wsap_vtcore_hist_rows(&h, 80) == 64); for (uint64_t id = hist_first_id(&h); id < hist_end_id(&h); id++) { int k = (int)(id % 6); struct cell out[80]; - assert(term_hist_decode_segment(&h, id, 0, 80, out, NULL) == lengths[k]); + assert(wsap_vtcore_hist_decode_segment(&h, id, 0, 80, out, NULL) == lengths[k]); for (int x = 0; x < lengths[k]; x++) { assert(out[x].c == (uint32_t)text[offsets[k] + x]); - assert(out[x].fg == TERM_COLOR_FG); - assert(out[x].bg == TERM_COLOR_BG); + assert(out[x].fg == WSAP_VTCORE_COLOR_FG); + assert(out[x].bg == WSAP_VTCORE_COLOR_BG); } } - term_hist_free(&h); + wsap_vtcore_hist_free(&h); } int main(void) diff --git a/tests/history_text_test.c b/tests/history_text_test.c index 88ca6aa..4ede890 100644 --- a/tests/history_text_test.c +++ b/tests/history_text_test.c @@ -1,4 +1,4 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include "term_api.h" #include <assert.h> @@ -8,9 +8,9 @@ #include <stdlib.h> #include <string.h> -static struct term *new_term(int cols) +static struct wsap_vtcore *new_term(int cols) { - struct term *term = term_new(&(struct term_options){ + struct wsap_vtcore *term = wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = cols, .y = 2 }, .scrollback = 100, }); @@ -18,12 +18,12 @@ static struct term *new_term(int cols) return term; } -static void feed(struct term *term, const char *text) +static void feed(struct wsap_vtcore *term, const char *text) { - term_feed(term, text, strlen(text), 0); + wsap_vtcore_feed(term, text, strlen(text), 0); } -static void expect_history(struct term *term, int rows, const char *expected) +static void expect_history(struct wsap_vtcore *term, int rows, const char *expected) { char *text = tt_history_text(term, rows); assert(text); @@ -36,13 +36,13 @@ static void expect_history(struct term *term, int rows, const char *expected) static void unicode_and_selection(void) { - struct term *term = new_term(16); + struct wsap_vtcore *term = new_term(16); expect_history(term, 100, ""); feed(term, "é👩💻界\r\nnext\r\nlast"); expect_history(term, 100, "é👩💻界\n"); expect_history(term, 0, ""); - term_select_start(term, (struct term_vector2i){0}, false, TERM_SELECT_CELL); - term_select_extend(term, (struct term_vector2i){ .x = 4 }, false); + wsap_vtcore_select_start(term, (struct wsap_vtcore_vector2i){0}, false, WSAP_VTCORE_SELECT_CELL); + wsap_vtcore_select_extend(term, (struct wsap_vtcore_vector2i){ .x = 4 }, false); char *before = tt_selection_text(term); assert(before); expect_history(term, 100, "é👩💻界\n"); @@ -54,41 +54,41 @@ static void unicode_and_selection(void) expect_history(term, 100, ""); feed(term, "\033[?1049l"); expect_history(term, 100, "é👩💻界\n"); - term_free(term); + wsap_vtcore_free(term); } static void limits_and_scrolled_view(void) { - struct term *term = new_term(8); + struct wsap_vtcore *term = new_term(8); feed(term, "one\r\ntwo\r\nthree\r\nfour\r\nfive"); expect_history(term, 100, "one\ntwo\nthree\n"); expect_history(term, 2, "two\nthree\n"); - term_scroll(term, 2); + wsap_vtcore_scroll(term, 2); expect_history(term, 100, "one\n"); - term_scroll(term, 100); + wsap_vtcore_scroll(term, 100); expect_history(term, 100, ""); - term_scroll_to(term, 0); - assert(term_resize(term, (struct term_vector2i){ .x = 12, .y = 2 })); + wsap_vtcore_scroll_to(term, 0); + assert(wsap_vtcore_resize(term, (struct wsap_vtcore_vector2i){ .x = 12, .y = 2 })); expect_history(term, 100, "one\ntwo\nthree\n"); - term_free(term); + wsap_vtcore_free(term); } static void wrapped_rows(void) { - struct term *term = new_term(4); + struct wsap_vtcore *term = new_term(4); feed(term, "abcdefghi\r\nx\r\ny"); expect_history(term, 100, "abcdefghi\n"); expect_history(term, 2, "efghi\n"); - term_free(term); + wsap_vtcore_free(term); term = new_term(4); feed(term, "abcdefghijklm"); expect_history(term, 100, "abcdefgh"); - term_free(term); + wsap_vtcore_free(term); } struct writer { - struct term *term; + struct wsap_vtcore *term; _Atomic bool done; }; @@ -106,7 +106,7 @@ static void *write_history(void *userdata) static void concurrent_history(void) { - struct term *term = new_term(16); + struct wsap_vtcore *term = new_term(16); struct writer writer = { .term = term }; pthread_t thread; assert(pthread_create(&thread, NULL, write_history, &writer) == 0); @@ -121,7 +121,7 @@ static void concurrent_history(void) free(text); } while (!atomic_load(&writer.done)); assert(pthread_join(thread, NULL) == 0); - term_free(term); + wsap_vtcore_free(term); } int main(void) diff --git a/tests/input_test.c b/tests/input_test.c index e3a6b8b..59223d2 100644 --- a/tests/input_test.c +++ b/tests/input_test.c @@ -1,29 +1,29 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static struct term_keyboard_state st; -static struct term_modes m; +static struct wsap_vtcore_keyboard_state st; +static struct wsap_vtcore_modes m; static char out[128]; static size_t out_len; static void mode(unsigned kitty_flags) { - st = (struct term_keyboard_state){0}; - m = (struct term_modes){ .keyboard = kitty_flags, .grid = { .x = 80, .y = 24 } }; + st = (struct wsap_vtcore_keyboard_state){0}; + m = (struct wsap_vtcore_modes){ .keyboard = kitty_flags, .grid = { .x = 80, .y = 24 } }; } -static void enc(struct term_key_event ev) +static void enc(struct wsap_vtcore_key_event ev) { - if (!ev.action) ev.action = TERM_KEY_PRESS; - term_keyboard_update(&st, &ev); - struct term_input_result r = - term_input_encode_key(&st, &ev, &m, out, sizeof(out)); + if (!ev.action) ev.action = WSAP_VTCORE_KEY_PRESS; + wsap_vtcore_keyboard_update(&st, &ev); + struct wsap_vtcore_input_result r = + wsap_vtcore_input_encode_key(&st, &ev, &m, out, sizeof(out)); out_len = r.len; } -#define K(...) enc((struct term_key_event){ __VA_ARGS__ }) +#define K(...) enc((struct wsap_vtcore_key_event){ __VA_ARGS__ }) static void typed(uint32_t cp, unsigned mods) { @@ -31,16 +31,16 @@ static void typed(uint32_t cp, unsigned mods) } static bool consumed; -static void enc_mouse(struct term_mouse_event ev) +static void enc_mouse(struct wsap_vtcore_mouse_event ev) { if (ev.pixel.x == 0 && ev.pixel.y == 0) ev.pixel = ev.pos; - struct term_input_result r = - term_input_encode_mouse(&ev, &m, out, sizeof(out)); + struct wsap_vtcore_input_result r = + wsap_vtcore_input_encode_mouse(&ev, &m, out, sizeof(out)); out_len = r.len; - consumed = r.status != TERM_INPUT_UNHANDLED; + consumed = r.status != WSAP_VTCORE_INPUT_UNHANDLED; } -#define MOUSE(x_, y_, ...) enc_mouse((struct term_mouse_event){ .pos = { .x = (x_), .y = (y_) }, __VA_ARGS__ }) +#define MOUSE(x_, y_, ...) enc_mouse((struct wsap_vtcore_mouse_event){ .pos = { .x = (x_), .y = (y_) }, __VA_ARGS__ }) static void expect_at(const char *s, int line) { @@ -55,343 +55,343 @@ static void expect_at(const char *s, int line) int main(void) { mode(0); - K(.key = TERM_KEY_UP); expect("\033[A"); - K(.key = TERM_KEY_HOME); expect("\033[H"); - K(.key = TERM_KEY_DELETE); expect("\033[3~"); - K(.key = TERM_KEY_PAGE_UP); expect("\033[5~"); - K(.key = TERM_KEY_F1); expect("\033OP"); - K(.key = TERM_KEY_F5); expect("\033[15~"); - K(.key = TERM_KEY_F12); expect("\033[24~"); - K(.key = TERM_KEY_RETURN); expect("\r"); - K(.key = TERM_KEY_ESCAPE); expect("\033"); - K(.key = TERM_KEY_TAB); expect("\t"); - K(.key = TERM_KEY_TAB, .mods = TERM_MOD_SHIFT); expect("\033[Z"); - K(.key = TERM_KEY_BACKSPACE); expect("\177"); - K(.key = TERM_KEY_RIGHT, .mods = TERM_MOD_CTRL); expect("\033[1;5C"); - K(.key = TERM_KEY_F5, .mods = TERM_MOD_SHIFT); expect("\033[15;2~"); - K(.key = TERM_KEY_DELETE, .mods = TERM_MOD_CTRL); expect("\033[3;5~"); + K(.key = WSAP_VTCORE_KEY_UP); expect("\033[A"); + K(.key = WSAP_VTCORE_KEY_HOME); expect("\033[H"); + K(.key = WSAP_VTCORE_KEY_DELETE); expect("\033[3~"); + K(.key = WSAP_VTCORE_KEY_PAGE_UP); expect("\033[5~"); + K(.key = WSAP_VTCORE_KEY_F1); expect("\033OP"); + K(.key = WSAP_VTCORE_KEY_F5); expect("\033[15~"); + K(.key = WSAP_VTCORE_KEY_F12); expect("\033[24~"); + K(.key = WSAP_VTCORE_KEY_RETURN); expect("\r"); + K(.key = WSAP_VTCORE_KEY_ESCAPE); expect("\033"); + K(.key = WSAP_VTCORE_KEY_TAB); expect("\t"); + K(.key = WSAP_VTCORE_KEY_TAB, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[Z"); + K(.key = WSAP_VTCORE_KEY_BACKSPACE); expect("\177"); + K(.key = WSAP_VTCORE_KEY_RIGHT, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[1;5C"); + K(.key = WSAP_VTCORE_KEY_F5, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[15;2~"); + K(.key = WSAP_VTCORE_KEY_DELETE, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[3;5~"); m.backarrow_bs = true; - K(.key = TERM_KEY_BACKSPACE); expect("\010"); + K(.key = WSAP_VTCORE_KEY_BACKSPACE); expect("\010"); m.backarrow_bs = false; m.app_cursor = true; - K(.key = TERM_KEY_UP); expect("\033OA"); - K(.key = TERM_KEY_END); expect("\033OF"); + K(.key = WSAP_VTCORE_KEY_UP); expect("\033OA"); + K(.key = WSAP_VTCORE_KEY_END); expect("\033OF"); - K(.key = TERM_KEY_UP, .mods = TERM_MOD_CTRL); expect("\033[1;5A"); + K(.key = WSAP_VTCORE_KEY_UP, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[1;5A"); m.app_cursor = false; typed('a', 0); expect("a"); typed(0x00E9, 0); expect("\xc3\xa9"); K(.codepoint = 'a', .shifted = 'A', .base = 'a', .text = 'A', - .mods = TERM_MOD_SHIFT); expect("A"); - K(.action = TERM_KEY_RELEASE, .codepoint = 'a', .text = 'a'); expect(""); + .mods = WSAP_VTCORE_MOD_SHIFT); expect("A"); + K(.action = WSAP_VTCORE_KEY_RELEASE, .codepoint = 'a', .text = 'a'); expect(""); - typed('c', TERM_MOD_CTRL); expect("\003"); - typed('a', TERM_MOD_CTRL); expect("\001"); - typed('\\', TERM_MOD_CTRL); expect("\034"); - typed(' ', TERM_MOD_CTRL); assert(out_len == 1 && out[0] == 0); + typed('c', WSAP_VTCORE_MOD_CTRL); expect("\003"); + typed('a', WSAP_VTCORE_MOD_CTRL); expect("\001"); + typed('\\', WSAP_VTCORE_MOD_CTRL); expect("\034"); + typed(' ', WSAP_VTCORE_MOD_CTRL); assert(out_len == 1 && out[0] == 0); K(.codepoint = '2', .shifted = '@', .base = '2', .text = '@', - .mods = TERM_MOD_CTRL | TERM_MOD_SHIFT); + .mods = WSAP_VTCORE_MOD_CTRL | WSAP_VTCORE_MOD_SHIFT); assert(out_len == 1 && out[0] == 0); - typed('b', TERM_MOD_ALT); expect("\033b"); - typed('b', TERM_MOD_ALT | TERM_MOD_CTRL); expect("\033\002"); - K(.key = TERM_KEY_BACKSPACE, .mods = TERM_MOD_ALT); expect("\033\177"); - K(.key = TERM_KEY_RETURN, .mods = TERM_MOD_ALT); expect("\033\r"); - K(.key = TERM_KEY_TAB, .mods = TERM_MOD_ALT); expect("\033\t"); - K(.key = TERM_KEY_TAB, .mods = TERM_MOD_ALT | TERM_MOD_SHIFT); expect("\033[Z"); - K(.key = TERM_KEY_ESCAPE, .mods = TERM_MOD_ALT); expect("\033"); + typed('b', WSAP_VTCORE_MOD_ALT); expect("\033b"); + typed('b', WSAP_VTCORE_MOD_ALT | WSAP_VTCORE_MOD_CTRL); expect("\033\002"); + K(.key = WSAP_VTCORE_KEY_BACKSPACE, .mods = WSAP_VTCORE_MOD_ALT); expect("\033\177"); + K(.key = WSAP_VTCORE_KEY_RETURN, .mods = WSAP_VTCORE_MOD_ALT); expect("\033\r"); + K(.key = WSAP_VTCORE_KEY_TAB, .mods = WSAP_VTCORE_MOD_ALT); expect("\033\t"); + K(.key = WSAP_VTCORE_KEY_TAB, .mods = WSAP_VTCORE_MOD_ALT | WSAP_VTCORE_MOD_SHIFT); expect("\033[Z"); + K(.key = WSAP_VTCORE_KEY_ESCAPE, .mods = WSAP_VTCORE_MOD_ALT); expect("\033"); - K(.key = TERM_KEY_LEFT, .mods = TERM_MOD_ALT); expect("\033[1;3D"); + K(.key = WSAP_VTCORE_KEY_LEFT, .mods = WSAP_VTCORE_MOD_ALT); expect("\033[1;3D"); { char b_null[16]; - struct term_input_result r = term_input_encode_key( + struct wsap_vtcore_input_result r = wsap_vtcore_input_encode_key( NULL, - &(struct term_key_event){ .key = TERM_KEY_UP, .action = TERM_KEY_PRESS }, - &(struct term_modes){0}, + &(struct wsap_vtcore_key_event){ .key = WSAP_VTCORE_KEY_UP, .action = WSAP_VTCORE_KEY_PRESS }, + &(struct wsap_vtcore_modes){0}, b_null, sizeof(b_null)); - assert(r.status == TERM_INPUT_BYTES && r.len == 3 && !memcmp(b_null, "\033[A", 3)); + assert(r.status == WSAP_VTCORE_INPUT_BYTES && r.len == 3 && !memcmp(b_null, "\033[A", 3)); } K(.codepoint = 'b', .base = 'b', .text = 0x222B, .text_deferred = true); expect(""); - K(.key = TERM_KEY_KP_DELETE, .keypad = TERM_KEY_KP_DECIMAL); expect("\033[3~"); - K(.key = TERM_KEY_KP_ENTER, .keypad = TERM_KEY_KP_ENTER); expect("\r"); - K(.key = TERM_KEY_KP_LEFT, .keypad = TERM_KEY_KP_4); expect("\033[D"); + K(.key = WSAP_VTCORE_KEY_KP_DELETE, .keypad = WSAP_VTCORE_KEY_KP_DECIMAL); expect("\033[3~"); + K(.key = WSAP_VTCORE_KEY_KP_ENTER, .keypad = WSAP_VTCORE_KEY_KP_ENTER); expect("\r"); + K(.key = WSAP_VTCORE_KEY_KP_LEFT, .keypad = WSAP_VTCORE_KEY_KP_4); expect("\033[D"); m.app_keypad = true; - K(.key = TERM_KEY_KP_END, .keypad = TERM_KEY_KP_1); expect("\033Oq"); - K(.key = TERM_KEY_KP_ENTER, .keypad = TERM_KEY_KP_ENTER); expect("\033OM"); - K(.key = TERM_KEY_KP_ADD, .keypad = TERM_KEY_KP_ADD); expect("\033Ok"); + K(.key = WSAP_VTCORE_KEY_KP_END, .keypad = WSAP_VTCORE_KEY_KP_1); expect("\033Oq"); + K(.key = WSAP_VTCORE_KEY_KP_ENTER, .keypad = WSAP_VTCORE_KEY_KP_ENTER); expect("\033OM"); + K(.key = WSAP_VTCORE_KEY_KP_ADD, .keypad = WSAP_VTCORE_KEY_KP_ADD); expect("\033Ok"); m.app_keypad = false; mode(1); - K(.key = TERM_KEY_ESCAPE); expect("\033[27u"); - K(.key = TERM_KEY_DELETE); expect("\033[3~"); - K(.key = TERM_KEY_F3); expect("\033[13~"); - K(.key = TERM_KEY_KP_ENTER, .keypad = TERM_KEY_KP_ENTER); expect("\033[57414u"); - typed('i', TERM_MOD_CTRL); expect("\033[105;5u"); - K(.key = TERM_KEY_RETURN, .mods = TERM_MOD_CTRL); expect("\033[13;5u"); + K(.key = WSAP_VTCORE_KEY_ESCAPE); expect("\033[27u"); + K(.key = WSAP_VTCORE_KEY_DELETE); expect("\033[3~"); + K(.key = WSAP_VTCORE_KEY_F3); expect("\033[13~"); + K(.key = WSAP_VTCORE_KEY_KP_ENTER, .keypad = WSAP_VTCORE_KEY_KP_ENTER); expect("\033[57414u"); + typed('i', WSAP_VTCORE_MOD_CTRL); expect("\033[105;5u"); + K(.key = WSAP_VTCORE_KEY_RETURN, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[13;5u"); typed('a', 0); expect("a"); - K(.key = TERM_KEY_RETURN); expect("\r"); + K(.key = WSAP_VTCORE_KEY_RETURN); expect("\r"); - K(.key = TERM_KEY_UP, .action = TERM_KEY_RELEASE); expect(""); - K(.key = TERM_KEY_LSHIFT); expect(""); + K(.key = WSAP_VTCORE_KEY_UP, .action = WSAP_VTCORE_KEY_RELEASE); expect(""); + K(.key = WSAP_VTCORE_KEY_LSHIFT); expect(""); mode(1 | 4); K(.codepoint = 'a', .shifted = 'A', .base = 'a', .text = 'A', - .mods = TERM_MOD_CTRL | TERM_MOD_SHIFT); expect("\033[97:65;6u"); + .mods = WSAP_VTCORE_MOD_CTRL | WSAP_VTCORE_MOD_SHIFT); expect("\033[97:65;6u"); mode(1 | 2 | 8); - K(.key = TERM_KEY_ESCAPE); expect("\033[27;1u"); - K(.key = TERM_KEY_ESCAPE, .action = TERM_KEY_REPEAT); expect("\033[27;1:2u"); - K(.key = TERM_KEY_ESCAPE, .action = TERM_KEY_RELEASE); expect("\033[27;1:3u"); - K(.key = TERM_KEY_UP, .action = TERM_KEY_REPEAT); expect("\033[1;1:2A"); + K(.key = WSAP_VTCORE_KEY_ESCAPE); expect("\033[27;1u"); + K(.key = WSAP_VTCORE_KEY_ESCAPE, .action = WSAP_VTCORE_KEY_REPEAT); expect("\033[27;1:2u"); + K(.key = WSAP_VTCORE_KEY_ESCAPE, .action = WSAP_VTCORE_KEY_RELEASE); expect("\033[27;1:3u"); + K(.key = WSAP_VTCORE_KEY_UP, .action = WSAP_VTCORE_KEY_REPEAT); expect("\033[1;1:2A"); mode(31); K(.codepoint = 1092, .base = 'a', .text = 1092); expect("\033[1092::97;1;1092u"); K(.codepoint = 'a', .shifted = 'A', .base = 'a', .text = 'A', - .mods = TERM_MOD_SHIFT); expect("\033[97:65;2;65u"); + .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[97:65;2;65u"); - K(.action = TERM_KEY_RELEASE, .codepoint = 'a', .base = 'a', .text = 'a'); + K(.action = WSAP_VTCORE_KEY_RELEASE, .codepoint = 'a', .base = 'a', .text = 'a'); expect("\033[97;1:3u"); mode(1 | 2 | 8); - K(.key = TERM_KEY_LSHIFT, .mods = TERM_MOD_SHIFT); expect("\033[57441;2u"); - K(.key = TERM_KEY_RSHIFT, .mods = TERM_MOD_SHIFT); expect("\033[57447;2u"); - K(.key = TERM_KEY_LSHIFT, .action = TERM_KEY_RELEASE, .mods = TERM_MOD_SHIFT); + K(.key = WSAP_VTCORE_KEY_LSHIFT, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[57441;2u"); + K(.key = WSAP_VTCORE_KEY_RSHIFT, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[57447;2u"); + K(.key = WSAP_VTCORE_KEY_LSHIFT, .action = WSAP_VTCORE_KEY_RELEASE, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[57441;2:3u"); - K(.key = TERM_KEY_RSHIFT, .action = TERM_KEY_RELEASE, .mods = TERM_MOD_SHIFT); + K(.key = WSAP_VTCORE_KEY_RSHIFT, .action = WSAP_VTCORE_KEY_RELEASE, .mods = WSAP_VTCORE_MOD_SHIFT); expect("\033[57447;1:3u"); - K(.key = TERM_KEY_ISO_LEVEL3_SHIFT); expect("\033[57453;1u"); - K(.key = TERM_KEY_ISO_LEVEL5_SHIFT); expect("\033[57454;1u"); - K(.key = TERM_KEY_CAPS_LOCK); expect("\033[57358;65u"); + K(.key = WSAP_VTCORE_KEY_ISO_LEVEL3_SHIFT); expect("\033[57453;1u"); + K(.key = WSAP_VTCORE_KEY_ISO_LEVEL5_SHIFT); expect("\033[57454;1u"); + K(.key = WSAP_VTCORE_KEY_CAPS_LOCK); expect("\033[57358;65u"); mode(1 | 2 | 4); - K(.key = TERM_KEY_CAPS_LOCK); expect(""); - K(.key = TERM_KEY_CAPS_LOCK, .action = TERM_KEY_RELEASE); expect(""); + K(.key = WSAP_VTCORE_KEY_CAPS_LOCK); expect(""); + K(.key = WSAP_VTCORE_KEY_CAPS_LOCK, .action = WSAP_VTCORE_KEY_RELEASE); expect(""); mode(1 | 2 | 4 | 8); - K(.key = TERM_KEY_CAPS_LOCK); expect("\033[57358;65u"); - K(.key = TERM_KEY_CAPS_LOCK, .action = TERM_KEY_RELEASE, - .mods = TERM_MOD_CAPS); expect("\033[57358;65:3u"); + K(.key = WSAP_VTCORE_KEY_CAPS_LOCK); expect("\033[57358;65u"); + K(.key = WSAP_VTCORE_KEY_CAPS_LOCK, .action = WSAP_VTCORE_KEY_RELEASE, + .mods = WSAP_VTCORE_MOD_CAPS); expect("\033[57358;65:3u"); mode(1); - K(.key = TERM_KEY_LEFT, .mods = TERM_MOD_NUM); expect("\033[1;129D"); - K(.key = TERM_KEY_LEFT); expect("\033[D"); - K(.key = TERM_KEY_F1, .mods = TERM_MOD_CAPS); expect("\033[1;65P"); - K(.codepoint = 'a', .base = 'a', .mods = TERM_MOD_CTRL | TERM_MOD_CAPS); + K(.key = WSAP_VTCORE_KEY_LEFT, .mods = WSAP_VTCORE_MOD_NUM); expect("\033[1;129D"); + K(.key = WSAP_VTCORE_KEY_LEFT); expect("\033[D"); + K(.key = WSAP_VTCORE_KEY_F1, .mods = WSAP_VTCORE_MOD_CAPS); expect("\033[1;65P"); + K(.codepoint = 'a', .base = 'a', .mods = WSAP_VTCORE_MOD_CTRL | WSAP_VTCORE_MOD_CAPS); expect("\033[97;69u"); - K(.codepoint = 'a', .base = 'a', .mods = TERM_MOD_CTRL); + K(.codepoint = 'a', .base = 'a', .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[97;5u"); - K(.codepoint = 'a', .base = 'a', .text = 'A', .mods = TERM_MOD_CAPS); + K(.codepoint = 'a', .base = 'a', .text = 'A', .mods = WSAP_VTCORE_MOD_CAPS); expect("A"); - K(.key = TERM_KEY_RETURN, .mods = TERM_MOD_CAPS); expect("\r"); + K(.key = WSAP_VTCORE_KEY_RETURN, .mods = WSAP_VTCORE_MOD_CAPS); expect("\r"); mode(1 | 8); - K(.codepoint = 'a', .base = 'a', .text = 'A', .mods = TERM_MOD_CAPS); + K(.codepoint = 'a', .base = 'a', .text = 'A', .mods = WSAP_VTCORE_MOD_CAPS); expect("\033[97;65u"); - K(.key = TERM_KEY_RETURN, .mods = TERM_MOD_CAPS); expect("\033[13;65u"); + K(.key = WSAP_VTCORE_KEY_RETURN, .mods = WSAP_VTCORE_MOD_CAPS); expect("\033[13;65u"); mode(0); - K(.key = TERM_KEY_LEFT, .mods = TERM_MOD_NUM); expect("\033[D"); - K(.key = TERM_KEY_F1, .mods = TERM_MOD_CAPS); expect("\033OP"); - K(.codepoint = 'a', .base = 'a', .mods = TERM_MOD_CTRL | TERM_MOD_CAPS); + K(.key = WSAP_VTCORE_KEY_LEFT, .mods = WSAP_VTCORE_MOD_NUM); expect("\033[D"); + K(.key = WSAP_VTCORE_KEY_F1, .mods = WSAP_VTCORE_MOD_CAPS); expect("\033OP"); + K(.codepoint = 'a', .base = 'a', .mods = WSAP_VTCORE_MOD_CTRL | WSAP_VTCORE_MOD_CAPS); expect("\001"); mode(0); - MOUSE(2, 1, .kind = TERM_MOUSE_PRESS); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_PRESS); assert(out_len == 0 && !consumed); - m.mouse = TERM_MOUSE_NORMAL; - MOUSE(2, 1, .kind = TERM_MOUSE_PRESS); expect("\033[M\040\043\042"); - MOUSE(2, 1, .kind = TERM_MOUSE_RELEASE); expect("\033[M\043\043\042"); - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION); expect(""); + m.mouse = WSAP_VTCORE_MOUSE_NORMAL; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_PRESS); expect("\033[M\040\043\042"); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_RELEASE); expect("\033[M\043\043\042"); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION); expect(""); - MOUSE(2, 1, .mods = TERM_MOD_SHIFT); + MOUSE(2, 1, .mods = WSAP_VTCORE_MOD_SHIFT); assert(out_len == 0 && !consumed); - MOUSE(200, 99, .kind = TERM_MOUSE_PRESS); + MOUSE(200, 99, .kind = WSAP_VTCORE_MOUSE_PRESS); assert(out_len == 0 && consumed); - m.mouse_encoding = TERM_MOUSE_ENC_SGR; - MOUSE(2, 1, .kind = TERM_MOUSE_PRESS); expect("\033[<0;3;2M"); - MOUSE(2, 1, .kind = TERM_MOUSE_RELEASE); expect("\033[<0;3;2m"); - MOUSE(2, 1, .mods = TERM_MOD_CTRL); expect("\033[<16;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_WHEEL_UP); expect("\033[<64;3;2M"); - m.mouse_encoding = TERM_MOUSE_ENC_SGR_PIXELS; + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_SGR; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_PRESS); expect("\033[<0;3;2M"); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_RELEASE); expect("\033[<0;3;2m"); + MOUSE(2, 1, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[<16;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_WHEEL_UP); expect("\033[<64;3;2M"); + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS; MOUSE(2, 1, .pixel = { .x = 25, .y = 17 }); expect("\033[<0;26;18M"); - m.mouse_encoding = TERM_MOUSE_ENC_URXVT; - MOUSE(2, 1, .kind = TERM_MOUSE_PRESS); expect("\033[32;3;2M"); - m.mouse_encoding = TERM_MOUSE_ENC_X10; + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_URXVT; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_PRESS); expect("\033[32;3;2M"); + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_X10; - m.mouse = TERM_MOUSE_BUTTON; - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION, .button = TERM_MOUSE_BUTTON_NONE); expect(""); - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION, .button = TERM_MOUSE_BUTTON_PRIMARY); + m.mouse = WSAP_VTCORE_MOUSE_BUTTON; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION, .button = WSAP_VTCORE_MOUSE_BUTTON_NONE); expect(""); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION, .button = WSAP_VTCORE_MOUSE_BUTTON_PRIMARY); expect("\033[M\100\043\042"); - m.mouse_encoding = TERM_MOUSE_ENC_SGR; - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION, .button = TERM_MOUSE_BUTTON_NONE); expect(""); - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION, .button = TERM_MOUSE_BUTTON_PRIMARY, .mods = TERM_MOD_CTRL); + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_SGR; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION, .button = WSAP_VTCORE_MOUSE_BUTTON_NONE); expect(""); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION, .button = WSAP_VTCORE_MOUSE_BUTTON_PRIMARY, .mods = WSAP_VTCORE_MOD_CTRL); expect("\033[<48;3;2M"); - m.mouse = TERM_MOUSE_ANY; - MOUSE(2, 1, .kind = TERM_MOUSE_MOTION, .button = TERM_MOUSE_BUTTON_NONE); expect("\033[<35;3;2M"); - m.mouse_encoding = TERM_MOUSE_ENC_X10; - MOUSE(2, 1, .button = TERM_MOUSE_WHEEL_UP); expect("\033[M\140\043\042"); + m.mouse = WSAP_VTCORE_MOUSE_ANY; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_MOTION, .button = WSAP_VTCORE_MOUSE_BUTTON_NONE); expect("\033[<35;3;2M"); + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_X10; + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_WHEEL_UP); expect("\033[M\140\043\042"); - m.mouse = TERM_MOUSE_X10; - MOUSE(2, 1, .kind = TERM_MOUSE_PRESS); expect("\033[M\040\043\042"); - MOUSE(2, 1, .kind = TERM_MOUSE_RELEASE); expect(""); + m.mouse = WSAP_VTCORE_MOUSE_X10; + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_PRESS); expect("\033[M\040\043\042"); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_RELEASE); expect(""); { - struct term_keyboard_state s2 = {0}; - struct term_modes m2 = { .keyboard = 1 | 2 | 8, .grid = { .x = 80, .y = 24 } }; + struct wsap_vtcore_keyboard_state s2 = {0}; + struct wsap_vtcore_modes m2 = { .keyboard = 1 | 2 | 8, .grid = { .x = 80, .y = 24 } }; char b2[64]; - struct term_key_event sh = { - .key = TERM_KEY_LSHIFT, .action = TERM_KEY_PRESS, - .mods = TERM_MOD_SHIFT, + struct wsap_vtcore_key_event sh = { + .key = WSAP_VTCORE_KEY_LSHIFT, .action = WSAP_VTCORE_KEY_PRESS, + .mods = WSAP_VTCORE_MOD_SHIFT, }; - term_keyboard_update(&s2, &sh); - struct term_key_event rsh = { - .key = TERM_KEY_RSHIFT, .action = TERM_KEY_PRESS, - .mods = TERM_MOD_SHIFT, + wsap_vtcore_keyboard_update(&s2, &sh); + struct wsap_vtcore_key_event rsh = { + .key = WSAP_VTCORE_KEY_RSHIFT, .action = WSAP_VTCORE_KEY_PRESS, + .mods = WSAP_VTCORE_MOD_SHIFT, }; - term_keyboard_update(&s2, &rsh); + wsap_vtcore_keyboard_update(&s2, &rsh); - struct term_key_event rel = { - .key = TERM_KEY_LSHIFT, .action = TERM_KEY_RELEASE, - .mods = TERM_MOD_SHIFT, + struct wsap_vtcore_key_event rel = { + .key = WSAP_VTCORE_KEY_LSHIFT, .action = WSAP_VTCORE_KEY_RELEASE, + .mods = WSAP_VTCORE_MOD_SHIFT, }; - term_keyboard_update(&s2, &rel); - struct term_input_result r = - term_input_encode_key(&s2, &rel, &m2, b2, sizeof(b2)); - assert(r.status == TERM_INPUT_BYTES); + wsap_vtcore_keyboard_update(&s2, &rel); + struct wsap_vtcore_input_result r = + wsap_vtcore_input_encode_key(&s2, &rel, &m2, b2, sizeof(b2)); + assert(r.status == WSAP_VTCORE_INPUT_BYTES); assert(!memcmp(b2, "\033[57441;2:3u", r.len)); - struct term_key_event rrel = { - .key = TERM_KEY_RSHIFT, .action = TERM_KEY_RELEASE, - .mods = TERM_MOD_SHIFT, + struct wsap_vtcore_key_event rrel = { + .key = WSAP_VTCORE_KEY_RSHIFT, .action = WSAP_VTCORE_KEY_RELEASE, + .mods = WSAP_VTCORE_MOD_SHIFT, }; - term_keyboard_update(&s2, &rrel); - r = term_input_encode_key(&s2, &rrel, &m2, b2, sizeof(b2)); + wsap_vtcore_keyboard_update(&s2, &rrel); + r = wsap_vtcore_input_encode_key(&s2, &rrel, &m2, b2, sizeof(b2)); assert(!memcmp(b2, "\033[57447;1:3u", r.len)); } { char tiny[4]; - struct term_input_result r = term_input_encode_key( + struct wsap_vtcore_input_result r = wsap_vtcore_input_encode_key( &st, - &(struct term_key_event){ - .key = TERM_KEY_DELETE, .action = TERM_KEY_PRESS, - .mods = TERM_MOD_CTRL | TERM_MOD_ALT | TERM_MOD_SHIFT, + &(struct wsap_vtcore_key_event){ + .key = WSAP_VTCORE_KEY_DELETE, .action = WSAP_VTCORE_KEY_PRESS, + .mods = WSAP_VTCORE_MOD_CTRL | WSAP_VTCORE_MOD_ALT | WSAP_VTCORE_MOD_SHIFT, }, - &(struct term_modes){ .grid = { .x = 80, .y = 24 } }, + &(struct wsap_vtcore_modes){ .grid = { .x = 80, .y = 24 } }, tiny, sizeof(tiny)); - assert(r.status == TERM_INPUT_BUFFER_FULL && r.len == 0); + assert(r.status == WSAP_VTCORE_INPUT_BUFFER_FULL && r.len == 0); } { - struct term_keyboard_state s5 = {0}; - struct term_key_event bad = { - .key = UINT16_MAX, .action = TERM_KEY_PRESS, + struct wsap_vtcore_keyboard_state s5 = {0}; + struct wsap_vtcore_key_event bad = { + .key = UINT16_MAX, .action = WSAP_VTCORE_KEY_PRESS, }; - term_keyboard_update(&s5, &bad); - assert(!term_keyboard_key_down(&s5, TERM_KEY_LSHIFT)); - struct term_input_result r = - term_input_encode_key(&s5, &bad, &m, out, sizeof(out)); - assert(r.status == TERM_INPUT_UNHANDLED && r.len == 0); - - struct term_key_event bad_kp = { - .key = TERM_KEY_KP_1, .keypad = UINT16_MAX, - .action = TERM_KEY_PRESS, + wsap_vtcore_keyboard_update(&s5, &bad); + assert(!wsap_vtcore_keyboard_key_down(&s5, WSAP_VTCORE_KEY_LSHIFT)); + struct wsap_vtcore_input_result r = + wsap_vtcore_input_encode_key(&s5, &bad, &m, out, sizeof(out)); + assert(r.status == WSAP_VTCORE_INPUT_UNHANDLED && r.len == 0); + + struct wsap_vtcore_key_event bad_kp = { + .key = WSAP_VTCORE_KEY_KP_1, .keypad = UINT16_MAX, + .action = WSAP_VTCORE_KEY_PRESS, }; m.app_keypad = true; - r = term_input_encode_key(&s5, &bad_kp, &m, out, sizeof(out)); + r = wsap_vtcore_input_encode_key(&s5, &bad_kp, &m, out, sizeof(out)); assert(r.len == 0); m.app_keypad = false; } { - struct term_key_event deferred = { - .action = TERM_KEY_PRESS, .codepoint = 'a', .text = 'a', + struct wsap_vtcore_key_event deferred = { + .action = WSAP_VTCORE_KEY_PRESS, .codepoint = 'a', .text = 'a', .text_deferred = true, }; - struct term_input_result r = term_input_encode_key( - &st, &deferred, &(struct term_modes){0}, out, sizeof(out)); - assert(r.status == TERM_INPUT_UNHANDLED && r.len == 0); - struct term_modes kitty = { .keyboard = TERM_KEYBOARD_ALL_KEYS }; - r = term_input_encode_key(&st, &deferred, &kitty, out, sizeof(out)); - assert(r.status == TERM_INPUT_BYTES && r.len == strlen("\033[97u")); + struct wsap_vtcore_input_result r = wsap_vtcore_input_encode_key( + &st, &deferred, &(struct wsap_vtcore_modes){0}, out, sizeof(out)); + assert(r.status == WSAP_VTCORE_INPUT_UNHANDLED && r.len == 0); + struct wsap_vtcore_modes kitty = { .keyboard = WSAP_VTCORE_KEYBOARD_ALL_KEYS }; + r = wsap_vtcore_input_encode_key(&st, &deferred, &kitty, out, sizeof(out)); + assert(r.status == WSAP_VTCORE_INPUT_BYTES && r.len == strlen("\033[97u")); assert(!memcmp(out, "\033[97u", r.len)); - deferred.action = TERM_KEY_RELEASE; - r = term_input_encode_key(&st, &deferred, &kitty, out, sizeof(out)); - assert(r.status == TERM_INPUT_CONSUMED && r.len == 0); + deferred.action = WSAP_VTCORE_KEY_RELEASE; + r = wsap_vtcore_input_encode_key(&st, &deferred, &kitty, out, sizeof(out)); + assert(r.status == WSAP_VTCORE_INPUT_CONSUMED && r.len == 0); } - m.mouse = TERM_MOUSE_ANY; - m.mouse_encoding = TERM_MOUSE_ENC_SGR; - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_1); expect("\033[<128;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_2); expect("\033[<129;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_3); expect("\033[<130;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_4); expect("\033[<131;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_WHEEL_LEFT); expect("\033[<66;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_WHEEL_RIGHT); expect("\033[<67;3;2M"); + m.mouse = WSAP_VTCORE_MOUSE_ANY; + m.mouse_encoding = WSAP_VTCORE_MOUSE_ENC_SGR; + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1); expect("\033[<128;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_2); expect("\033[<129;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_3); expect("\033[<130;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_4); expect("\033[<131;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_WHEEL_LEFT); expect("\033[<66;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_WHEEL_RIGHT); expect("\033[<67;3;2M"); /* Ensure Alt modifier does not collide with extra buttons */ - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_PRIMARY, .mods = TERM_MOD_ALT); expect("\033[<8;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_1, .mods = TERM_MOD_ALT); expect("\033[<136;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_MIDDLE, .mods = TERM_MOD_ALT); expect("\033[<9;3;2M"); - MOUSE(2, 1, .button = TERM_MOUSE_BUTTON_EXTRA_2, .mods = TERM_MOD_ALT); expect("\033[<137;3;2M"); - MOUSE(2, 1, .kind = TERM_MOUSE_RELEASE, .button = TERM_MOUSE_BUTTON_EXTRA_1); expect("\033[<128;3;2m"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_PRIMARY, .mods = WSAP_VTCORE_MOD_ALT); expect("\033[<8;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1, .mods = WSAP_VTCORE_MOD_ALT); expect("\033[<136;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_MIDDLE, .mods = WSAP_VTCORE_MOD_ALT); expect("\033[<9;3;2M"); + MOUSE(2, 1, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_2, .mods = WSAP_VTCORE_MOD_ALT); expect("\033[<137;3;2M"); + MOUSE(2, 1, .kind = WSAP_VTCORE_MOUSE_RELEASE, .button = WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1); expect("\033[<128;3;2m"); { /* A host sizes the paste buffer from the text alone. */ static const char text[] = "ls\r\n\033[31m\u202erm\x7f\t\xe4\xb8\xad"; static const char want[] = "\033[200~ls\r[31mrm\t\xe4\xb8\xad\033[201~"; - char buf[sizeof(text) - 1 + TERM_PASTE_EXTRA]; - struct term_modes bracketed = { .bracketed_paste = true }; - struct term_input_result r = - term_input_encode_paste(&bracketed, text, sizeof(text) - 1, buf, sizeof(buf)); - assert(r.status == TERM_INPUT_BYTES && r.len == sizeof(want) - 1); + char buf[sizeof(text) - 1 + WSAP_VTCORE_PASTE_EXTRA]; + struct wsap_vtcore_modes bracketed = { .bracketed_paste = true }; + struct wsap_vtcore_input_result r = + wsap_vtcore_input_encode_paste(&bracketed, text, sizeof(text) - 1, buf, sizeof(buf)); + assert(r.status == WSAP_VTCORE_INPUT_BYTES && r.len == sizeof(want) - 1); assert(!memcmp(buf, want, r.len)); - r = term_input_encode_paste(&bracketed, text, sizeof(text) - 1, buf, r.len - 1); - assert(r.status == TERM_INPUT_BUFFER_FULL && r.len == 0); + r = wsap_vtcore_input_encode_paste(&bracketed, text, sizeof(text) - 1, buf, r.len - 1); + assert(r.status == WSAP_VTCORE_INPUT_BUFFER_FULL && r.len == 0); - r = term_input_encode_paste(&bracketed, "\033\a\u2066", 5, buf, sizeof(buf)); - assert(r.status == TERM_INPUT_CONSUMED && r.len == 0); + r = wsap_vtcore_input_encode_paste(&bracketed, "\033\a\u2066", 5, buf, sizeof(buf)); + assert(r.status == WSAP_VTCORE_INPUT_CONSUMED && r.len == 0); - struct term_modes plain = {0}; - r = term_input_encode_paste(&plain, "a\nb", 3, buf, 3); - assert(r.status == TERM_INPUT_BYTES && r.len == 3 && !memcmp(buf, "a\rb", 3)); + struct wsap_vtcore_modes plain = {0}; + r = wsap_vtcore_input_encode_paste(&plain, "a\nb", 3, buf, 3); + assert(r.status == WSAP_VTCORE_INPUT_BYTES && r.len == 3 && !memcmp(buf, "a\rb", 3)); } { - mode(TERM_KEYBOARD_ALL_KEYS | TERM_KEYBOARD_EVENT_TYPES); - K(.key = TERM_KEY_NUM_LOCK); expect("\033[57360;129u"); - K(.key = TERM_KEY_NUM_LOCK, .action = TERM_KEY_REPEAT, - .mods = TERM_MOD_NUM); expect("\033[57360;129:2u"); - K(.key = TERM_KEY_NUM_LOCK, .action = TERM_KEY_RELEASE, - .mods = TERM_MOD_NUM); expect("\033[57360;129:3u"); - K(.key = TERM_KEY_NUM_LOCK, .mods = TERM_MOD_NUM); expect("\033[57360;1u"); - K(.key = TERM_KEY_SCROLL_LOCK); expect("\033[57359;1u"); + mode(WSAP_VTCORE_KEYBOARD_ALL_KEYS | WSAP_VTCORE_KEYBOARD_EVENT_TYPES); + K(.key = WSAP_VTCORE_KEY_NUM_LOCK); expect("\033[57360;129u"); + K(.key = WSAP_VTCORE_KEY_NUM_LOCK, .action = WSAP_VTCORE_KEY_REPEAT, + .mods = WSAP_VTCORE_MOD_NUM); expect("\033[57360;129:2u"); + K(.key = WSAP_VTCORE_KEY_NUM_LOCK, .action = WSAP_VTCORE_KEY_RELEASE, + .mods = WSAP_VTCORE_MOD_NUM); expect("\033[57360;129:3u"); + K(.key = WSAP_VTCORE_KEY_NUM_LOCK, .mods = WSAP_VTCORE_MOD_NUM); expect("\033[57360;1u"); + K(.key = WSAP_VTCORE_KEY_SCROLL_LOCK); expect("\033[57359;1u"); } { /* UTF-8 writes must report overflow without crossing the capacity. */ - struct term_key_event key = { .action = TERM_KEY_PRESS, .text = 0x4e2d }; - struct term_mouse_event mouse = { - .kind = TERM_MOUSE_PRESS, .button = TERM_MOUSE_BUTTON_PRIMARY, + struct wsap_vtcore_key_event key = { .action = WSAP_VTCORE_KEY_PRESS, .text = 0x4e2d }; + struct wsap_vtcore_mouse_event mouse = { + .kind = WSAP_VTCORE_MOUSE_PRESS, .button = WSAP_VTCORE_MOUSE_BUTTON_PRIMARY, .pos = { .x = 190, .y = 95 }, }; - struct term_modes modes = { - .mouse = TERM_MOUSE_ANY, .mouse_encoding = TERM_MOUSE_ENC_UTF8, + struct wsap_vtcore_modes modes = { + .mouse = WSAP_VTCORE_MOUSE_ANY, .mouse_encoding = WSAP_VTCORE_MOUSE_ENC_UTF8, .grid = { .x = 256, .y = 128 }, }; static const char *const want[] = { "\xe4\xb8\xad", "\033[M \xc3\x9f\xc2\x80" }; @@ -400,14 +400,14 @@ int main(void) size_t len = strlen(want[which]); for (size_t cap = 0; cap <= len + 1; cap++) { memset(buf, '!', sizeof(buf)); - struct term_input_result r = which == 0 - ? term_input_encode_key(NULL, &key, &modes, buf, cap) - : term_input_encode_mouse(&mouse, &modes, buf, cap); + struct wsap_vtcore_input_result r = which == 0 + ? wsap_vtcore_input_encode_key(NULL, &key, &modes, buf, cap) + : wsap_vtcore_input_encode_mouse(&mouse, &modes, buf, cap); assert(buf[cap] == '!'); if (cap < len) { - assert(r.status == TERM_INPUT_BUFFER_FULL && r.len == 0); + assert(r.status == WSAP_VTCORE_INPUT_BUFFER_FULL && r.len == 0); } else { - assert(r.status == TERM_INPUT_BYTES && r.len == len); + assert(r.status == WSAP_VTCORE_INPUT_BYTES && r.len == len); assert(!memcmp(buf, want[which], len)); } } diff --git a/tests/meson.build b/tests/meson.build index 4fda075..c0a0cd0 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -13,7 +13,7 @@ test_env.set('DYLD_INSERT_LIBRARIES', '') test_env.set('NM', find_program('nm', native: true).full_path()) # [name, sources, dependencies, suites] -term_tests = [ +wsap_vtcore_tests = [ ['unicode-test', files('unicode/unicode_test.c'), [], []], ['term-input-test', files('input_test.c'), [], []], ['term-test', files('term_test.c'), [thread_dep], ['isa']], @@ -34,14 +34,14 @@ term_tests = [ ] test_helpers_inc = include_directories('helpers') -term_test_exes = {} -foreach entry : term_tests +wsap_vtcore_test_exes = {} +foreach entry : wsap_vtcore_tests exe = executable(entry[0], entry[1], c_args: test_c_args, include_directories: test_helpers_inc, - dependencies: [term_internal_dep] + entry[2], + dependencies: [wsap_vtcore_internal_dep] + entry[2], ) - term_test_exes += {entry[0]: exe} + wsap_vtcore_test_exes += {entry[0]: exe} test(entry[0], exe, args: entry[0] == 'write-fuzz-test' ? [get_option('write_fuzz_seeds').to_string()] : [], env: test_env, @@ -56,40 +56,40 @@ if host_machine.cpu_family() == 'x86_64' and cc.get_argument_syntax() == 'gcc' a cc.get_define('__AVX2__', args: get_option('arch_flag') != '' ? [get_option('arch_flag')] : []) == '' foreach level : ['base', 'avx2'] level_env = test_env - level_env.set('TERM_HEADLESS_ISA', level) + level_env.set('WSAP_VTCORE_ISA', level) foreach name : ['term-test', 'spec-test', 'model-test', 'view-test', 'term-input-test', 'hist-test', 'history-text-test'] - test(name + '-' + level, term_test_exes[name], env: level_env, + test(name + '-' + level, wsap_vtcore_test_exes[name], env: level_env, suite: ['unit', 'isa'], timeout: 180) endforeach endforeach endif -# The amalgamation is the core as one term.c, the way a host builds it. The -# tests that use only term.h run again against it. -term_amalgamation = custom_target( +# The amalgamation is the core as one wsap_vtcore.c, the way a host builds +# it. The tests that use only wsap_vtcore.h run again against it. +wsap_vtcore_amalgamation = custom_target( 'term-amalgamation', - output: ['term.c', 'term.h'], + output: ['wsap_vtcore.c', 'wsap_vtcore.h'], depfile: 'term-amalgamation.d', command: [python, files('../tools/amalgamate.py'), meson.project_source_root(), '@OUTDIR@', '@DEPFILE@'], ) -term_amalgamation_lib = static_library( +wsap_vtcore_amalgamation_lib = static_library( 'term-amalgamation', - term_amalgamation[0], + wsap_vtcore_amalgamation[0], dependencies: [m_dep, thread_dep], override_options: ['c_std=c11', 'warning_level=3', 'werror=true'], build_by_default: false, ) -foreach entry : term_tests +foreach entry : wsap_vtcore_tests if entry[0] in ['term-test', 'spec-test', 'view-test', 'dcs-test', 'osc-test', 'history-text-test', 'term-input-test', 'model-test', 'model-row-test', 'resize-property-test', 'api-args-test'] test(entry[0] + '-amalgamation', executable(entry[0] + '-amalgamation', entry[1], c_args: test_c_args, - include_directories: [term_inc, test_helpers_inc], - link_with: term_amalgamation_lib, + include_directories: [wsap_vtcore_inc, test_helpers_inc], + link_with: wsap_vtcore_amalgamation_lib, dependencies: [m_dep, thread_dep] + entry[2], build_by_default: false), env: test_env, suite: ['unit', 'amalgamation'], timeout: 180) @@ -97,9 +97,9 @@ foreach entry : term_tests endforeach test('term-symbols-test', bash, - args: [files('symbols_test.sh'), term_lib.get_static_lib(), - meson.project_source_root() / 'include' / 'term', - term_lib.get_shared_lib()], + args: [files('symbols_test.sh'), wsap_vtcore_lib.get_static_lib(), + meson.project_source_root() / 'include' / 'wsap_vtcore', + wsap_vtcore_lib.get_shared_lib()], env: test_env, suite: 'unit', ) @@ -111,7 +111,7 @@ if cc.has_link_argument('-Wl,--wrap=realloc') and cc.has_link_argument('-Wl,--wr snapshot_failure_test = executable('snapshot-failure-test', 'snapshot_failure_test.c', c_args: test_c_args, link_args: ['-Wl,--wrap=realloc', '-Wl,--wrap=malloc'], - dependencies: [term_internal_dep], + dependencies: [wsap_vtcore_internal_dep], ) test('snapshot-failure-test', snapshot_failure_test, env: test_env, @@ -122,8 +122,8 @@ endif # The project version comes in as a define, so the header macros cannot # drift from meson.build. version_test = executable('version-test', 'version_test.c', - c_args: test_c_args + ['-DTERM_TEST_PROJECT_VERSION="@0@"'.format(meson.project_version())], - dependencies: [term_internal_dep], + c_args: test_c_args + ['-DWSAP_VTCORE_TEST_PROJECT_VERSION="@0@"'.format(meson.project_version())], + dependencies: [wsap_vtcore_internal_dep], ) test('version-test', version_test, env: test_env, @@ -141,10 +141,10 @@ kitty_tests = get_option('kitty').require( host_machine.system() == 'linux' and get_option('b_sanitize') == 'none', error_message: 'The Kitty tests need an unsanitized Linux build', ) -term_kitty_tests = kitty_tests.allowed() -if term_kitty_tests +wsap_vtcore_kitty_tests = kitty_tests.allowed() +if wsap_vtcore_kitty_tests kitty_bridge = shared_library('kitty_bridge', 'extern/kitty/screen_bridge.c', - dependencies: term_internal_dep, + dependencies: wsap_vtcore_internal_dep, ) kitty_env = environment() kitty_env.set('WSAP_KITTY_LIB', kitty_bridge.full_path()) diff --git a/tests/model.c b/tests/model.c index 6c9f288..bd8c6c7 100644 --- a/tests/model.c +++ b/tests/model.c @@ -13,7 +13,7 @@ * current terminal, and the macro names the phase that removes it. */ #include "model.h" -#include "term/unicode/unicode.h" +#include "wsap_vtcore/unicode/unicode.h" #include <limits.h> #include <stdarg.h> @@ -31,10 +31,10 @@ #define STR_KEEP 1024 struct cell { - uint32_t cp[TERM_GRAPHEME_MAX_LEN]; + uint32_t cp[WSAP_VTCORE_GRAPHEME_MAX_LEN]; uint8_t n, width; uint16_t attrs; - term_color fg, bg; + wsap_vtcore_color fg, bg; bool pad; /* the blank that a wide glyph left at a row end */ }; @@ -50,8 +50,8 @@ struct row { }; struct pen { - term_color fg, bg, ul; - uint16_t attrs; /* TERM_ATTR_* style bits and the underline style */ + wsap_vtcore_color fg, bg, ul; + uint16_t attrs; /* WSAP_VTCORE_ATTR_* style bits and the underline style */ bool inverse; }; @@ -99,7 +99,7 @@ struct model { bool tabs[MAX_TABS]; struct keyboard keyboard[2]; /* The last printed glyph, for REP and cluster joins. */ - uint32_t last[TERM_GRAPHEME_MAX_LEN]; + uint32_t last[WSAP_VTCORE_GRAPHEME_MAX_LEN]; int last_n; int prompt; /* screen row of the last OSC 133;A, or -1 */ unsigned flags; @@ -124,14 +124,14 @@ struct model { /* ---- cells and rows ---- */ -static struct cell blank(term_color fg, term_color bg) +static struct cell blank(wsap_vtcore_color fg, wsap_vtcore_color bg) { return (struct cell){ .cp = { ' ' }, .n = 1, .width = 1, .fg = fg, .bg = bg }; } static struct cell default_blank(void) { - return blank(TERM_COLOR_FG, TERM_COLOR_BG); + return blank(WSAP_VTCORE_COLOR_FG, WSAP_VTCORE_COLOR_BG); } static struct row *row_new(int cols) @@ -154,12 +154,12 @@ static void row_cut(struct row *r, int n, int cols) static bool pristine(const struct model *m) { - return m->pen.fg == TERM_COLOR_FG && m->pen.bg == TERM_COLOR_BG; + return m->pen.fg == WSAP_VTCORE_COLOR_FG && m->pen.bg == WSAP_VTCORE_COLOR_BG; } static bool is_ri(uint32_t cp) { - return cp - 0x1F1E6u <= 0x19u && term_grapheme_regional_indicator(cp); + return cp - 0x1F1E6u <= 0x19u && wsap_vtcore_grapheme_regional_indicator(cp); } /* ---- replies ---- */ @@ -185,7 +185,7 @@ static void __attribute__((format(printf, 2, 3))) reply(struct model *m, const c static int history_limit(int requested) { - return requested == 0 ? TERM_SCROLLBACK_DEFAULT : requested < 0 ? 0 : requested; + return requested == 0 ? WSAP_VTCORE_SCROLLBACK_DEFAULT : requested < 0 ? 0 : requested; } static void hist_reflow_tail(struct model *m); @@ -229,7 +229,7 @@ static void hist_push(struct model *m, struct row *r) hist_reflow_tail(m); } -static void term_hist_clear(struct model *m) +static void wsap_vtcore_hist_clear(struct model *m) { for (int i = 0; i < m->hist_len; i++) free(m->hist[i]); m->hist_len = 0; @@ -355,7 +355,7 @@ static int last_text_row(const struct model *m) static void erase_display(struct model *m, int mode) { if (mode == 3) { - term_hist_clear(m); + wsap_vtcore_hist_clear(m); return; } if (mode == 2) { @@ -418,17 +418,17 @@ static void fill_gap(struct row *r, int x) static uint16_t presentation(const uint32_t *cps, int n) { - bool pictographic = term_unicode_extended_pictographic(cps[0]); + bool pictographic = wsap_vtcore_unicode_extended_pictographic(cps[0]); bool emoji = false; for (int i = 1; i < n; i++) { - if (cps[i] == 0xFE0F) return TERM_ATTR_EMOJI; - if (cps[i] == 0xFE0E) return TERM_ATTR_TEXT; - if (cps[i] == 0x20E3 || term_grapheme_regional_indicator(cps[i]) || - (pictographic && (cps[i] == 0x200D || term_grapheme_emoji_modifier(cps[i]) || + if (cps[i] == 0xFE0F) return WSAP_VTCORE_ATTR_EMOJI; + if (cps[i] == 0xFE0E) return WSAP_VTCORE_ATTR_TEXT; + if (cps[i] == 0x20E3 || wsap_vtcore_grapheme_regional_indicator(cps[i]) || + (pictographic && (cps[i] == 0x200D || wsap_vtcore_grapheme_emoji_modifier(cps[i]) || (cps[i] >= 0xE0020 && cps[i] <= 0xE007F)))) emoji = true; } - return emoji ? TERM_ATTR_EMOJI : 0; + return emoji ? WSAP_VTCORE_ATTR_EMOJI : 0; } static void wrap_to_next_row(struct model *m) @@ -443,10 +443,10 @@ static void wrap_to_next_row(struct model *m) static void put_glyph(struct model *m, const uint32_t *cps, int n, uint16_t attrs) { if (n > 1) - attrs = (uint16_t)((attrs & ~(TERM_ATTR_EMOJI | TERM_ATTR_TEXT)) | presentation(cps, n)); - int width = term_unicode_width(cps[0]) == 2 ? 2 : 1; - if (attrs & TERM_ATTR_EMOJI) width = 2; - if (attrs & TERM_ATTR_TEXT) width = 1; + attrs = (uint16_t)((attrs & ~(WSAP_VTCORE_ATTR_EMOJI | WSAP_VTCORE_ATTR_TEXT)) | presentation(cps, n)); + int width = wsap_vtcore_unicode_width(cps[0]) == 2 ? 2 : 1; + if (attrs & WSAP_VTCORE_ATTR_EMOJI) width = 2; + if (attrs & WSAP_VTCORE_ATTR_TEXT) width = 1; if (m->pending) wrap_to_next_row(m); int right = m->cols - 1; struct row *r = m->scr[m->y]; @@ -496,14 +496,14 @@ static void put_glyph(struct model *m, const uint32_t *cps, int n, uint16_t attr static bool joins(uint32_t cp, int width) { if (cp < 0x300) return false; - return width == 0 || term_grapheme_emoji_modifier(cp) || - (width == 1 && term_unicode_spacing_mark(cp)); + return width == 0 || wsap_vtcore_grapheme_emoji_modifier(cp) || + (width == 1 && wsap_vtcore_unicode_spacing_mark(cp)); } static bool cluster_joins(const uint32_t *cps, int n, uint32_t cp, int width) { if (joins(cp, width)) return true; - if (cps[n - 1] == 0x200D) return term_unicode_extended_pictographic(cp); + if (cps[n - 1] == 0x200D) return wsap_vtcore_unicode_extended_pictographic(cp); return n == 1 && is_ri(cp) && is_ri(cps[0]); } @@ -528,10 +528,10 @@ static bool extend_cluster(struct model *m, uint32_t cp, int width) return joins(cp, width); if (!cluster_joins(prev->cp, prev->n, cp, width)) return false; - if (prev->n >= TERM_GRAPHEME_MAX_LEN) + if (prev->n >= WSAP_VTCORE_GRAPHEME_MAX_LEN) return true; struct cell old = *prev; - uint32_t cps[TERM_GRAPHEME_MAX_LEN]; + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN]; memcpy(cps, old.cp, (size_t)old.n * sizeof(*cps)); cps[old.n] = cp; int n = old.n + 1; @@ -542,7 +542,7 @@ static bool extend_cluster(struct model *m, uint32_t cp, int width) m->pending = false; memcpy(m->last, cps, (size_t)n * sizeof(*cps)); m->last_n = n; - put_glyph(m, cps, n, (uint16_t)(old.attrs & ~(TERM_ATTR_EMOJI | TERM_ATTR_TEXT))); + put_glyph(m, cps, n, (uint16_t)(old.attrs & ~(WSAP_VTCORE_ATTR_EMOJI | WSAP_VTCORE_ATTR_TEXT))); r = m->scr[m->y]; x = m->pending ? m->cols - 1 : m->x - 1; if (x > 0 && r->c[x].width == 0) x--; @@ -591,7 +591,7 @@ static void print_cp(struct model *m, uint32_t cp) emit(m, cp); return; } - int width = term_unicode_width(cp); + int width = wsap_vtcore_unicode_width(cp); if (!extend_cluster(m, cp, width)) emit(m, cp); } @@ -655,7 +655,7 @@ static void restore_cursor(struct model *m, const struct saved *s) static struct saved initial_saved(void) { return (struct saved){ - .pen = { .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }, + .pen = { .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }, .g = { 'B', 'B' }, }; } @@ -723,28 +723,28 @@ static void insert_chars(struct model *m, int n) static void pen_reset(struct pen *p) { - *p = (struct pen){ .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG }; + *p = (struct pen){ .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG }; } static void set_underline(uint16_t *attrs, int style) { static const uint16_t flags[] = { - 0, TERM_ATTR_UNDERLINE, TERM_ATTR_DOUBLE_UNDERLINE, - TERM_ATTR_CURLY_UNDERLINE, TERM_ATTR_DOTTED_UNDERLINE, TERM_ATTR_DASHED_UNDERLINE, + 0, WSAP_VTCORE_ATTR_UNDERLINE, WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE, + WSAP_VTCORE_ATTR_CURLY_UNDERLINE, WSAP_VTCORE_ATTR_DOTTED_UNDERLINE, WSAP_VTCORE_ATTR_DASHED_UNDERLINE, }; if ((unsigned)style > 5) style = 1; - *attrs = (uint16_t)((*attrs & ~TERM_ATTR_UNDERLINE_MASK) | flags[style]); + *attrs = (uint16_t)((*attrs & ~WSAP_VTCORE_ATTR_UNDERLINE_MASK) | flags[style]); } /* 38, 48, and 58. Returns the parameters it used after the first. */ -static int extended_color(const struct model *m, int i, term_color *color, bool *ok) +static int extended_color(const struct model *m, int i, wsap_vtcore_color *color, bool *ok) { *ok = false; if (i + 1 >= m->nparam) return 0; if (i + 2 < m->nparam && m->param[i + 1] == 5) { int index = m->param[i + 2]; if (index >= 0 && index <= 255) { - *color = term_color_index(index); + *color = wsap_vtcore_color_index(index); *ok = true; } return 2; @@ -756,7 +756,7 @@ static int extended_color(const struct model *m, int i, term_color *color, bool colon++; int skip = colon >= 4 ? 1 : 0; if (i + 4 + skip >= m->nparam) return 0; - *color = term_color_rgb((uint8_t)m->param[i + 2 + skip], (uint8_t)m->param[i + 3 + skip], + *color = wsap_vtcore_color_rgb((uint8_t)m->param[i + 2 + skip], (uint8_t)m->param[i + 3 + skip], (uint8_t)m->param[i + 4 + skip]); *ok = true; return 4 + skip; @@ -771,13 +771,13 @@ static void sgr(struct model *m) } for (int i = 0; i < m->nparam; i++) { int v = m->param[i]; - term_color color; + wsap_vtcore_color color; bool ok; switch (v) { case 0: pen_reset(p); break; - case 1: p->attrs |= TERM_ATTR_BOLD; break; - case 2: p->attrs |= TERM_ATTR_FAINT; break; - case 3: p->attrs |= TERM_ATTR_ITALIC; break; + case 1: p->attrs |= WSAP_VTCORE_ATTR_BOLD; break; + case 2: p->attrs |= WSAP_VTCORE_ATTR_FAINT; break; + case 3: p->attrs |= WSAP_VTCORE_ATTR_ITALIC; break; case 4: { int style = 1; if (i + 1 < m->nparam && (m->sub & (1u << (i + 1)))) @@ -786,26 +786,26 @@ static void sgr(struct model *m) break; } case 7: p->inverse = true; break; - case 9: p->attrs |= TERM_ATTR_STRIKE; break; + case 9: p->attrs |= WSAP_VTCORE_ATTR_STRIKE; break; case 21: set_underline(&p->attrs, 2); break; - case 22: p->attrs &= (uint16_t)~(TERM_ATTR_BOLD | TERM_ATTR_FAINT); break; - case 23: p->attrs &= (uint16_t)~TERM_ATTR_ITALIC; break; + case 22: p->attrs &= (uint16_t)~(WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_FAINT); break; + case 23: p->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_ITALIC; break; case 24: set_underline(&p->attrs, 0); break; case 27: p->inverse = false; break; - case 29: p->attrs &= (uint16_t)~TERM_ATTR_STRIKE; break; + case 29: p->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_STRIKE; break; case 38: i += extended_color(m, i, &color, &ok); if (ok) p->fg = color; break; - case 39: p->fg = TERM_COLOR_FG; break; + case 39: p->fg = WSAP_VTCORE_COLOR_FG; break; case 48: i += extended_color(m, i, &color, &ok); if (ok) p->bg = color; break; - case 49: p->bg = TERM_COLOR_BG; break; - case 53: p->attrs |= TERM_ATTR_OVERLINE; break; - case 55: p->attrs &= (uint16_t)~TERM_ATTR_OVERLINE; break; + case 49: p->bg = WSAP_VTCORE_COLOR_BG; break; + case 53: p->attrs |= WSAP_VTCORE_ATTR_OVERLINE; break; + case 55: p->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_OVERLINE; break; case 58: i += extended_color(m, i, &color, &ok); if (ok) p->ul = color; break; case 59: p->ul = 0; break; default: - if (v >= 30 && v <= 37) p->fg = term_color_index(v - 30); - else if (v >= 40 && v <= 47) p->bg = term_color_index(v - 40); - else if (v >= 90 && v <= 97) p->fg = term_color_index(v - 90 + 8); - else if (v >= 100 && v <= 107) p->bg = term_color_index(v - 100 + 8); + if (v >= 30 && v <= 37) p->fg = wsap_vtcore_color_index(v - 30); + else if (v >= 40 && v <= 47) p->bg = wsap_vtcore_color_index(v - 40); + else if (v >= 90 && v <= 97) p->fg = wsap_vtcore_color_index(v - 90 + 8); + else if (v >= 100 && v <= 107) p->bg = wsap_vtcore_color_index(v - 100 + 8); break; } } @@ -818,27 +818,27 @@ static void sgr_report(const struct model *m, char *out, size_t cap) size_t n = 0; out[0] = 0; #define ADD(...) do { int k = snprintf(out + n, cap - n, __VA_ARGS__); if (k > 0) n += (size_t)k; } while (0) - int ul = term_attr_underline(p->attrs); - if (!(p->attrs & (TERM_ATTR_BOLD | TERM_ATTR_FAINT | TERM_ATTR_ITALIC | TERM_ATTR_STRIKE | - TERM_ATTR_OVERLINE | TERM_ATTR_UNDERLINE_MASK)) && - !p->inverse && p->fg == TERM_COLOR_FG && p->bg == TERM_COLOR_BG && !p->ul) + int ul = wsap_vtcore_attr_underline(p->attrs); + if (!(p->attrs & (WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_FAINT | WSAP_VTCORE_ATTR_ITALIC | WSAP_VTCORE_ATTR_STRIKE | + WSAP_VTCORE_ATTR_OVERLINE | WSAP_VTCORE_ATTR_UNDERLINE_MASK)) && + !p->inverse && p->fg == WSAP_VTCORE_COLOR_FG && p->bg == WSAP_VTCORE_COLOR_BG && !p->ul) return; ADD("0"); - if (p->attrs & TERM_ATTR_BOLD) ADD(";1"); - if (p->attrs & TERM_ATTR_FAINT) ADD(";2"); - if (p->attrs & TERM_ATTR_ITALIC) ADD(";3"); + if (p->attrs & WSAP_VTCORE_ATTR_BOLD) ADD(";1"); + if (p->attrs & WSAP_VTCORE_ATTR_FAINT) ADD(";2"); + if (p->attrs & WSAP_VTCORE_ATTR_ITALIC) ADD(";3"); if (ul == 1) ADD(";4"); else if (ul) ADD(";4:%d", ul); if (p->inverse) ADD(";7"); - if (p->attrs & TERM_ATTR_STRIKE) ADD(";9"); - if (p->attrs & TERM_ATTR_OVERLINE) ADD(";53"); - const term_color colors[3] = { p->fg, p->bg, p->ul }; - const bool set[3] = { p->fg != TERM_COLOR_FG, p->bg != TERM_COLOR_BG, p->ul != 0 }; + if (p->attrs & WSAP_VTCORE_ATTR_STRIKE) ADD(";9"); + if (p->attrs & WSAP_VTCORE_ATTR_OVERLINE) ADD(";53"); + const wsap_vtcore_color colors[3] = { p->fg, p->bg, p->ul }; + const bool set[3] = { p->fg != WSAP_VTCORE_COLOR_FG, p->bg != WSAP_VTCORE_COLOR_BG, p->ul != 0 }; for (int k = 0; k < 3; k++) { if (!set[k]) continue; int base = 30 + 10 * k; - term_color c = colors[k]; - if (term_color_is_slot(c) && (c & 0x1FFu) < 256) { + wsap_vtcore_color c = colors[k]; + if (wsap_vtcore_color_is_slot(c) && (c & 0x1FFu) < 256) { int i = (int)(c & 0xFFu); if (i < 16 && k < 2) ADD(";%d", i < 8 ? base + i : base + 60 + i - 8); else ADD(";%d:5:%d", base + 8, i); @@ -856,24 +856,24 @@ static void sgr_report(const struct model *m, char *out, size_t cap) static void cara_cell(struct model *m, struct cell *c) { if (m->nparam <= 4) { - c->fg = TERM_COLOR_FG; - c->bg = TERM_COLOR_BG; - c->attrs &= TERM_ATTR_EMOJI | TERM_ATTR_TEXT | TERM_ATTR_LINK; + c->fg = WSAP_VTCORE_COLOR_FG; + c->bg = WSAP_VTCORE_COLOR_BG; + c->attrs &= WSAP_VTCORE_ATTR_EMOJI | WSAP_VTCORE_ATTR_TEXT | WSAP_VTCORE_ATTR_LINK; return; } for (int i = 4; i < m->nparam; i++) { int v = m->param[i]; - term_color color; + wsap_vtcore_color color; bool ok; switch (v) { case 0: - c->fg = TERM_COLOR_FG; - c->bg = TERM_COLOR_BG; - c->attrs &= TERM_ATTR_EMOJI | TERM_ATTR_TEXT | TERM_ATTR_LINK; + c->fg = WSAP_VTCORE_COLOR_FG; + c->bg = WSAP_VTCORE_COLOR_BG; + c->attrs &= WSAP_VTCORE_ATTR_EMOJI | WSAP_VTCORE_ATTR_TEXT | WSAP_VTCORE_ATTR_LINK; break; - case 1: c->attrs |= TERM_ATTR_BOLD; break; - case 2: c->attrs |= TERM_ATTR_FAINT; break; - case 3: c->attrs |= TERM_ATTR_ITALIC; break; + case 1: c->attrs |= WSAP_VTCORE_ATTR_BOLD; break; + case 2: c->attrs |= WSAP_VTCORE_ATTR_FAINT; break; + case 3: c->attrs |= WSAP_VTCORE_ATTR_ITALIC; break; case 4: { int style = 1; if (i + 1 < m->nparam && (m->sub & (1u << (i + 1)))) @@ -881,25 +881,25 @@ static void cara_cell(struct model *m, struct cell *c) set_underline(&c->attrs, style); break; } - case 7: { term_color t = c->fg; c->fg = c->bg; c->bg = t; break; } - case 9: c->attrs |= TERM_ATTR_STRIKE; break; + case 7: { wsap_vtcore_color t = c->fg; c->fg = c->bg; c->bg = t; break; } + case 9: c->attrs |= WSAP_VTCORE_ATTR_STRIKE; break; case 21: set_underline(&c->attrs, 2); break; - case 22: c->attrs &= (uint16_t)~(TERM_ATTR_BOLD | TERM_ATTR_FAINT); break; - case 23: c->attrs &= (uint16_t)~TERM_ATTR_ITALIC; break; + case 22: c->attrs &= (uint16_t)~(WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_FAINT); break; + case 23: c->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_ITALIC; break; case 24: set_underline(&c->attrs, 0); break; - case 29: c->attrs &= (uint16_t)~TERM_ATTR_STRIKE; break; + case 29: c->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_STRIKE; break; case 38: i += extended_color(m, i, &color, &ok); if (ok) c->fg = color; break; - case 39: c->fg = TERM_COLOR_FG; break; + case 39: c->fg = WSAP_VTCORE_COLOR_FG; break; case 48: i += extended_color(m, i, &color, &ok); if (ok) c->bg = color; break; - case 49: c->bg = TERM_COLOR_BG; break; - case 53: c->attrs |= TERM_ATTR_OVERLINE; break; - case 55: c->attrs &= (uint16_t)~TERM_ATTR_OVERLINE; break; + case 49: c->bg = WSAP_VTCORE_COLOR_BG; break; + case 53: c->attrs |= WSAP_VTCORE_ATTR_OVERLINE; break; + case 55: c->attrs &= (uint16_t)~WSAP_VTCORE_ATTR_OVERLINE; break; case 58: i += extended_color(m, i, &color, &ok); break; default: - if (v >= 30 && v <= 37) c->fg = term_color_index(v - 30); - else if (v >= 40 && v <= 47) c->bg = term_color_index(v - 40); - else if (v >= 90 && v <= 97) c->fg = term_color_index(v - 90 + 8); - else if (v >= 100 && v <= 107) c->bg = term_color_index(v - 100 + 8); + if (v >= 30 && v <= 37) c->fg = wsap_vtcore_color_index(v - 30); + else if (v >= 40 && v <= 47) c->bg = wsap_vtcore_color_index(v - 40); + else if (v >= 90 && v <= 97) c->fg = wsap_vtcore_color_index(v - 90 + 8); + else if (v >= 100 && v <= 107) c->bg = wsap_vtcore_color_index(v - 100 + 8); break; } } @@ -1187,7 +1187,7 @@ static void reflow(struct model *m, int cols, int rows) } m->cols = cols; - term_hist_clear(m); + wsap_vtcore_hist_clear(m); for (int i = start - history; i < start; i++) { hist_push(m, r.out[i]); r.out[i] = NULL; @@ -1291,7 +1291,7 @@ static void resize_plain(struct model *m, int cols, int rows) static bool resize(struct model *m, int cols, int rows) { - if (cols > TERM_MAX_COLS) return false; + if (cols > WSAP_VTCORE_MAX_COLS) return false; if (cols == m->cols && rows == m->rows) return true; if (cols > MAX_TABS) return false; m->top = 0; @@ -1352,7 +1352,7 @@ static void soft_reset(struct model *m) m->bracketed = false; m->autowrap = m->visible = true; m->blink = true; - m->style = TERM_CURSOR_BLOCK; + m->style = WSAP_VTCORE_CURSOR_BLOCK; m->top = 0; m->bottom = m->rows - 1; m->decsace = 0; @@ -1630,11 +1630,11 @@ static void csi_dispatch(struct model *m, unsigned char final) } else if (!m->prefix && m->inter == ' ') { int ps = m->nparam ? m->param[0] : 0; if (ps == 0) { - m->style = TERM_CURSOR_BLOCK; + m->style = WSAP_VTCORE_CURSOR_BLOCK; m->blink = true; } else if (ps <= 6) { - m->style = ps < 3 ? TERM_CURSOR_BLOCK : ps < 5 ? TERM_CURSOR_UNDERLINE - : TERM_CURSOR_BAR; + m->style = ps < 3 ? WSAP_VTCORE_CURSOR_BLOCK : ps < 5 ? WSAP_VTCORE_CURSOR_UNDERLINE + : WSAP_VTCORE_CURSOR_BAR; m->blink = ps & 1; } } @@ -1676,8 +1676,8 @@ static void dcs_finish(struct model *m) size_t n = len - 2; char body[256]; if (n == 2 && !memcmp(spec, " q", 2)) { - int shape = m->style == TERM_CURSOR_BLOCK ? (m->blink ? 1 : 2) - : m->style == TERM_CURSOR_UNDERLINE ? (m->blink ? 3 : 4) + int shape = m->style == WSAP_VTCORE_CURSOR_BLOCK ? (m->blink ? 1 : 2) + : m->style == WSAP_VTCORE_CURSOR_UNDERLINE ? (m->blink ? 3 : 4) : (m->blink ? 5 : 6); reply(m, "\033P1$r%d q\033\\", shape); } else if (n == 1 && spec[0] == 'm') { @@ -1779,7 +1779,7 @@ static void control(struct model *m, unsigned char c) case 0x1b: m->state = ESC; break; case '\n': case 0x0b: case 0x0c: m->pending = false; - if (m->lnm || (m->flags & TERM_FEED_ONLCR)) m->x = 0; + if (m->lnm || (m->flags & WSAP_VTCORE_FEED_ONLCR)) m->x = 0; line_feed(m); break; case '\r': m->pending = false; m->x = 0; break; @@ -1972,17 +1972,17 @@ static void feed_byte(struct model *m, unsigned char c) /* ---- public ---- */ -struct model *model_new(struct term_vector2i size, int history, const char *name) +struct model *model_new(struct wsap_vtcore_vector2i size, int history, const char *name) { struct model *m = calloc(1, sizeof(*m)); if (!m) abort(); - snprintf(m->name, sizeof(m->name), "%s", name && *name ? name : "term"); + snprintf(m->name, sizeof(m->name), "%s", name && *name ? name : "wsap_vtcore"); m->cols = size.x < 1 ? 80 : size.x; m->rows = size.y < 1 ? 24 : size.y; m->limit = history_limit(history); m->scr = rows_new(m->rows, m->cols); m->autowrap = m->visible = m->blink = true; - m->style = TERM_CURSOR_BLOCK; + m->style = WSAP_VTCORE_CURSOR_BLOCK; m->bottom = m->rows - 1; m->g[0] = m->g[1] = 'B'; m->saved = initial_saved(); @@ -1998,7 +1998,7 @@ void model_free(struct model *m) if (!m) return; free_rows(m->scr, m->rows); free_rows(m->normal, m->normal_rows); - term_hist_clear(m); + wsap_vtcore_hist_clear(m); free(m->hist); free(m->reply); for (int i = 0; i < m->out_cap; i++) free(m->out[i]); @@ -2012,15 +2012,15 @@ void model_feed(struct model *m, const char *s, size_t len, unsigned flags) for (size_t i = 0; i < len; i++) feed_byte(m, (unsigned char)s[i]); } -bool model_resize(struct model *m, struct term_vector2i size) +bool model_resize(struct model *m, struct wsap_vtcore_vector2i size) { if (size.x < 1 || size.y < 1) return false; return resize(m, size.x, size.y); } -struct term_vector2i model_size(const struct model *m) +struct wsap_vtcore_vector2i model_size(const struct model *m) { - return (struct term_vector2i){ .x = m->cols, .y = m->rows }; + return (struct wsap_vtcore_vector2i){ .x = m->cols, .y = m->rows }; } int model_history(const struct model *m) @@ -2071,22 +2071,22 @@ const struct model_cell *model_row(const struct model *m, int row) return mm->out[row]; } -struct term_cursor model_cursor(const struct model *m) +struct wsap_vtcore_cursor model_cursor(const struct model *m) { - return (struct term_cursor){ + return (struct wsap_vtcore_cursor){ .pos = { .x = m->x, .y = m->y }, - .style = (enum term_cursor_style)m->style, + .style = (enum wsap_vtcore_cursor_style)m->style, .visible = m->visible, .blink = m->blink, }; } -struct term_modes model_modes(const struct model *m) +struct wsap_vtcore_modes model_modes(const struct model *m) { - return (struct term_modes){ + return (struct wsap_vtcore_modes){ .keyboard = m->keyboard[m->alternate].flags, - .mouse = (enum term_mouse)m->mouse, - .mouse_encoding = (enum term_mouse_encoding)m->mouse_enc, + .mouse = (enum wsap_vtcore_mouse)m->mouse, + .mouse_encoding = (enum wsap_vtcore_mouse_encoding)m->mouse_enc, .app_cursor = m->app_cursor, .app_keypad = m->app_keypad, .backarrow_bs = m->backarrow, diff --git a/tests/model.h b/tests/model.h index ca2bf96..be250ef 100644 --- a/tests/model.h +++ b/tests/model.h @@ -3,7 +3,7 @@ /* * A slow reference model of the terminal. It defines correct behavior for - * the input that tests/term/fuzz_gen.h makes. model.c names its sources: + * the input that tests/fuzz_gen.h makes. model.c names its sources: * xterm and ECMA-48 for controls, Unicode for UTF-8, and this terminal's * own design where xterm has no rule (reflow, history, clusters). * @@ -11,39 +11,39 @@ * the public API only. */ -#include "term/term.h" -#include "term/unicode/grapheme.h" +#include "wsap_vtcore/wsap_vtcore.h" +#include "wsap_vtcore/unicode/grapheme.h" #include <stdbool.h> #include <stddef.h> #include <stdint.h> struct model_cell { - uint32_t cp[TERM_GRAPHEME_MAX_LEN]; + uint32_t cp[WSAP_VTCORE_GRAPHEME_MAX_LEN]; uint8_t n; /* code points; 0 for the right half of a wide cell */ uint8_t width; /* 1, 2 for a wide cell, 0 for its right half */ - uint16_t attrs; /* TERM_ATTR_* */ - term_color fg, bg; + uint16_t attrs; /* WSAP_VTCORE_ATTR_* */ + wsap_vtcore_color fg, bg; }; struct model; -/* history is the history limit, as in term_options.scrollback. name is - * as in term_options.name. */ -struct model *model_new(struct term_vector2i size, int history, const char *name); +/* history is the history limit, as in wsap_vtcore_options.scrollback. name is + * as in wsap_vtcore_options.name. */ +struct model *model_new(struct wsap_vtcore_vector2i size, int history, const char *name); void model_free(struct model *m); void model_feed(struct model *m, const char *s, size_t len, unsigned flags); -bool model_resize(struct model *m, struct term_vector2i size); +bool model_resize(struct model *m, struct wsap_vtcore_vector2i size); -struct term_vector2i model_size(const struct model *m); +struct wsap_vtcore_vector2i model_size(const struct model *m); /* History rows. The alternate screen shows no history, so it reports 0. */ int model_history(const struct model *m); /* Row 0 is the oldest history row. Row model_history() is the top screen * row. Return NULL for an invalid row. Different rows can be read together. * A feed or resize ends the lifetime of returned row data. */ const struct model_cell *model_row(const struct model *m, int row); -struct term_cursor model_cursor(const struct model *m); -struct term_modes model_modes(const struct model *m); +struct wsap_vtcore_cursor model_cursor(const struct model *m); +struct wsap_vtcore_modes model_modes(const struct model *m); /* Replies since the last model_take_replies(). */ const char *model_replies(const struct model *m, size_t *len); void model_take_replies(struct model *m); diff --git a/tests/model_row_test.c b/tests/model_row_test.c index ad4ac2c..e204e1f 100644 --- a/tests/model_row_test.c +++ b/tests/model_row_test.c @@ -5,7 +5,7 @@ int main(void) { - struct model *m = model_new((struct term_vector2i){ .x = 10, .y = 3 }, 10, NULL); + struct model *m = model_new((struct wsap_vtcore_vector2i){ .x = 10, .y = 3 }, 10, NULL); model_feed(m, "A\r\nB\r\nC\r\nD", strlen("A\r\nB\r\nC\r\nD"), 0); assert(model_history(m) == 1); assert(model_row(m, -1) == NULL); @@ -21,7 +21,7 @@ int main(void) model_feed(m, "E", 1, 0); assert(model_row(m, 3)[1].cp[0] == 'E'); - assert(model_resize(m, (struct term_vector2i){ .x = 12, .y = 3 })); + assert(model_resize(m, (struct wsap_vtcore_vector2i){ .x = 12, .y = 3 })); assert(model_row(m, 3)[0].cp[0] == 'D'); assert(model_row(m, 3)[1].cp[0] == 'E'); model_free(m); diff --git a/tests/model_test.c b/tests/model_test.c index d3988c6..4f58914 100644 --- a/tests/model_test.c +++ b/tests/model_test.c @@ -17,7 +17,7 @@ */ #include "model.h" #include "fuzz_gen.h" -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <stdio.h> #include <limits.h> @@ -33,11 +33,11 @@ struct event { char *bytes; /* NULL for a resize */ size_t len; unsigned flags; - struct term_vector2i size; + struct wsap_vtcore_vector2i size; }; struct script { - struct term_vector2i size; + struct wsap_vtcore_vector2i size; int history; struct event *ev; int n, cap; @@ -107,10 +107,10 @@ static char glyph(uint32_t cp) } /* Print every retained row of both, side by side. */ -static void dump_all(struct model *m, struct term *t, struct term_snapshot *snap, FILE *log) +static void dump_all(struct model *m, struct wsap_vtcore *t, struct wsap_vtcore_snapshot *snap, FILE *log) { - int total = term_scrollback(t).total, mtotal = model_history(m); - struct term_vector2i size = term_size(t), msize = model_size(m); + int total = wsap_vtcore_scrollback(t).total, mtotal = model_history(m); + struct wsap_vtcore_vector2i size = wsap_vtcore_size(t), msize = model_size(m); int rows = total + size.y > mtotal + msize.y ? total + size.y : mtotal + msize.y; fprintf(log, " term (history %d)%*s model (history %d)\n", total, size.x > 8 ? size.x - 8 : 0, "", mtotal); @@ -118,12 +118,12 @@ static void dump_all(struct model *m, struct term *t, struct term_snapshot *snap fprintf(log, " %3d |", r); if (r < total + size.y) { int offset = r < total ? total - r : 0; - term_scroll_to(t, offset); - term_snapshot_update(snap, t); - const struct term_cell *row = term_snapshot_row(snap, r < total ? 0 : r - total); + wsap_vtcore_scroll_to(t, offset); + wsap_vtcore_snapshot_update(snap, t); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(snap, r < total ? 0 : r - total); for (int x = 0; x < size.x; x++) { - uint32_t cp[TERM_GRAPHEME_MAX_LEN] = {0}; - if (row[x].text) term_snapshot_cluster(snap, row[x].text, cp, TERM_GRAPHEME_MAX_LEN); + uint32_t cp[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + if (row[x].text) wsap_vtcore_snapshot_cluster(snap, row[x].text, cp, WSAP_VTCORE_GRAPHEME_MAX_LEN); fputc(glyph(cp[0]), log); } } else { @@ -136,14 +136,14 @@ static void dump_all(struct model *m, struct term *t, struct term_snapshot *snap } fprintf(log, "|\n"); } - term_scroll_to(t, 0); - struct term_cursor c = term_cursor(t), mc = model_cursor(m); + wsap_vtcore_scroll_to(t, 0); + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t), mc = model_cursor(m); fprintf(log, " cursor term %d,%d model %d,%d\n", c.pos.x, c.pos.y, mc.pos.x, mc.pos.y); } /* Returns NULL when the terminal matches the model, else a description. * Details go to log when it is not NULL. */ -static const char *compare(struct model *m, struct term *t, struct term_snapshot *snap, +static const char *compare(struct model *m, struct wsap_vtcore *t, struct wsap_vtcore_snapshot *snap, struct replies *got, char *why, size_t cap, FILE *log) { size_t want_len; @@ -159,12 +159,12 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot snprintf(why, cap, "replies differ"); return why; } - struct term_vector2i size = term_size(t), msize = model_size(m); + struct wsap_vtcore_vector2i size = wsap_vtcore_size(t), msize = model_size(m); if (size.x != msize.x || size.y != msize.y) { snprintf(why, cap, "size %dx%d, model %dx%d", size.x, size.y, msize.x, msize.y); return why; } - struct term_cursor c = term_cursor(t), mc = model_cursor(m); + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t), mc = model_cursor(m); if (c.pos.x != mc.pos.x || c.pos.y != mc.pos.y || c.style != mc.style || c.visible != mc.visible || c.blink != mc.blink) { snprintf(why, cap, "cursor %d,%d style %d visible %d blink %d; model %d,%d %d %d %d", @@ -172,7 +172,7 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot mc.pos.x, mc.pos.y, mc.style, mc.visible, mc.blink); return why; } - struct term_modes md = term_modes(t), mm = model_modes(m); + struct wsap_vtcore_modes md = wsap_vtcore_modes(t), mm = model_modes(m); if (md.keyboard != mm.keyboard || md.mouse != mm.mouse || md.mouse_encoding != mm.mouse_encoding || md.app_cursor != mm.app_cursor || md.app_keypad != mm.app_keypad || md.backarrow_bs != mm.backarrow_bs || @@ -186,24 +186,24 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot } /* Visit each retained row. Wide-line totals can start as estimates. */ int total = model_history(m); - term_scroll_to(t, 0); - term_scroll(t, INT_MAX); + wsap_vtcore_scroll_to(t, 0); + wsap_vtcore_scroll(t, INT_MAX); for (int offset = total;; offset = offset > size.y ? offset - size.y : 0) { if (!offset) - term_scroll_to(t, 0); - if (!term_snapshot_update(snap, t)) { + wsap_vtcore_scroll_to(t, 0); + if (!wsap_vtcore_snapshot_update(snap, t)) { snprintf(why, cap, "snapshot update failed"); return why; } for (int y = 0; y < size.y; y++) { - const struct term_cell *row = term_snapshot_row(snap, y); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(snap, y); int retained = total - offset + y; const struct model_cell *want_row = model_row(m, retained); for (int x = 0; x < size.x; x++) { const struct model_cell *e = &want_row[x]; - uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0}; - int n = row[x].text ? term_snapshot_cluster(snap, row[x].text, cps, - TERM_GRAPHEME_MAX_LEN) : 0; + uint32_t cps[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; + int n = row[x].text ? wsap_vtcore_snapshot_cluster(snap, row[x].text, cps, + WSAP_VTCORE_GRAPHEME_MAX_LEN) : 0; if (n == e->n && row[x].width == e->width && row[x].attrs == e->attrs && row[x].fg == e->fg && row[x].bg == e->bg && !memcmp(cps, e->cp, (size_t)n * sizeof(*cps))) @@ -211,9 +211,9 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot if (log) { fprintf(log, "retained row %d (offset %d):\n term: ", retained, offset); for (int k = 0; k < size.x; k++) { - uint32_t cp[TERM_GRAPHEME_MAX_LEN] = {0}; + uint32_t cp[WSAP_VTCORE_GRAPHEME_MAX_LEN] = {0}; if (row[k].text) - term_snapshot_cluster(snap, row[k].text, cp, TERM_GRAPHEME_MAX_LEN); + wsap_vtcore_snapshot_cluster(snap, row[k].text, cp, WSAP_VTCORE_GRAPHEME_MAX_LEN); fputc(glyph(cp[0]), log); } fprintf(log, "\n model: "); @@ -228,19 +228,19 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot "model U+%04X (%u cps) w%u attrs %#x fg %#x bg %#x", x, y, cps[0], n, row[x].width, row[x].attrs, row[x].fg, row[x].bg, e->cp[0], e->n, e->width, e->attrs, e->fg, e->bg); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); return why; } } if (!offset) break; - term_scroll(t, -(offset > size.y ? size.y : offset)); + wsap_vtcore_scroll(t, -(offset > size.y ? size.y : offset)); } - int observed_total = term_scrollback(t).total; + int observed_total = wsap_vtcore_scrollback(t).total; if (observed_total != total) { snprintf(why, cap, "visited history %d rows, model %d", observed_total, total); return why; } - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); return NULL; } @@ -251,13 +251,13 @@ static int run(const struct script *s, enum chunking chunks, uint64_t chunk_seed char *why, size_t cap, bool verbose) { struct replies got = {0}; - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = s->size, .scrollback = s->history, .callbacks = { .ud = &got, .reply = on_reply }, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); struct model *m = model_new(s->size, s->history, NULL); - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); if (!t || !snap) abort(); uint64_t saved_rng = rng; rng = chunk_seed | 1; @@ -270,12 +270,12 @@ static int run(const struct script *s, enum chunking chunks, uint64_t chunk_seed size_t n = chunks == CHUNK_WHOLE ? e->len - k : chunks == CHUNK_BYTES ? 1 : 1 + (size_t)rn((int)(e->len - k)); - term_feed(t, e->bytes + k, n, e->flags); + wsap_vtcore_feed(t, e->bytes + k, n, e->flags); k += n; } } else { bool a = model_resize(m, e->size); - bool b = term_resize(t, e->size); + bool b = wsap_vtcore_resize(t, e->size); if (a != b) { snprintf(why, cap, "resize result differs"); bad = i; @@ -291,9 +291,9 @@ static int run(const struct script *s, enum chunking chunks, uint64_t chunk_seed } rng = saved_rng; free(got.s); - term_snapshot_free(snap); + wsap_vtcore_snapshot_free(snap); model_free(m); - term_free(t); + wsap_vtcore_free(t); return bad; } @@ -378,7 +378,7 @@ static int fixed_cases(void) { 8, 3, 5, "abcdefgh\033[3;4H\033[31;1m\0337\033[0m\033[H\0338X" }, { 6, 2, 5, "abcdef\xe3\x80z\xed\xa0\x80\x80" }, }; - static const struct term_vector2i sizes[] = { + static const struct wsap_vtcore_vector2i sizes[] = { { .x = 5, .y = 3 }, { .x = 16, .y = 4 }, { .x = 7, .y = 3 }, { .x = 20, .y = 5 }, { .x = 1, .y = 2 }, { .x = 3, .y = 6 }, }; @@ -419,16 +419,16 @@ int main(int argc, char **argv) .size = { .x = 4 + rn(37), .y = 2 + rn(11) }, .history = limits[rn(4)], }; - struct term_vector2i size = s.size; + struct wsap_vtcore_vector2i size = s.size; for (int step = 0; step < 4; step++) { blen = 0; gen(10 + rn(30), size.x, size.y); put(probe); - unsigned flags = rn(5) == 0 ? TERM_FEED_ONLCR : 0; + unsigned flags = rn(5) == 0 ? WSAP_VTCORE_FEED_ONLCR : 0; script_add(&s, (struct event){ .bytes = dup_bytes(buf, blen), .len = blen, .flags = flags }); if (rn(4) == 0) { - size = (struct term_vector2i){ .x = 1 + rn(44), .y = 1 + rn(14) }; + size = (struct wsap_vtcore_vector2i){ .x = 1 + rn(44), .y = 1 + rn(14) }; script_add(&s, (struct event){ .size = size }); } } diff --git a/tests/osc_test.c b/tests/osc_test.c index 9d08157..66c6303 100644 --- a/tests/osc_test.c +++ b/tests/osc_test.c @@ -1,17 +1,17 @@ #include "term_api.h" -#include "term/unicode/unicode.h" +#include "wsap_vtcore/unicode/unicode.h" #include <assert.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static void write_seq(struct term *t, const char *s) +static void write_seq(struct wsap_vtcore *t, const char *s) { for (; *s; s++) tt_write(t, s, 1); } -static void write_buf(struct term *t, const char *s, size_t len) +static void write_buf(struct wsap_vtcore *t, const char *s, size_t len) { tt_write(t, s, len); } @@ -55,9 +55,9 @@ static void capture_notify(void *ud, const char *t_, const char *b) notify_count++; } -static struct term *osc_test_term(void) +static struct wsap_vtcore *osc_test_term(void) { - struct term *t = tt_new_opts(80, 24, &(struct term_callbacks){ + struct wsap_vtcore *t = tt_new_opts(80, 24, &(struct wsap_vtcore_callbacks){ .reply = capture_reply, .title = capture_title, .clipboard = capture_clip, @@ -69,7 +69,7 @@ static struct term *osc_test_term(void) /* Check the OSC 8 link or the detected URL at a viewport cell. NULL means * no link. */ -static void assert_link(struct term *t, int col, int row, const char *want) +static void assert_link(struct wsap_vtcore *t, int col, int row, const char *want) { char *url = tt_link_at(t, col, row); if (want) @@ -79,13 +79,13 @@ static void assert_link(struct term *t, int col, int row, const char *want) free(url); } -static uint32_t cursor_color(struct term *t) +static uint32_t cursor_color(struct wsap_vtcore *t) { - return term_snapshot_view(tt_snapshot_for(t))->palette[TERM_PALETTE_CURSOR]; + return wsap_vtcore_snapshot_view(tt_snapshot_for(t))->palette[WSAP_VTCORE_PALETTE_CURSOR]; } /* Send a color query and check the reply. */ -static void assert_query(struct term *t, const char *query, const char *want) +static void assert_query(struct wsap_vtcore *t, const char *query, const char *want) { reply[0] = 0; write_seq(t, query); @@ -104,16 +104,16 @@ static void reset_captures(void) notify_count = 0; } -/* The notification default is term_options.name. A DCS +p does not change it. */ +/* The notification default is wsap_vtcore_options.name. A DCS +p does not change it. */ static void test_host_name_notify(void) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = 80, .y = 24 }, .scrollback = TEST_SCROLLBACK, .name = "myterm", .callbacks = { .notify = capture_notify }, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); reset_captures(); write_seq(t, "\033]9;hello\007"); @@ -130,12 +130,12 @@ static void test_host_name_notify(void) write_seq(t, "\033]777;notify;Title;Body\007"); assert(notify_count == 2); assert(!strcmp(notify_title, "Title")); - term_free(t); + wsap_vtcore_free(t); } static void test_osc52(void) { - struct term *t = osc_test_term(); + struct wsap_vtcore *t = osc_test_term(); reset_captures(); write_seq(t, "\033]52;c;aGVsbG8=\007"); assert(clip_count == 1 && !strcmp(clip_sel, "c")); @@ -180,7 +180,7 @@ static void test_osc52(void) write_seq(t, "\033]52;s;AAH9\007"); assert(clip_count == 1 && !strcmp(clip_sel, "s") && clip_len == 3); assert(clip_data[0] == 0 && clip_data[1] == 1 && clip_data[2] == (char)0xfd); - term_free(t); + wsap_vtcore_free(t); } /* An SGR reset must not drop an open link. @@ -191,44 +191,44 @@ static void test_osc52(void) * path runs. */ static void test_sgr_reset_keeps_link(void) { - struct term *t = osc_test_term(); + struct wsap_vtcore *t = osc_test_term(); reset_captures(); static const char seq[] = "\033]8;;https://reset.dev\033\\\033[0mX"; write_buf(t, seq, sizeof(seq) - 1); - assert(tt_cell(t, 0, 0)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 0, 0)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 0, 0, "https://reset.dev"); /* The same reset in its own write, which takes the normal parser. */ static const char seq2[] = "\033]8;;https://second.dev\033\\\033[0m"; write_buf(t, seq2, sizeof(seq2) - 1); write_buf(t, "Y", 1); - assert(tt_cell(t, 1, 0)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 1, 0)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 1, 0, "https://second.dev"); - term_free(t); + wsap_vtcore_free(t); } static void test_osc8(void) { - struct term *t = osc_test_term(); + struct wsap_vtcore *t = osc_test_term(); reset_captures(); write_seq(t, "\033]8;;https://example.com\033\\link text\033]8;;\033\\after"); for (int c = 0; c < 9; c++) { - assert(tt_cell(t, c, 0)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, c, 0)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, c, 0, "https://example.com"); } for (int c = 9; c < 14; c++) { - assert(!(tt_cell(t, c, 0)->attrs & TERM_ATTR_LINK)); + assert(!(tt_cell(t, c, 0)->attrs & WSAP_VTCORE_ATTR_LINK)); assert_link(t, c, 0, NULL); } /* Each cell keeps the URI of its own link. */ write_seq(t, "\033[2;1H\033]8;;https://other.org\033\\bbb\033]8;;\033\\"); write_seq(t, "\033[3;1H\033]8;;https://example.com\033\\ccc\033]8;;\033\\"); - assert(tt_cell(t, 0, 1)->attrs & TERM_ATTR_LINK); - assert(tt_cell(t, 0, 2)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 0, 1)->attrs & WSAP_VTCORE_ATTR_LINK); + assert(tt_cell(t, 0, 2)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 0, 1, "https://other.org"); assert_link(t, 2, 1, "https://other.org"); assert_link(t, 0, 2, "https://example.com"); @@ -236,31 +236,31 @@ static void test_osc8(void) /* An erase removes the link. */ write_seq(t, "\033[4;1H\033]8;;https://gone.io\033\\zzz\033]8;;\033\\"); - assert(tt_cell(t, 0, 3)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 0, 3)->attrs & WSAP_VTCORE_ATTR_LINK); write_seq(t, "\033[4;1H\033[K"); - assert(!(tt_cell(t, 0, 3)->attrs & TERM_ATTR_LINK)); + assert(!(tt_cell(t, 0, 3)->attrs & WSAP_VTCORE_ATTR_LINK)); assert_link(t, 0, 3, NULL); write_seq(t, "\033[5;1H\033]8;x\033\\nop\033]8;xyz\033\\qq"); - assert(!(tt_cell(t, 0, 4)->attrs & TERM_ATTR_LINK)); + assert(!(tt_cell(t, 0, 4)->attrs & WSAP_VTCORE_ATTR_LINK)); assert_link(t, 0, 4, NULL); - assert(!(tt_cell(t, 4, 4)->attrs & TERM_ATTR_LINK)); + assert(!(tt_cell(t, 4, 4)->attrs & WSAP_VTCORE_ATTR_LINK)); write_seq(t, "\033]8;;https://stay.net\033\\\033]8;bogus\033\\ST\033]8;;\033\\"); - assert(tt_cell(t, 5, 4)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 5, 4)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 5, 4, "https://stay.net"); write_seq(t, "\033[6;1H\033]8;id=grp;https://params.dev\007p1\033]8;;\007"); - assert(tt_cell(t, 0, 5)->attrs & TERM_ATTR_LINK); + assert(tt_cell(t, 0, 5)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 0, 5, "https://params.dev"); /* A link stays on its cells when they scroll into the history. */ for (int i = 0; i < 30; i++) write_buf(t, "filler\r\n", 8); assert(tt_history(t) > 0); - term_scroll(t, tt_history(t)); - assert(tt_view_cell(t, 0, 0)->attrs & TERM_ATTR_LINK); + wsap_vtcore_scroll(t, tt_history(t)); + assert(tt_view_cell(t, 0, 0)->attrs & WSAP_VTCORE_ATTR_LINK); assert_link(t, 0, 0, "https://example.com"); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); write_seq(t, "\033[7;1H"); for (int i = 0; i < 8300; i++) { @@ -279,46 +279,46 @@ static void test_osc8(void) write_seq(t, "\033[1;1H\033]8;;https://altscreen.test\033\\ALT\033]8;;\033\\"); assert_link(t, 0, 0, "https://altscreen.test"); write_seq(t, "\033[?1049l"); - term_scroll(t, tt_history(t)); + wsap_vtcore_scroll(t, tt_history(t)); assert_link(t, 0, 0, "https://example.com"); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); write_seq(t, "\033[8;1HSee file:///home/user/code/file.c#L10-L20 for info"); assert_link(t, 10, 7, "file:///home/user/code/file.c#L10-L20"); - term_free(t); + wsap_vtcore_free(t); } -static bool text_is(char *(*get)(const struct term *), - const struct term *t, const char *want) +static bool text_is(char *(*get)(const struct wsap_vtcore *), + const struct wsap_vtcore *t, const char *want) { char *text = get(t); bool same = text && !strcmp(text, want); - term_text_free(text); + wsap_vtcore_text_free(text); return same; } static void test_osc_misc(void) { - struct term *t = osc_test_term(); + struct wsap_vtcore *t = osc_test_term(); reset_captures(); write_seq(t, "\033]7;file://host/home/user/proj\007"); - assert(text_is(term_cwd, t, "/home/user/proj")); + assert(text_is(wsap_vtcore_cwd, t, "/home/user/proj")); write_seq(t, "\033]7;file:///a%20b\033\\"); - assert(text_is(term_cwd, t, "/a b")); + assert(text_is(wsap_vtcore_cwd, t, "/a b")); const char *bulk = "\033]7;file://h/bulk%20dir\007"; write_buf(t, bulk, strlen(bulk)); - assert(text_is(term_cwd, t, "/bulk dir")); + assert(text_is(wsap_vtcore_cwd, t, "/bulk dir")); write_seq(t, "\033]7;https://x/y\007"); write_seq(t, "\033]7;notauri\007"); - assert(text_is(term_cwd, t, "/bulk dir")); + assert(text_is(wsap_vtcore_cwd, t, "/bulk dir")); write_seq(t, "\033]9;hello there\033\\"); assert(notify_count == 1); - assert(!strcmp(notify_title, "term")); + assert(!strcmp(notify_title, "wsap_vtcore")); assert(!strcmp(notify_body, "hello there")); write_seq(t, "\033]9;4;3;50\007"); assert(notify_count == 1); @@ -331,43 +331,43 @@ static void test_osc_misc(void) assert(notify_count == 2); write_seq(t, "\033]22;pointer\033\\"); - assert(text_is(term_pointer_shape, t, "pointer")); + assert(text_is(wsap_vtcore_pointer_shape, t, "pointer")); write_seq(t, "\033]22;text\007"); - assert(text_is(term_pointer_shape, t, "text")); + assert(text_is(wsap_vtcore_pointer_shape, t, "text")); write_seq(t, "\033]22;\033\\"); - assert(!term_pointer_shape(t)); + assert(!wsap_vtcore_pointer_shape(t)); - term_free(t); + wsap_vtcore_free(t); } /* OSC 4, 10, 11, and 12 change the colors of one terminal. The reset codes * restore the colors of its theme. */ static void test_osc_colors(void) { - struct term_theme theme; - term_theme_default(&theme); - struct term *t = osc_test_term(); - struct term *other = osc_test_term(); + struct wsap_vtcore_theme theme; + wsap_vtcore_theme_default(&theme); + struct wsap_vtcore *t = osc_test_term(); + struct wsap_vtcore *other = osc_test_term(); reset_captures(); /* tt_new starts with the built-in theme. */ - assert(tt_color(t, TERM_COLOR_FG) == 0xFFFFFFFFu && theme.fg == 0xFFFFFFFFu); - assert(tt_color(t, TERM_COLOR_BG) == 0xFF1E1E2Eu && theme.bg == 0xFF1E1E2Eu); + assert(tt_color(t, WSAP_VTCORE_COLOR_FG) == 0xFFFFFFFFu && theme.fg == 0xFFFFFFFFu); + assert(tt_color(t, WSAP_VTCORE_COLOR_BG) == 0xFF1E1E2Eu && theme.bg == 0xFF1E1E2Eu); assert(cursor_color(t) == 0xFF89B4FAu && theme.cursor == 0xFF89B4FAu); assert_query(t, "\033]10;?\007", "\033]10;rgb:ffff/ffff/ffff\033\\"); write_seq(t, "\033]10;#ff0000\007"); - assert(tt_color(t, TERM_COLOR_FG) == 0xFFFF0000u); + assert(tt_color(t, WSAP_VTCORE_COLOR_FG) == 0xFFFF0000u); assert_query(t, "\033]10;?\007", "\033]10;rgb:ffff/0000/0000\033\\"); write_seq(t, "\033]110\007"); - assert(tt_color(t, TERM_COLOR_FG) == theme.fg); + assert(tt_color(t, WSAP_VTCORE_COLOR_FG) == theme.fg); assert_query(t, "\033]10;?\033\\", "\033]10;rgb:ffff/ffff/ffff\033\\"); write_seq(t, "\033]11;#00ff00\033\\"); - assert(tt_color(t, TERM_COLOR_BG) == 0xFF00FF00u); + assert(tt_color(t, WSAP_VTCORE_COLOR_BG) == 0xFF00FF00u); assert_query(t, "\033]11;?\007", "\033]11;rgb:0000/ffff/0000\033\\"); write_seq(t, "\033]111\007"); - assert(tt_color(t, TERM_COLOR_BG) == theme.bg); + assert(tt_color(t, WSAP_VTCORE_COLOR_BG) == theme.bg); assert_query(t, "\033]11;?\007", "\033]11;rgb:1e1e/1e1e/2e2e\033\\"); write_seq(t, "\033]12;#0000ff\007"); @@ -377,35 +377,35 @@ static void test_osc_colors(void) assert(cursor_color(t) == theme.cursor); assert_query(t, "\033]12;?\007", "\033]12;rgb:8989/b4b4/fafa\033\\"); - uint32_t ansi5 = tt_color(t, term_color_index(5)); + uint32_t ansi5 = tt_color(t, wsap_vtcore_color_index(5)); assert(ansi5 == theme.ansi[5]); write_seq(t, "\033]4;5;#ff0000\007"); - assert(tt_color(t, term_color_index(5)) == 0xFFFF0000u); - assert(tt_color(t, term_color_index(4)) == theme.ansi[4]); + assert(tt_color(t, wsap_vtcore_color_index(5)) == 0xFFFF0000u); + assert(tt_color(t, wsap_vtcore_color_index(4)) == theme.ansi[4]); /* A color change in one terminal does not change another terminal. */ write_seq(t, "\033]10;#123456\007"); - assert(tt_color(other, term_color_index(5)) == theme.ansi[5]); - assert(tt_color(other, TERM_COLOR_FG) == theme.fg); + assert(tt_color(other, wsap_vtcore_color_index(5)) == theme.ansi[5]); + assert(tt_color(other, WSAP_VTCORE_COLOR_FG) == theme.fg); assert_query(other, "\033]10;?\007", "\033]10;rgb:ffff/ffff/ffff\033\\"); - assert(tt_color(t, TERM_COLOR_FG) == 0xFF123456u); + assert(tt_color(t, WSAP_VTCORE_COLOR_FG) == 0xFF123456u); write_seq(t, "\033]104;5\007"); - assert(tt_color(t, term_color_index(5)) == ansi5); + assert(tt_color(t, wsap_vtcore_color_index(5)) == ansi5); write_seq(t, "\033]4;1;#010203;2;#040506\007"); - assert(tt_color(t, term_color_index(1)) == 0xFF010203u); - assert(tt_color(t, term_color_index(2)) == 0xFF040506u); + assert(tt_color(t, wsap_vtcore_color_index(1)) == 0xFF010203u); + assert(tt_color(t, wsap_vtcore_color_index(2)) == 0xFF040506u); write_seq(t, "\033]104\007"); - assert(tt_color(t, term_color_index(1)) == theme.ansi[1]); - assert(tt_color(t, term_color_index(2)) == theme.ansi[2]); + assert(tt_color(t, wsap_vtcore_color_index(1)) == theme.ansi[1]); + assert(tt_color(t, wsap_vtcore_color_index(2)) == theme.ansi[2]); - term_free(other); - term_free(t); + wsap_vtcore_free(other); + wsap_vtcore_free(t); } static void test_osc_legacy_titles(void) { - struct term *t = osc_test_term(); + struct wsap_vtcore *t = osc_test_term(); reset_captures(); write_seq(t, "\033]legacy title\007"); @@ -415,61 +415,61 @@ static void test_osc_legacy_titles(void) write_seq(t, "\033]2adjacent\033\\"); assert(!strcmp(title, "adjacent")); - term_free(t); + wsap_vtcore_free(t); } static void test_palette_and_theme(void) { uint32_t c; /* Hex formats */ - assert(term_color_parse("#f00", &c) && c == 0xFFFF0000u); - assert(term_color_parse("#00ff00", &c) && c == 0xFF00FF00u); - assert(term_color_parse(" #0000ff \t", &c) && c == 0xFF0000FFu); - assert(term_color_parse("123456", &c) && c == 0xFF123456u); - assert(term_color_parse("abc", &c) && c == 0xFFAABBCCu); - assert(term_color_parse("#123456789abc", &c) && c == 0xFF12569au); - assert(term_color_parse("#123456789", &c) && c == 0xFF124578u); - assert(!term_color_parse("#12g456789", &c)); - assert(!term_color_parse("#123456789abg", &c)); + assert(wsap_vtcore_color_parse("#f00", &c) && c == 0xFFFF0000u); + assert(wsap_vtcore_color_parse("#00ff00", &c) && c == 0xFF00FF00u); + assert(wsap_vtcore_color_parse(" #0000ff \t", &c) && c == 0xFF0000FFu); + assert(wsap_vtcore_color_parse("123456", &c) && c == 0xFF123456u); + assert(wsap_vtcore_color_parse("abc", &c) && c == 0xFFAABBCCu); + assert(wsap_vtcore_color_parse("#123456789abc", &c) && c == 0xFF12569au); + assert(wsap_vtcore_color_parse("#123456789", &c) && c == 0xFF124578u); + assert(!wsap_vtcore_color_parse("#12g456789", &c)); + assert(!wsap_vtcore_color_parse("#123456789abg", &c)); /* rgb: / rgbi: */ - assert(term_color_parse("rgb:ff/80/00", &c) && c == 0xFFFF8000u); - assert(term_color_parse("rgb:f/123/4567", &c) && c == 0xFFFF1245u); - assert(!term_color_parse("rgb:fffff/0/0", &c)); - assert(term_color_parse("rgbi:1.0/0.0/0.5", &c) && c == 0xFFFF0080u); - assert(term_color_parse("rgbi:.25/.5/.75", &c)); + assert(wsap_vtcore_color_parse("rgb:ff/80/00", &c) && c == 0xFFFF8000u); + assert(wsap_vtcore_color_parse("rgb:f/123/4567", &c) && c == 0xFFFF1245u); + assert(!wsap_vtcore_color_parse("rgb:fffff/0/0", &c)); + assert(wsap_vtcore_color_parse("rgbi:1.0/0.0/0.5", &c) && c == 0xFFFF0080u); + assert(wsap_vtcore_color_parse("rgbi:.25/.5/.75", &c)); /* Errors */ - assert(!term_color_parse(NULL, &c)); - assert(!term_color_parse("#ff", &c)); - assert(!term_color_parse("", &c)); - assert(!term_color_parse("rgb:ff/80", &c)); - assert(!term_color_parse("rgb:ff/80/00/11", &c)); - assert(!term_color_parse("rgbi:2.0/0/0", &c)); - assert(!term_color_parse("rgbi:./0/0", &c)); + assert(!wsap_vtcore_color_parse(NULL, &c)); + assert(!wsap_vtcore_color_parse("#ff", &c)); + assert(!wsap_vtcore_color_parse("", &c)); + assert(!wsap_vtcore_color_parse("rgb:ff/80", &c)); + assert(!wsap_vtcore_color_parse("rgb:ff/80/00/11", &c)); + assert(!wsap_vtcore_color_parse("rgbi:2.0/0/0", &c)); + assert(!wsap_vtcore_color_parse("rgbi:./0/0", &c)); /* Theme APIs */ - struct term_theme theme; - term_theme_default(&theme); - assert(term_theme_set_key(&theme, "foreground", "#112233") && theme.fg == 0xFF112233u); - assert(term_theme_set_key(&theme, "foreground", "") && theme.fg == 0xFFFFFFFFu); - assert(term_theme_set_key(&theme, "background", "#445566") && theme.bg == 0xFF445566u); - assert(term_theme_set_key(&theme, "background", "") && theme.bg == 0xFF1E1E2Eu); - assert(term_theme_set_key(&theme, "color0", "#010203") && theme.ansi[0] == 0xFF010203u); - assert(term_theme_set_key(&theme, "color15", "#fafbfc") && theme.ansi[15] == 0xFFFAFBFCu); - assert(term_theme_set_key(&theme, "color0", "") && theme.ansi[0] == 0xFF585B70u); - assert(!term_theme_set_key(&theme, "color16", "#000000")); - assert(!term_theme_set_key(&theme, "color01", "#000000")); - assert(!term_theme_set_key(&theme, "color", "#000000")); - assert(!term_theme_set_key(&theme, "color1x", "#000000")); - assert(!term_theme_set_key(&theme, "color100000000000000000000", "#000000")); - assert(!term_theme_set_key(&theme, "invalid", "#000000")); - assert(!term_theme_set_key(NULL, "foreground", "#000000")); - assert(!term_theme_set_key(&theme, NULL, "#000000")); - assert(!term_theme_set_key(&theme, "foreground", NULL)); - - struct term_theme hc; - term_theme_high_contrast(&hc); + struct wsap_vtcore_theme theme; + wsap_vtcore_theme_default(&theme); + assert(wsap_vtcore_theme_set_key(&theme, "foreground", "#112233") && theme.fg == 0xFF112233u); + assert(wsap_vtcore_theme_set_key(&theme, "foreground", "") && theme.fg == 0xFFFFFFFFu); + assert(wsap_vtcore_theme_set_key(&theme, "background", "#445566") && theme.bg == 0xFF445566u); + assert(wsap_vtcore_theme_set_key(&theme, "background", "") && theme.bg == 0xFF1E1E2Eu); + assert(wsap_vtcore_theme_set_key(&theme, "color0", "#010203") && theme.ansi[0] == 0xFF010203u); + assert(wsap_vtcore_theme_set_key(&theme, "color15", "#fafbfc") && theme.ansi[15] == 0xFFFAFBFCu); + assert(wsap_vtcore_theme_set_key(&theme, "color0", "") && theme.ansi[0] == 0xFF585B70u); + assert(!wsap_vtcore_theme_set_key(&theme, "color16", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "color01", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "color", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "color1x", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "color100000000000000000000", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "invalid", "#000000")); + assert(!wsap_vtcore_theme_set_key(NULL, "foreground", "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, NULL, "#000000")); + assert(!wsap_vtcore_theme_set_key(&theme, "foreground", NULL)); + + struct wsap_vtcore_theme hc; + wsap_vtcore_theme_high_contrast(&hc); assert(hc.bg == 0xFF000000u && hc.fg == 0xFFFFFFFFu); } diff --git a/tests/resize_failure_test.c b/tests/resize_failure_test.c index fbfa38d..0074f56 100644 --- a/tests/resize_failure_test.c +++ b/tests/resize_failure_test.c @@ -52,7 +52,7 @@ int main(void) puts("resize failure test skipped under sanitizer"); return 0; #else - struct term *term = tt_new(10, 2); + struct wsap_vtcore *term = tt_new(10, 2); assert(term); tt_write(term, "abc", 3); @@ -79,7 +79,7 @@ int main(void) assert(tt_cols(term) == 20); assert(tt_rows(term) == 2); assert(tt_cell(term, 0, 0)->text == '1'); - term_free(term); + wsap_vtcore_free(term); term = tt_new(10, 3); assert(term); @@ -96,7 +96,7 @@ int main(void) assert(tt_cell(term, 4, 0)->text == 'e'); assert(tt_cell(term, 5, 0)->text != 'f'); assert(tt_cell(term, 0, 1)->text == 'f'); - term_free(term); + wsap_vtcore_free(term); term = tt_new(10, 2); assert(term); @@ -106,12 +106,12 @@ int main(void) assert(!fail_next_calloc); /* A failed alternate-screen allocation keeps the normal screen active. */ - assert(!term_modes(term).alternate); + assert(!wsap_vtcore_modes(term).alternate); assert(tt_cell(term, 0, 0)->text == 'n'); assert(tt_cell(term, 5, 0)->text == 'l'); tt_write(term, "\033[?1049l", 8); assert(tt_cell(term, 0, 0)->text == 'n'); - term_free(term); + wsap_vtcore_free(term); /* A reflow that cannot grow its row buffers fails before it changes the * history, so the old geometry and text survive the failed resize. The @@ -144,7 +144,7 @@ int main(void) resized = tt_resize(term, 10, 40); assert(resized); assert(tt_cols(term) == 10); - term_free(term); + wsap_vtcore_free(term); /* A failed same-width height shrink must not scroll rows into history or * move the cursor. The same resize must succeed when allocation recovers. */ @@ -174,14 +174,14 @@ int main(void) assert(tt_cell(term, 0, 1)->text == 'D'); assert(tt_cursor_y(term) == 1); assert(tt_history(term) == 2); - term_free(term); + wsap_vtcore_free(term); /* The alternate screen uses the same allocation-before-scroll path. */ term = tt_new(8, 4); assert(term); tt_write(term, "\033[?1049h", 8); tt_write(term, four_rows, sizeof four_rows - 1); - assert(term_modes(term).alternate); + assert(wsap_vtcore_modes(term).alternate); assert(tt_cursor_y(term) == 3); fail_next_calloc = true; resized = tt_resize(term, 8, 2); @@ -195,7 +195,7 @@ int main(void) assert(tt_rows(term) == 2 && tt_cursor_y(term) == 1); assert(tt_cell(term, 0, 0)->text == 'C'); assert(tt_cell(term, 0, 1)->text == 'D'); - term_free(term); + wsap_vtcore_free(term); puts("lazy screen allocation failures preserve observable terminal state"); return 0; diff --git a/tests/resize_property_test.c b/tests/resize_property_test.c index 360e640..91b487f 100644 --- a/tests/resize_property_test.c +++ b/tests/resize_property_test.c @@ -1,4 +1,4 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include "term_api.h" #include <stdint.h> @@ -18,15 +18,15 @@ static unsigned random_below(unsigned limit) /* Select from the oldest retained row to the end of the live screen. * Selection text joins wrapped rows and trims blank cells on other rows. */ -static char *logical_text(struct term *t) +static char *logical_text(struct wsap_vtcore *t) { - struct term_vector2i size = term_size(t); - term_scroll_to(t, term_scrollback(t).total); - term_select_start(t, (struct term_vector2i){ .x = 0, .y = 0 }, false, TERM_SELECT_CELL); - term_scroll_to(t, 0); - term_select_extend(t, (struct term_vector2i){ .x = size.x - 1, .y = size.y - 1 }, true); + struct wsap_vtcore_vector2i size = wsap_vtcore_size(t); + wsap_vtcore_scroll_to(t, wsap_vtcore_scrollback(t).total); + wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 0 }, false, WSAP_VTCORE_SELECT_CELL); + wsap_vtcore_scroll_to(t, 0); + wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = size.x - 1, .y = size.y - 1 }, true); char *text = tt_selection_text(t); - term_select_clear(t); + wsap_vtcore_select_clear(t); if (!text) return NULL; size_t out = 0; for (size_t i = 0; text[i]; i++) { @@ -40,76 +40,76 @@ static char *logical_text(struct term *t) return text; } -static uint32_t cell_at(struct term *t, struct term_snapshot *s, int x, int y) +static uint32_t cell_at(struct wsap_vtcore *t, struct wsap_vtcore_snapshot *s, int x, int y) { - if (!term_snapshot_update(s, t)) return 0; - return term_snapshot_row(s, y)[x].text; + if (!wsap_vtcore_snapshot_update(s, t)) return 0; + return wsap_vtcore_snapshot_row(s, y)[x].text; } /* A height change that pulls rows back from history moves the saved * cursor with its row. DECRC then prints next to the saved text. */ -static int saved_cursor_follows_history(struct term_snapshot *s) +static int saved_cursor_follows_history(struct wsap_vtcore_snapshot *s) { static const struct { int cols, rows, grow_cols, grow_rows; } cases[] = { { 8, 3, 8, 5 }, /* same width: rows come back from history */ { 8, 3, 10, 5 }, /* new width: reflow */ }; for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = cases[i].cols, .y = cases[i].rows }, .scrollback = 10, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); if (!t) return 1; const char *text = "l1\r\nl2\r\nl3\r\nl4\r\nab\0337\033[1;1H"; - term_feed(t, text, strlen(text), 0); - struct term_vector2i size = { .x = cases[i].grow_cols, .y = cases[i].grow_rows }; - if (!term_resize(t, size)) return 1; - term_feed(t, "\0338X", 3, 0); - struct term_cursor c = term_cursor(t); + wsap_vtcore_feed(t, text, strlen(text), 0); + struct wsap_vtcore_vector2i size = { .x = cases[i].grow_cols, .y = cases[i].grow_rows }; + if (!wsap_vtcore_resize(t, size)) return 1; + wsap_vtcore_feed(t, "\0338X", 3, 0); + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t); int y = c.pos.y; if (cell_at(t, s, 0, y) != 'a' || cell_at(t, s, 1, y) != 'b' || cell_at(t, s, 2, y) != 'X') { fprintf(stderr, "case %zu: DECRC after a resize lost the saved row\n", i); return 1; } - term_free(t); + wsap_vtcore_free(t); } return 0; } /* Narrowing a full screen with the cursor at the top wraps more rows than * the ring holds. The cursor row must survive and stay on screen. */ -static int narrow_resize_keeps_cursor_row(struct term_snapshot *s) +static int narrow_resize_keeps_cursor_row(struct wsap_vtcore_snapshot *s) { - struct term_options opt = { .size = { .x = 40, .y = 12 }, .scrollback = 5 }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 40, .y = 12 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); if (!t) return 1; for (int y = 0; y < 12; y++) { char line[64]; memset(line, 'a' + y, 40); line[40] = 0; - term_feed(t, line, 40, 0); + wsap_vtcore_feed(t, line, 40, 0); } - term_feed(t, "\033[1;1H", 6, 0); - if (!term_resize(t, (struct term_vector2i){ .x = 1, .y = 12 })) return 1; - struct term_cursor c = term_cursor(t); + wsap_vtcore_feed(t, "\033[1;1H", 6, 0); + if (!wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ .x = 1, .y = 12 })) return 1; + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t); if (c.pos.x != 0 || c.pos.y != 0 || cell_at(t, s, 0, 0) != 'a') { fprintf(stderr, "narrow resize: cursor %d,%d, cell %x\n", c.pos.x, c.pos.y, cell_at(t, s, 0, 0)); return 1; } - term_feed(t, "Z", 1, 0); + wsap_vtcore_feed(t, "Z", 1, 0); if (cell_at(t, s, 0, 0) != 'Z') return 1; - term_free(t); + wsap_vtcore_free(t); return 0; } int main(int argc, char **argv) { - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); if (!snap || saved_cursor_follows_history(snap) || narrow_resize_keeps_cursor_row(snap)) return 1; - term_snapshot_free(snap); + wsap_vtcore_snapshot_free(snap); int seeds = argc > 1 ? atoi(argv[1]) : 100; static const char *word[] = { @@ -117,28 +117,28 @@ int main(int argc, char **argv) }; for (int seed = 1; seed <= seeds; seed++) { state = 0x9e3779b97f4a7c15ull * (uint64_t)seed; - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = 40, .y = 12 }, .scrollback = 4096, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); if (!t) return 1; for (int line = 0; line < 16; line++) { int words = 1 + (int)random_below(4); for (int i = 0; i < words; i++) { const char *s = word[random_below(sizeof(word) / sizeof(word[0]))]; - term_feed(t, s, strlen(s), 0); + wsap_vtcore_feed(t, s, strlen(s), 0); } - if (line != 15) term_feed(t, "\r\n", 2, 0); + if (line != 15) wsap_vtcore_feed(t, "\r\n", 2, 0); } char *before = logical_text(t); if (!before) return 1; for (int step = 0; step < 20; step++) { - struct term_vector2i size = { + struct wsap_vtcore_vector2i size = { .x = 1 + (int)random_below(200), .y = 1 + (int)random_below(60), }; - if (!term_resize(t, size)) return 1; + if (!wsap_vtcore_resize(t, size)) return 1; char *after = logical_text(t); if (!after) return 1; if (strcmp(before, after)) { @@ -150,7 +150,7 @@ int main(int argc, char **argv) free(after); } free(before); - term_free(t); + wsap_vtcore_free(t); } return 0; } diff --git a/tests/snapshot_failure_test.c b/tests/snapshot_failure_test.c index 7d4b139..bf4b694 100644 --- a/tests/snapshot_failure_test.c +++ b/tests/snapshot_failure_test.c @@ -1,4 +1,4 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <assert.h> #include <stdbool.h> @@ -49,18 +49,18 @@ void *__wrap_realloc(void *p, size_t size) /* A copy of everything a renderer can read from a snapshot. */ struct frame { - struct term_view view; - uint32_t palette[TERM_PALETTE_SIZE]; + struct wsap_vtcore_view view; + uint32_t palette[WSAP_VTCORE_PALETTE_SIZE]; int cols, rows; - struct term_cell *cells; /* rows * cols */ + struct wsap_vtcore_cell *cells; /* rows * cols */ uint32_t *cps; /* per cell: count, then code points */ uint64_t *keys; /* per row */ - struct term_span *sel; /* per row */ + struct wsap_vtcore_span *sel; /* per row */ }; -static void frame_capture(const struct term_snapshot *s, struct frame *f) +static void frame_capture(const struct wsap_vtcore_snapshot *s, struct frame *f) { - const struct term_view *v = term_snapshot_view(s); + const struct wsap_vtcore_view *v = wsap_vtcore_snapshot_view(s); f->view = *v; memcpy(f->palette, v->palette, sizeof(f->palette)); f->cols = v->size.x; @@ -72,17 +72,17 @@ static void frame_capture(const struct term_snapshot *s, struct frame *f) f->sel = calloc((size_t)f->rows + 1, sizeof(*f->sel)); assert(f->cells && f->cps && f->keys && f->sel); for (int y = 0; y < f->rows; y++) { - const struct term_cell *row = term_snapshot_row(s, y); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, y); assert(row); - f->keys[y] = term_snapshot_row_key(s, y); - f->sel[y] = term_snapshot_row_selection(s, y); + f->keys[y] = wsap_vtcore_snapshot_row_key(s, y); + f->sel[y] = wsap_vtcore_snapshot_row_selection(s, y); for (int x = 0; x < f->cols; x++) { size_t i = (size_t)y * f->cols + x; f->cells[i] = row[x]; uint32_t *cps = f->cps + i * CPS_SLOT; cps[0] = 0; - if (row[x].text & TERM_TEXT_CLUSTER) - cps[0] = (uint32_t)term_snapshot_cluster(s, row[x].text, cps + 1, CPS_MAX); + if (row[x].text & WSAP_VTCORE_TEXT_CLUSTER) + cps[0] = (uint32_t)wsap_vtcore_snapshot_cluster(s, row[x].text, cps + 1, CPS_MAX); } } } @@ -97,7 +97,7 @@ static void frame_free(struct frame *f) static bool same_view(const struct frame *a, const struct frame *b) { - const struct term_view *x = &a->view, *y = &b->view; + const struct wsap_vtcore_view *x = &a->view, *y = &b->view; return x->size.x == y->size.x && x->size.y == y->size.y && x->cursor.pos.x == y->cursor.pos.x && x->cursor.pos.y == y->cursor.pos.y && x->cursor.style == y->cursor.style && x->cursor.visible == y->cursor.visible && @@ -125,7 +125,7 @@ static bool frame_same(const struct frame *a, const struct frame *b) * between an incremental snapshot and a fresh one. */ static bool frame_shows_same(const struct frame *a, const struct frame *b) { - const struct term_view *x = &a->view, *y = &b->view; + const struct wsap_vtcore_view *x = &a->view, *y = &b->view; if (a->cols != b->cols || a->rows != b->rows || x->cursor.pos.x != y->cursor.pos.x || x->cursor.pos.y != y->cursor.pos.y || x->cursor.visible != y->cursor.visible || x->scroll_offset != y->scroll_offset || x->reverse_video != y->reverse_video || @@ -136,11 +136,11 @@ static bool frame_shows_same(const struct frame *a, const struct frame *b) return false; for (int c = 0; c < a->cols; c++) { size_t i = (size_t)r * a->cols + c; - const struct term_cell *p = &a->cells[i], *q = &b->cells[i]; + const struct wsap_vtcore_cell *p = &a->cells[i], *q = &b->cells[i]; const uint32_t *cp = a->cps + i * CPS_SLOT, *cq = b->cps + i * CPS_SLOT; if (p->fg != q->fg || p->bg != q->bg || p->attrs != q->attrs || p->width != q->width) return false; - if (p->text & TERM_TEXT_CLUSTER) { + if (p->text & WSAP_VTCORE_TEXT_CLUSTER) { if (cp[0] != cq[0] || memcmp(cp + 1, cq + 1, cp[0] * sizeof(*cp)) != 0) return false; } else if (p->text != q->text) { @@ -154,13 +154,13 @@ static bool frame_shows_same(const struct frame *a, const struct frame *b) /* One update with the k-th allocation failing, from the state the caller * built. A failed update must leave s as it was, and the retry must succeed. * Returns true when an allocation was failed. */ -static bool update_failing_at(struct term_snapshot *s, struct term *t, int k) +static bool update_failing_at(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t, int k) { struct frame before, after; frame_capture(s, &before); alloc_was_failed = false; alloc_countdown = k; - bool ok = term_snapshot_update(s, t); + bool ok = wsap_vtcore_snapshot_update(s, t); alloc_countdown = -1; bool injected = alloc_was_failed; if (!ok) { @@ -168,7 +168,7 @@ static bool update_failing_at(struct term_snapshot *s, struct term *t, int k) frame_capture(s, &after); assert(frame_same(&before, &after)); frame_free(&after); - assert(term_snapshot_update(s, t)); + assert(wsap_vtcore_snapshot_update(s, t)); } frame_free(&before); return injected; @@ -191,7 +191,7 @@ static int sweep(bool (*attempt)(int k)) * an update succeeds. Every failed attempt must leave s as it was. Progress * from earlier attempts stays, so this covers the later steps of a long run * rather than each site from one start. Returns the number of failures. */ -static int update_each_failure(struct term_snapshot *s, struct term *t) +static int update_each_failure(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t) { struct frame before, after; frame_capture(s, &before); @@ -201,7 +201,7 @@ static int update_each_failure(struct term_snapshot *s, struct term *t) assert(k < 1000); alloc_was_failed = false; alloc_countdown = k; - ok = term_snapshot_update(s, t); + ok = wsap_vtcore_snapshot_update(s, t); alloc_countdown = -1; if (ok) break; @@ -216,53 +216,53 @@ static int update_each_failure(struct term_snapshot *s, struct term *t) } /* A renderer sees the same picture as a fresh capture of t. */ -static void expect_matches_fresh(struct term *t, const struct term_snapshot *s) +static void expect_matches_fresh(struct wsap_vtcore *t, const struct wsap_vtcore_snapshot *s) { - struct term_snapshot *fresh = term_snapshot_new(); - assert(fresh && term_snapshot_update(fresh, t)); + struct wsap_vtcore_snapshot *fresh = wsap_vtcore_snapshot_new(); + assert(fresh && wsap_vtcore_snapshot_update(fresh, t)); struct frame a, b; frame_capture(s, &a); frame_capture(fresh, &b); assert(frame_shows_same(&a, &b)); frame_free(&a); frame_free(&b); - term_snapshot_free(fresh); + wsap_vtcore_snapshot_free(fresh); } /* A US flag and a ZWJ family: two regional indicators, and five code points. */ static const char flag_us[] = "\xf0\x9f\x87\xba\xf0\x9f\x87\xb8"; static const char family[] = "\xf0\x9f\x91\xa8\xe2\x80\x8d\xf0\x9f\x91\xa9\xe2\x80\x8d\xf0\x9f\x91\xa7"; -static uint32_t cluster_cps(const struct term_snapshot *s, const struct term_cell *cell, +static uint32_t cluster_cps(const struct wsap_vtcore_snapshot *s, const struct wsap_vtcore_cell *cell, uint32_t *cps, int cap) { - return (uint32_t)term_snapshot_cluster(s, cell->text, cps, cap); + return (uint32_t)wsap_vtcore_snapshot_cluster(s, cell->text, cps, cap); } /* A new terminal and an empty snapshot. The first update grows every buffer * and the arena, so each allocation site in the update is hit. */ static bool first_update_at(int k) { - struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 8, 3 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); const char accented[] = "e\xcc\x81 "; - term_feed(t, accented, sizeof(accented) - 1, 0); - term_feed(t, flag_us, sizeof(flag_us) - 1, 0); + wsap_vtcore_feed(t, accented, sizeof(accented) - 1, 0); + wsap_vtcore_feed(t, flag_us, sizeof(flag_us) - 1, 0); bool injected = update_failing_at(s, t, k); - const struct term_cell *row = term_snapshot_row(s, 0); - assert(row && (row[0].text & TERM_TEXT_CLUSTER)); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, 0); + assert(row && (row[0].text & WSAP_VTCORE_TEXT_CLUSTER)); uint32_t cps[8]; assert(cluster_cps(s, &row[0], cps, 8) == 2 && cps[0] == 'e' && cps[1] == 0x301); assert(cluster_cps(s, &row[2], cps, 8) == 2 && cps[0] == 0x1F1FA && cps[1] == 0x1F1F8); expect_matches_fresh(t, s); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return injected; } @@ -270,60 +270,60 @@ static bool first_update_at(int k) * 256 words, so the arena growth is one of the failing sites. */ static bool full_cluster_screen_at(int k) { - struct term_options options = { .size = { 32, 16 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 32, 16 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); for (int y = 0; y < 16; y++) { for (int i = 0; i < 16; i++) { if (y % 2) - term_feed(t, flag_us, sizeof(flag_us) - 1, 0); + wsap_vtcore_feed(t, flag_us, sizeof(flag_us) - 1, 0); else - term_feed(t, family, sizeof(family) - 1, 0); + wsap_vtcore_feed(t, family, sizeof(family) - 1, 0); } if (y < 15) - term_feed(t, "\r\n", 2, 0); + wsap_vtcore_feed(t, "\r\n", 2, 0); } bool injected = update_failing_at(s, t, k); uint32_t cps[8]; - const struct term_cell *row = term_snapshot_row(s, 0); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, 0); assert(cluster_cps(s, &row[0], cps, 8) == 5 && cps[0] == 0x1F468 && cps[1] == 0x200D); - row = term_snapshot_row(s, 1); + row = wsap_vtcore_snapshot_row(s, 1); assert(cluster_cps(s, &row[0], cps, 8) == 2 && cps[0] == 0x1F1FA); expect_matches_fresh(t, s); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return injected; } /* The screen grows, so cells, keys, row clusters, and selection all reserve. */ static bool resize_at(int k) { - struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 8, 3 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); - term_feed(t, "old", 3, 0); - assert(term_snapshot_update(s, t)); + wsap_vtcore_feed(t, "old", 3, 0); + assert(wsap_vtcore_snapshot_update(s, t)); - assert(term_resize(t, (struct term_vector2i){ 32, 16 })); - term_feed(t, "\x1b[H\x1b[2J", 7, 0); - term_feed(t, family, sizeof(family) - 1, 0); + assert(wsap_vtcore_resize(t, (struct wsap_vtcore_vector2i){ 32, 16 })); + wsap_vtcore_feed(t, "\x1b[H\x1b[2J", 7, 0); + wsap_vtcore_feed(t, family, sizeof(family) - 1, 0); bool injected = update_failing_at(s, t, k); - assert(term_snapshot_view(s)->size.x == 32 && term_snapshot_view(s)->size.y == 16); + assert(wsap_vtcore_snapshot_view(s)->size.x == 32 && wsap_vtcore_snapshot_view(s)->size.y == 16); uint32_t cps[8]; - const struct term_cell *row = term_snapshot_row(s, 0); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, 0); assert(cluster_cps(s, &row[0], cps, 8) == 5 && cps[0] == 0x1F468); expect_matches_fresh(t, s); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return injected; } @@ -331,124 +331,124 @@ static bool resize_at(int k) * row list, off the stack. */ static bool tall_screen_at(int k) { - struct term_options options = { .size = { 8, 300 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 8, 300 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); for (int y = 0; y < 299; y++) - term_feed(t, "\r\n", 2, 0); - term_feed(t, "e\xcc\x81yes", 5, 0); - assert(term_select_start(t, (struct term_vector2i){ .x = 0, .y = 299 }, false, - TERM_SELECT_CELL)); - assert(term_select_extend(t, (struct term_vector2i){ .x = 3, .y = 299 }, true)); + wsap_vtcore_feed(t, "\r\n", 2, 0); + wsap_vtcore_feed(t, "e\xcc\x81yes", 5, 0); + assert(wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 299 }, false, + WSAP_VTCORE_SELECT_CELL)); + assert(wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 3, .y = 299 }, true)); bool injected = update_failing_at(s, t, k); - assert(term_snapshot_view(s)->size.y == 300); - const struct term_cell *row = term_snapshot_row(s, 299); + assert(wsap_vtcore_snapshot_view(s)->size.y == 300); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, 299); uint32_t cps[4]; assert(cluster_cps(s, &row[0], cps, 4) == 2 && cps[0] == 'e' && cps[1] == 0x301); - struct term_span span = term_snapshot_row_selection(s, 299); + struct wsap_vtcore_span span = wsap_vtcore_snapshot_row_selection(s, 299); assert(span.begin == 0 && span.end == 4); expect_matches_fresh(t, s); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return injected; } /* Without failures, the selection of a tall screen reaches the last row. */ static void tall_selection_is_kept(void) { - struct term_options options = { .size = { 8, 300 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 8, 300 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); for (int y = 0; y < 299; y++) - term_feed(t, "\r\n", 2, 0); - term_feed(t, "e\xcc\x81yes", 5, 0); - term_select_start(t, (struct term_vector2i){ .x = 0, .y = 299 }, false, TERM_SELECT_CELL); - term_select_extend(t, (struct term_vector2i){ .x = 3, .y = 299 }, true); + wsap_vtcore_feed(t, "\r\n", 2, 0); + wsap_vtcore_feed(t, "e\xcc\x81yes", 5, 0); + wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 299 }, false, WSAP_VTCORE_SELECT_CELL); + wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 3, .y = 299 }, true); - assert(term_snapshot_update(s, t)); - struct term_span span = term_snapshot_row_selection(s, 299); + assert(wsap_vtcore_snapshot_update(s, t)); + struct wsap_vtcore_span span = wsap_vtcore_snapshot_row_selection(s, 299); assert(span.begin == 0 && span.end == 4); expect_matches_fresh(t, s); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); } /* On a screen taller than 256 rows, selecting needs memory. When none is * left, the call fails and the selection stays as it was. */ static void tall_selection_fails_cleanly(void) { - struct term_options options = { .size = { 8, 300 }, .scrollback = 5 }; - struct term *t = term_new(&options); + struct wsap_vtcore_options options = { .size = { 8, 300 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); assert(t); for (int y = 0; y < 299; y++) - term_feed(t, "\r\n", 2, 0); - term_feed(t, "yes", 3, 0); - assert(term_select_start(t, (struct term_vector2i){ .x = 0, .y = 299 }, false, - TERM_SELECT_CELL)); - assert(term_select_extend(t, (struct term_vector2i){ .x = 1, .y = 299 }, true)); - char *before = term_selection_text(t); + wsap_vtcore_feed(t, "\r\n", 2, 0); + wsap_vtcore_feed(t, "yes", 3, 0); + assert(wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 299 }, false, + WSAP_VTCORE_SELECT_CELL)); + assert(wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 1, .y = 299 }, true)); + char *before = wsap_vtcore_selection_text(t); assert(before && !strcmp(before, "ye")); alloc_was_failed = false; alloc_countdown = 0; - assert(!term_select_extend(t, (struct term_vector2i){ .x = 2, .y = 299 }, true)); + assert(!wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 2, .y = 299 }, true)); alloc_countdown = -1; assert(alloc_was_failed); alloc_was_failed = false; alloc_countdown = 0; - assert(!term_select_start(t, (struct term_vector2i){ .x = 2, .y = 299 }, false, - TERM_SELECT_WORD)); + assert(!wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 2, .y = 299 }, false, + WSAP_VTCORE_SELECT_WORD)); alloc_countdown = -1; assert(alloc_was_failed); - char *after = term_selection_text(t); + char *after = wsap_vtcore_selection_text(t); assert(after && !strcmp(after, before)); - term_text_free(before); - term_text_free(after); + wsap_vtcore_text_free(before); + wsap_vtcore_text_free(after); - assert(term_select_extend(t, (struct term_vector2i){ .x = 2, .y = 299 }, true)); - char *grown = term_selection_text(t); + assert(wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 2, .y = 299 }, true)); + char *grown = wsap_vtcore_selection_text(t); assert(grown && !strcmp(grown, "yes")); - term_text_free(grown); - term_free(t); + wsap_vtcore_text_free(grown); + wsap_vtcore_free(t); } /* Scroll with clusters in most lines. Each step fails every allocation in * turn, then retries, and must match a fresh capture. */ static void scrolling_fails_cleanly(void) { - struct term_options options = { .size = { 8, 3 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_options options = { .size = { 8, 3 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); assert(t && s); int failures = 0; for (int i = 0; i < 300; i++) { - term_feed(t, "e\xcc\x81", 3, 0); + wsap_vtcore_feed(t, "e\xcc\x81", 3, 0); if (i % 3 == 0) - term_feed(t, flag_us, sizeof(flag_us) - 1, 0); + wsap_vtcore_feed(t, flag_us, sizeof(flag_us) - 1, 0); if (i % 5 == 0) - term_feed(t, family, sizeof(family) - 1, 0); - term_feed(t, "\r\n", 2, 0); + wsap_vtcore_feed(t, family, sizeof(family) - 1, 0); + wsap_vtcore_feed(t, "\r\n", 2, 0); if (i == 150) - term_select_start(t, (struct term_vector2i){ .x = 0, .y = 1 }, false, TERM_SELECT_CELL); + wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 1 }, false, WSAP_VTCORE_SELECT_CELL); if (i == 151) - term_select_extend(t, (struct term_vector2i){ .x = 4, .y = 2 }, true); + wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 4, .y = 2 }, true); failures += update_each_failure(s, t); expect_matches_fresh(t, s); } assert(failures > 0); - assert(term_history_rows(t) == 5); + assert(wsap_vtcore_history_rows(t) == 5); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); } int main(void) diff --git a/tests/snapshot_scroll_arena_test.c b/tests/snapshot_scroll_arena_test.c index 7da6507..8e20aae 100644 --- a/tests/snapshot_scroll_arena_test.c +++ b/tests/snapshot_scroll_arena_test.c @@ -7,23 +7,23 @@ int main(void) { - struct term_options options = { .size = { 8, 24 }, .scrollback = 5 }; - struct term *t = term_new(&options); - struct term_snapshot *s = term_snapshot_new(); - assert(t && s && term_snapshot_update(s, t)); + struct wsap_vtcore_options options = { .size = { 8, 24 }, .scrollback = 5 }; + struct wsap_vtcore *t = wsap_vtcore_new(&options); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); + assert(t && s && wsap_vtcore_snapshot_update(s, t)); const char line[] = "e\xcc\x81\r\n"; for (int i = 0; i < 10000; i++) { - term_feed(t, line, sizeof(line) - 1, 0); - assert(term_snapshot_update(s, t)); + wsap_vtcore_feed(t, line, sizeof(line) - 1, 0); + assert(wsap_vtcore_snapshot_update(s, t)); } /* A fixed viewport holds fewer than 24 * 8 cluster records at once. * Dead records are compacted before they can dominate this arena. */ - assert(term_history_rows(t) == 5); + assert(wsap_vtcore_history_rows(t) == 5); assert(s->arena_len < 8192); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); return 0; } diff --git a/tests/spec_test.c b/tests/spec_test.c index 202f9ba..56e974c 100644 --- a/tests/spec_test.c +++ b/tests/spec_test.c @@ -6,7 +6,7 @@ * Rows read as text: '#' is U+FFFD, '?' is any other code point outside * ASCII or a cluster, '_' is the right half of a wide glyph. */ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <stdio.h> #include <stdlib.h> @@ -21,7 +21,7 @@ struct spec { * the history check; reply NULL skips the reply check. */ int attr_x, attr_y; uint16_t attrs; - term_color fg, bg; + wsap_vtcore_color fg, bg; int history; const char *reply; }; @@ -31,8 +31,8 @@ struct spec { #define NO_EXTRA .attr_x = -1, .history = -1 #define CASE(name_, input_, a, b, c, x_, y_) \ { .name = name_, .input = input_, .cols = 8, .rows = 3, ROWS3(a, b, c), AT(x_, y_), NO_EXTRA } -#define RED (TERM_COLOR_SLOT | 1) -#define BLUE (TERM_COLOR_SLOT | 4) +#define RED (WSAP_VTCORE_COLOR_SLOT | 1) +#define BLUE (WSAP_VTCORE_COLOR_SLOT | 4) static const struct spec cases[] = { /* Printing and C0 controls. */ @@ -174,56 +174,56 @@ static const struct spec cases[] = { .name = "SGR", .input = "\033[1;3;4;9;53;38;5;123;48;2;1;2;3mX", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), .attr_x = 0, .attr_y = 0, - .attrs = TERM_ATTR_BOLD | TERM_ATTR_ITALIC | TERM_ATTR_STRIKE | - TERM_ATTR_OVERLINE | TERM_ATTR_UNDERLINE, - .fg = TERM_COLOR_SLOT | 123, .bg = 0xff010203u, .history = -1, + .attrs = WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_ITALIC | WSAP_VTCORE_ATTR_STRIKE | + WSAP_VTCORE_ATTR_OVERLINE | WSAP_VTCORE_ATTR_UNDERLINE, + .fg = WSAP_VTCORE_COLOR_SLOT | 123, .bg = 0xff010203u, .history = -1, }, { .name = "SGR colon RGB with a color space", .input = "\033[38:2::1:2:3mX", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), - .attr_x = 0, .attr_y = 0, .fg = 0xff010203u, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 0, .attr_y = 0, .fg = 0xff010203u, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { /* 48:2:: takes the next three fields as RGB; the trailing 0 resets. */ .name = "SGR colon form is not two semicolon colors", .input = "\033[48:2::::38;2;;;mX", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), - .attr_x = 0, .attr_y = 0, .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 0, .attr_y = 0, .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { .name = "restore restores the pen", .input = "\033[31m\0337\033[m\0338X", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), - .attr_x = 0, .attr_y = 0, .fg = RED, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 0, .attr_y = 0, .fg = RED, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { .name = "SCORC restores the pen", .input = "\033[1m\033[s\033[m\033[uX", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), - .attr_x = 0, .attr_y = 0, .attrs = TERM_ATTR_BOLD, - .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 0, .attr_y = 0, .attrs = WSAP_VTCORE_ATTR_BOLD, + .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { .name = "restore without save resets the pen", .input = "\033[31m\0338X", .cols = 8, .rows = 3, ROWS3("X", "", ""), AT(1, 0), - .attr_x = 0, .attr_y = 0, .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 0, .attr_y = 0, .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { /* A rectangle edge on the right half of a wide glyph changes both * halves. */ .name = "DECCARA on half a wide glyph", .input = "a中b\033[1;3;1;3;1$r", .cols = 8, .rows = 3, ROWS3("a?_b", "", ""), AT(4, 0), - .attr_x = 1, .attr_y = 0, .attrs = TERM_ATTR_BOLD, - .fg = TERM_COLOR_FG, .bg = TERM_COLOR_BG, .history = -1, + .attr_x = 1, .attr_y = 0, .attrs = WSAP_VTCORE_ATTR_BOLD, + .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_BG, .history = -1, }, { .name = "erase uses the pen background", .input = "ab\033[41m\033[1;1H\033[X", .cols = 8, .rows = 3, ROWS3(" b", "", ""), AT(0, 0), - .attr_x = 0, .attr_y = 0, .fg = TERM_COLOR_FG, .bg = TERM_COLOR_SLOT | 1, .history = -1, + .attr_x = 0, .attr_y = 0, .fg = WSAP_VTCORE_COLOR_FG, .bg = WSAP_VTCORE_COLOR_SLOT | 1, .history = -1, }, { .name = "full-screen scroll BCE", .input = "abc\033[44m\r\n\r\n\r\n", .cols = 8, .rows = 3, ROWS3("", "", ""), AT(0, 2), .attr_x = 0, .attr_y = 2, - .fg = TERM_COLOR_FG, .bg = BLUE, .history = -1, + .fg = WSAP_VTCORE_COLOR_FG, .bg = BLUE, .history = -1, }, /* Replies. */ @@ -268,41 +268,41 @@ static void on_reply(void *ud, const char *bytes, size_t len) } } -static char cell_char(const struct term_snapshot *s, const struct term_cell *c) +static char cell_char(const struct wsap_vtcore_snapshot *s, const struct wsap_vtcore_cell *c) { if (c->width == 0) return '_'; uint32_t cps[4] = {0}; - int n = term_snapshot_cluster(s, c->text, cps, 4); + int n = wsap_vtcore_snapshot_cluster(s, c->text, cps, 4); if (n != 1) return '?'; if (cps[0] == 0xFFFD) return '#'; return cps[0] >= 0x20 && cps[0] < 0x7f ? (char)cps[0] : '?'; } -static int run(const struct spec *c, struct term_snapshot *s, bool bytes) +static int run(const struct spec *c, struct wsap_vtcore_snapshot *s, bool bytes) { struct replies got = {0}; - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = c->cols, .y = c->rows }, .scrollback = 100, .callbacks = { .ud = &got, .reply = on_reply }, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); if (!t) return 1; size_t len = strlen(c->input); if (bytes) - for (size_t i = 0; i < len; i++) term_feed(t, c->input + i, 1, 0); + for (size_t i = 0; i < len; i++) wsap_vtcore_feed(t, c->input + i, 1, 0); else - term_feed(t, c->input, len, 0); + wsap_vtcore_feed(t, c->input, len, 0); const char *mode = bytes ? "byte by byte" : "whole"; int bad = 0; - struct term_cursor cursor = term_cursor(t); + struct wsap_vtcore_cursor cursor = wsap_vtcore_cursor(t); if (cursor.pos.x != c->x || cursor.pos.y != c->y) { fprintf(stderr, "%s (%s): cursor %d,%d; expected %d,%d\n", c->name, mode, cursor.pos.x, cursor.pos.y, c->x, c->y); bad = 1; } - if (!term_snapshot_update(s, t)) return 1; + if (!wsap_vtcore_snapshot_update(s, t)) return 1; for (int y = 0; y < c->rows && y < 4; y++) { - const struct term_cell *row = term_snapshot_row(s, y); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, y); char text[64]; int n = 0; for (int x = 0; x < c->cols && n < 63; x++) text[n++] = cell_char(s, &row[x]); @@ -316,66 +316,66 @@ static int run(const struct spec *c, struct term_snapshot *s, bool bytes) } } if (c->attr_x >= 0) { - const struct term_cell *cell = &term_snapshot_row(s, c->attr_y)[c->attr_x]; + const struct wsap_vtcore_cell *cell = &wsap_vtcore_snapshot_row(s, c->attr_y)[c->attr_x]; if (cell->attrs != c->attrs || cell->fg != c->fg || cell->bg != c->bg) { fprintf(stderr, "%s (%s): attributes %x fg %x bg %x; expected %x %x %x\n", c->name, mode, cell->attrs, cell->fg, cell->bg, c->attrs, c->fg, c->bg); bad = 1; } } - if (c->history >= 0 && term_scrollback(t).total != c->history) { + if (c->history >= 0 && wsap_vtcore_scrollback(t).total != c->history) { fprintf(stderr, "%s (%s): history %d; expected %d\n", c->name, mode, - term_scrollback(t).total, c->history); + wsap_vtcore_scrollback(t).total, c->history); bad = 1; } if (c->reply && (got.len != strlen(c->reply) || memcmp(got.s, c->reply, got.len))) { fprintf(stderr, "%s (%s): reply differs\n", c->name, mode); bad = 1; } - term_free(t); + wsap_vtcore_free(t); return bad; } int main(void) { - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); if (!s) return 1; int failed = 0; for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) failed += run(&cases[i], s, false) | run(&cases[i], s, true); /* ONLCR is a feed option. A plain line feed keeps the column. */ - struct term_options opt = { .size = { .x = 8, .y = 2 } }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 8, .y = 2 } }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); if (!t) return 1; - term_feed(t, "ab\nZ", 4, TERM_FEED_ONLCR); - if (term_cursor(t).pos.x != 1 || term_cursor(t).pos.y != 1) { + wsap_vtcore_feed(t, "ab\nZ", 4, WSAP_VTCORE_FEED_ONLCR); + if (wsap_vtcore_cursor(t).pos.x != 1 || wsap_vtcore_cursor(t).pos.y != 1) { fprintf(stderr, "ONLCR: line feed did not return to column zero\n"); failed++; } - term_free(t); + wsap_vtcore_free(t); /* A long stream can skip old rows. A bare CR must keep the last rows. */ - opt.size = (struct term_vector2i){ .x = 8, .y = 3 }; + opt.size = (struct wsap_vtcore_vector2i){ .x = 8, .y = 3 }; opt.scrollback = 5; - t = term_new(&opt); + t = wsap_vtcore_new(&opt); if (!t) return 1; char *stream = malloc(13000u * 9u + 8u); if (!stream) return 1; for (int i = 0; i < 13000; i++) memcpy(stream + (size_t)i * 9, "1234567\r\n", 9); memcpy(stream + 13000u * 9u, "broken\rY", 8); - term_feed(t, stream, 13000u * 9u + 8u, 0); + wsap_vtcore_feed(t, stream, 13000u * 9u + 8u, 0); free(stream); - if (term_scrollback(t).total != 5) { + if (wsap_vtcore_scrollback(t).total != 5) { fprintf(stderr, "long stream: history count differs\n"); failed++; } for (int offset = 5;; offset = offset > 3 ? offset - 3 : 0) { - term_scroll_to(t, offset); - if (!term_snapshot_update(s, t)) return 1; + wsap_vtcore_scroll_to(t, offset); + if (!wsap_vtcore_snapshot_update(s, t)) return 1; for (int y = 0; y < 3; y++) { const char *want = offset == 0 && y == 2 ? "Yroken" : "1234567"; - const struct term_cell *row = term_snapshot_row(s, y); + const struct wsap_vtcore_cell *row = wsap_vtcore_snapshot_row(s, y); for (int x = 0; x < 8; x++) { uint32_t cp = x < (int)strlen(want) ? (unsigned char)want[x] : ' '; if (row[x].text != cp) { @@ -388,8 +388,8 @@ int main(void) } if (!offset) break; } - term_free(t); - term_snapshot_free(s); + wsap_vtcore_free(t); + wsap_vtcore_snapshot_free(s); if (failed) fprintf(stderr, "%d spec failures\n", failed); return failed != 0; } diff --git a/tests/symbols_test.sh b/tests/symbols_test.sh index 0343eb0..d787b72 100644 --- a/tests/symbols_test.sh +++ b/tests/symbols_test.sh @@ -1,12 +1,12 @@ #!/usr/bin/env bash -# Every global symbol of the term library starts with term_. A host links +# Every global symbol of the library starts with wsap_vtcore_. A host links # the library next to its own code, so a bare name such as palette_init can -# collide with a host symbol. Every function that term.h declares is also +# collide with a host symbol. Every function that wsap_vtcore.h declares is also # defined, so the library cannot leave one out. A shared build exports -# exactly the functions of term.h. +# exactly the functions of wsap_vtcore.h. set -euo pipefail lib=$1 -src=${2:-$(dirname "$0")/../include/term} +src=${2:-$(dirname "$0")/../include/wsap_vtcore} nm=${NM:-nm} defined_args=(-g --defined-only -P) @@ -21,14 +21,14 @@ defined=$(awk 'NF >= 2 && $2 ~ /^[A-Z]$/ && $2 != "U" { print $1 }' <<<"$syms" | grep -v '^_*odr_asan\.' | sed 's/^_//' | sort -u) status=0 -bad=$(grep -v '^term_' <<<"$defined" || true) +bad=$(grep -v '^wsap_vtcore_' <<<"$defined" || true) if [[ -n $bad ]]; then - echo "$lib: global symbols without the term_ prefix:" >&2 + echo "$lib: global symbols without the wsap_vtcore_ prefix:" >&2 echo "$bad" >&2 status=1 fi -declared=$("${CC:-cc}" -std=c11 -E -P -I"$src" "$src/term.h" | python3 -c ' +declared=$("${CC:-cc}" -std=c11 -E -P -I"$src" "$src/wsap_vtcore.h" | python3 -c ' import re, sys text = re.sub(r"\s+", " ", sys.stdin.read()) depth, flat = 0, [] @@ -42,18 +42,18 @@ for ch in text: for stmt in "".join(flat).split(";"): if "static" in stmt or "typedef" in stmt: continue - m = re.search(r"\b(term_\w+)\s*\(", stmt) + m = re.search(r"\b(wsap_vtcore_\w+)\s*\(", stmt) if m: print(m.group(1)) ' | sort -u) missing=$(comm -23 <(echo "$declared") <(echo "$defined")) if [[ -n $missing ]]; then - echo "$lib: functions declared in term.h but not defined:" >&2 + echo "$lib: functions declared in wsap_vtcore.h but not defined:" >&2 echo "$missing" >&2 status=1 fi -# The shared library exports term.h and nothing else. +# The shared library exports wsap_vtcore.h and nothing else. shared=${3:-} if [[ -n $shared ]]; then exported=$("$nm" "${exported_args[@]}" "$shared" | awk '$2 ~ /^[TDBRVW]$/ { print $1 }' | @@ -61,8 +61,8 @@ if [[ -n $shared ]]; then extra=$(comm -13 <(echo "$declared") <(echo "$exported")) absent=$(comm -23 <(echo "$declared") <(echo "$exported")) if [[ -n $extra || -n $absent ]]; then - echo "$shared: exports differ from term.h" >&2 - [[ -n $extra ]] && echo "not in term.h: $extra" >&2 + echo "$shared: exports differ from wsap_vtcore.h" >&2 + [[ -n $extra ]] && echo "not in wsap_vtcore.h: $extra" >&2 [[ -n $absent ]] && echo "not exported: $absent" >&2 status=1 fi diff --git a/tests/term_test.c b/tests/term_test.c index 235e9df..0e7d986 100644 --- a/tests/term_test.c +++ b/tests/term_test.c @@ -1,6 +1,6 @@ #include "term_api.h" -#include "term/unicode/unicode.h" -#include "term/unicode/utf8.h" +#include "wsap_vtcore/unicode/unicode.h" +#include "wsap_vtcore/unicode/utf8.h" #include <assert.h> #include <limits.h> #include <pthread.h> @@ -27,21 +27,21 @@ static void capture_title(void *ud, const char *s) (void)ud; snprintf(title, sizeof(title), "%s", s); } -static const struct term_callbacks reply_cb = { .reply = respond }; -static const struct term_callbacks title_cb = { .reply = respond, .title = capture_title }; +static const struct wsap_vtcore_callbacks reply_cb = { .reply = respond }; +static const struct wsap_vtcore_callbacks title_cb = { .reply = respond, .title = capture_title }; -static void write_seq(struct term *t, const char *s) +static void write_seq(struct wsap_vtcore *t, const char *s) { for (; *s; s++) tt_write(t, s, 1); } -static void feed_seq(struct term *t, const char *s, unsigned flags) +static void feed_seq(struct wsap_vtcore *t, const char *s, unsigned flags) { - for (; *s; s++) term_feed(t, s, 1, flags); + for (; *s; s++) wsap_vtcore_feed(t, s, 1, flags); } -static const char *row_text(struct term *t, int r, char *buf) +static const char *row_text(struct wsap_vtcore *t, int r, char *buf) { - const struct term_cell *cells = term_snapshot_row(tt_snapshot_for(t), r); + const struct wsap_vtcore_cell *cells = wsap_vtcore_snapshot_row(tt_snapshot_for(t), r); int n = 0; for (int c = 0; c < tt_cols(t); c++) { uint32_t cp = tt_cell_cp(t, &cells[c]); @@ -52,7 +52,7 @@ static const char *row_text(struct term *t, int r, char *buf) buf[n] = 0; return buf; } -static bool row_eq(struct term *t, int r, const char *want) +static bool row_eq(struct wsap_vtcore *t, int r, const char *want) { char *got = malloc((size_t)tt_cols(t) + 1); assert(got); @@ -60,7 +60,7 @@ static bool row_eq(struct term *t, int r, const char *want) free(got); return equal; } -static bool row_is(struct term *t, int r, const char *want) +static bool row_is(struct wsap_vtcore *t, int r, const char *want) { char *got = malloc((size_t)tt_cols(t) + 1); assert(got); @@ -71,7 +71,7 @@ static bool row_is(struct term *t, int r, const char *want) return equal; } -static void write_both(struct term *whole, struct term *bytes, const char *s) +static void write_both(struct wsap_vtcore *whole, struct wsap_vtcore *bytes, const char *s) { tt_write(whole, s, strlen(s)); write_seq(bytes, s); @@ -79,10 +79,10 @@ static void write_both(struct term *whole, struct term *bytes, const char *s) /* The view version of s after it copies t. A renderer redraws when the * version changes. */ -static uint64_t view_version(struct term_snapshot *s, struct term *t) +static uint64_t view_version(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t) { - term_snapshot_update(s, t); - return term_snapshot_view(s)->version; + wsap_vtcore_snapshot_update(s, t); + return wsap_vtcore_snapshot_view(s)->version; } /* @@ -102,12 +102,12 @@ static void test_skipped_cells_read_blank(void) /* row_text() reads U+2026 as '?'. */ static const char *const want[] = { "ab cd ef", "a?b c", "ab cd" }; for (size_t k = 0; k < sizeof(lines) / sizeof(lines[0]); k++) { - struct term *whole = tt_new(20, 4); - struct term *bytes = tt_new(20, 4); + struct wsap_vtcore *whole = tt_new(20, 4); + struct wsap_vtcore *bytes = tt_new(20, 4); for (int i = 0; i < 12; i++) write_both(whole, bytes, "XXXXXXXXXXXXXXXXXXXX\r\n"); write_both(whole, bytes, lines[k]); - for (struct term *t = whole; t; t = t == whole ? bytes : NULL) { + for (struct wsap_vtcore *t = whole; t; t = t == whole ? bytes : NULL) { char *got = malloc((size_t)tt_cols(t) + 1); assert(got); row_text(t, 3, got); @@ -118,39 +118,39 @@ static void test_skipped_cells_read_blank(void) } free(got); } - term_free(whole); - term_free(bytes); + wsap_vtcore_free(whole); + wsap_vtcore_free(bytes); } - struct term *whole = tt_new(20, 4); - struct term *bytes = tt_new(20, 4); + struct wsap_vtcore *whole = tt_new(20, 4); + struct wsap_vtcore *bytes = tt_new(20, 4); write_both(whole, bytes, "abcdefgh\r\033[2C\033[K\033[2CZ"); assert(row_is(whole, 0, "ab Z")); assert(row_is(bytes, 0, "ab Z")); - term_free(whole); - term_free(bytes); + wsap_vtcore_free(whole); + wsap_vtcore_free(bytes); } /* Compare the first rows of both viewports cell by cell. Each terminal gets * its own snapshot. A cluster has a different handle in each snapshot, so * the test compares its code points. */ -static void assert_same_rows(struct term *a, struct term *b, int rows) +static void assert_same_rows(struct wsap_vtcore *a, struct wsap_vtcore *b, int rows) { - struct term_snapshot *sa = term_snapshot_new(); - struct term_snapshot *sb = term_snapshot_new(); - bool copied = sa && sb && term_snapshot_update(sa, a) && term_snapshot_update(sb, b); + struct wsap_vtcore_snapshot *sa = wsap_vtcore_snapshot_new(); + struct wsap_vtcore_snapshot *sb = wsap_vtcore_snapshot_new(); + bool copied = sa && sb && wsap_vtcore_snapshot_update(sa, a) && wsap_vtcore_snapshot_update(sb, b); assert(copied); - int cols = term_snapshot_view(sa)->size.x; - assert(cols == term_snapshot_view(sb)->size.x); + int cols = wsap_vtcore_snapshot_view(sa)->size.x; + assert(cols == wsap_vtcore_snapshot_view(sb)->size.x); for (int y = 0; y < rows; y++) { - const struct term_cell *ra = term_snapshot_row(sa, y); - const struct term_cell *rb = term_snapshot_row(sb, y); + const struct wsap_vtcore_cell *ra = wsap_vtcore_snapshot_row(sa, y); + const struct wsap_vtcore_cell *rb = wsap_vtcore_snapshot_row(sb, y); assert(ra && rb); for (int x = 0; x < cols; x++) { - const struct term_cell *ac = &ra[x], *bc = &rb[x]; + const struct wsap_vtcore_cell *ac = &ra[x], *bc = &rb[x]; uint32_t acp[32], bcp[32]; - int an = term_snapshot_cluster(sa, ac->text, acp, 32); - int bn = term_snapshot_cluster(sb, bc->text, bcp, 32); + int an = wsap_vtcore_snapshot_cluster(sa, ac->text, acp, 32); + int bn = wsap_vtcore_snapshot_cluster(sb, bc->text, bcp, 32); bool same = an == bn && an <= 32 && !memcmp(acp, bcp, (size_t)an * sizeof(*acp)) && ac->fg == bc->fg && ac->bg == bc->bg && @@ -164,16 +164,16 @@ static void assert_same_rows(struct term *a, struct term *b, int rows) } } } - term_snapshot_free(sa); - term_snapshot_free(sb); + wsap_vtcore_snapshot_free(sa); + wsap_vtcore_snapshot_free(sb); } -static void assert_same_screen(struct term *a, struct term *b) +static void assert_same_screen(struct wsap_vtcore *a, struct wsap_vtcore *b) { assert(tt_cursor_x(a) == tt_cursor_x(b)); assert(tt_cursor_y(a) == tt_cursor_y(b)); assert(tt_history(a) == tt_history(b)); - assert(term_modes(a).synchronized == term_modes(b).synchronized); + assert(wsap_vtcore_modes(a).synchronized == wsap_vtcore_modes(b).synchronized); assert(tt_rows(a) == tt_rows(b)); assert_same_rows(a, b, tt_rows(a)); } @@ -187,24 +187,24 @@ static void test_read_boundaries(void) "\033[?1049halt\033[?1049lZ" "\033]11;?\007\033Pignored\033\\" "\xf0\x9f\x98\x80\xc3XQ©️界\033[2G\033[P"; - struct term *expected = tt_new(16, 4); + struct wsap_vtcore *expected = tt_new(16, 4); tt_write(expected, input, sizeof(input) - 1); for (size_t split = 0; split < sizeof(input); split++) { - struct term *actual = tt_new(16, 4); + struct wsap_vtcore *actual = tt_new(16, 4); tt_write(actual, input, split); tt_write(actual, input + split, sizeof(input) - 1 - split); assert_same_screen(actual, expected); - term_free(actual); + wsap_vtcore_free(actual); } /* The byte that ends an unfinished sequence is not lost. */ - struct term *t = tt_new(16, 4); + struct wsap_vtcore *t = tt_new(16, 4); write_seq(t, "\xc3XQ"); assert(tt_cell_cp(t, tt_cell(t, 0, 0)) == 0xFFFD); assert(tt_cell_cp(t, tt_cell(t, 1, 0)) == 'X'); assert(tt_cell_cp(t, tt_cell(t, 2, 0)) == 'Q'); - term_free(t); - term_free(expected); + wsap_vtcore_free(t); + wsap_vtcore_free(expected); } static void test_ascii_controls(void) @@ -218,8 +218,8 @@ static void test_ascii_controls(void) memcpy(input + 29, separators[c], n); memset(input + 29 + n, 'b', 173); input[202 + n] = '\0'; - struct term *bulk = tt_new(120, 6); - struct term *bytes = tt_new(120, 6); + struct wsap_vtcore *bulk = tt_new(120, 6); + struct wsap_vtcore *bytes = tt_new(120, 6); const char *setup = bottom ? "\033[6;1H\033[1;3;4;38;2;12;34;56m" : "\033[1;3;4;38;2;12;34;56m"; write_seq(bulk, setup); @@ -227,18 +227,18 @@ static void test_ascii_controls(void) tt_write(bulk, input, strlen(input)); write_seq(bytes, input); assert_same_screen(bulk, bytes); - term_scroll(bulk, 6); - term_scroll(bytes, 6); + wsap_vtcore_scroll(bulk, 6); + wsap_vtcore_scroll(bytes, 6); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } } } static void test_esc_control_strings_and_designators(void) { - struct term *t = tt_new(32, 2); + struct wsap_vtcore *t = tt_new(32, 2); assert(t); write_seq(t, "A\033_payload ignored\033\\B"); @@ -253,13 +253,13 @@ static void test_esc_control_strings_and_designators(void) write_seq(t, "\033.Am\033*0n"); assert(row_is(t, 0, "ABCDxyz%qxmn")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(8, 2); write_seq(t, "A\033_ignored\033DB"); assert(row_is(t, 0, "A")); assert(row_is(t, 1, " B")); - term_free(t); + wsap_vtcore_free(t); } static void test_random_read_boundaries(void) @@ -277,11 +277,11 @@ static void test_random_read_boundaries(void) input[i] = (char)(random >> 16); } memcpy(input + 400, embedded, sizeof(embedded) - 1); - struct term *whole = tt_new(32, 8); + struct wsap_vtcore *whole = tt_new(32, 8); tt_write(whole, input, sizeof(input)); for (size_t c = 0; c < sizeof(chunks) / sizeof(chunks[0]); c++) { - struct term *a = tt_new(32, 8); - struct term *b = tt_new(32, 8); + struct wsap_vtcore *a = tt_new(32, 8); + struct wsap_vtcore *b = tt_new(32, 8); for (size_t block = 0; block < sizeof(input); block += 128) { tt_write(a, input + block, 128); for (size_t i = block; i < block + 128;) { @@ -298,14 +298,14 @@ static void test_random_read_boundaries(void) assert_same_screen(a, b); int history = tt_history(a); for (int i = 0; i < history; i += 8) { - term_scroll(a, 8); - term_scroll(b, 8); + wsap_vtcore_scroll(a, 8); + wsap_vtcore_scroll(b, 8); assert_same_screen(a, b); } - term_free(a); - term_free(b); + wsap_vtcore_free(a); + wsap_vtcore_free(b); } - term_free(whole); + wsap_vtcore_free(whole); } } @@ -330,13 +330,13 @@ static void test_csi_recovery(void) for (size_t c = 0; c < sizeof(cases) / sizeof(cases[0]); c++) { size_t len = strlen(cases[c].input); for (size_t split = 0; split <= len; split++) { - struct term *t = tt_new(20, 4); + struct wsap_vtcore *t = tt_new(20, 4); tt_write(t, cases[c].input, split); tt_write(t, cases[c].input + split, len - split); assert(row_is(t, 0, cases[c].first)); assert(row_is(t, 1, cases[c].second)); - for (int x = 0; x < 20; x++) assert(tt_cell(t, x, 0)->fg == TERM_COLOR_FG); - term_free(t); + for (int x = 0; x < 20; x++) assert(tt_cell(t, x, 0)->fg == WSAP_VTCORE_COLOR_FG); + wsap_vtcore_free(t); } } } @@ -353,31 +353,31 @@ static void test_csi_byte_boundaries(void) static const char suffix[] = "mX\033[6n\033[?25l\033[?25h\033[0mY"; memcpy(input + n, suffix, sizeof(suffix) - 1); n += sizeof(suffix) - 1; - struct term *whole = tt_new_opts(20, 4, &reply_cb); + struct wsap_vtcore *whole = tt_new_opts(20, 4, &reply_cb); response_len = 0; tt_write(whole, input, n); char expected_response[64]; size_t expected_len = response_len; memcpy(expected_response, response, expected_len); for (size_t split = 0; split <= strlen(prefixes[p]) + 2; split++) { - struct term *parts = tt_new_opts(20, 4, &reply_cb); + struct wsap_vtcore *parts = tt_new_opts(20, 4, &reply_cb); response_len = 0; tt_write(parts, input, split); tt_write(parts, input + split, n - split); assert_same_screen(whole, parts); - assert(term_cursor(whole).visible == term_cursor(parts).visible); + assert(wsap_vtcore_cursor(whole).visible == wsap_vtcore_cursor(parts).visible); assert(response_len == expected_len); assert(!memcmp(response, expected_response, expected_len)); - term_free(parts); + wsap_vtcore_free(parts); } - term_free(whole); + wsap_vtcore_free(whole); } } } static void test_parameter_limits(void) { - struct term *t = tt_new(10, 4); + struct wsap_vtcore *t = tt_new(10, 4); write_seq(t, "\033[2;4r\033[?6h\033[999999999999999999999;1H"); assert(tt_cursor_y(t) == 3 && tt_cursor_x(t) == 0); write_seq(t, "\033[?6l\033[r"); @@ -387,26 +387,26 @@ static void test_parameter_limits(void) write_seq(t, "\033[999999999999999999999A\033[999999999999999999999D"); assert(tt_cursor_y(t) == 0 && tt_cursor_x(t) == 0); write_seq(t, "\033[38;5;999999999999999999999mX"); - assert(tt_cell(t, 0, 0)->fg == TERM_COLOR_FG); + assert(tt_cell(t, 0, 0)->fg == WSAP_VTCORE_COLOR_FG); /* A renderer sees the cursor move to another row. */ - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); uint64_t version = view_version(snap, t); write_seq(t, "\033[3d"); assert(tt_cursor_y(t) == 2 && view_version(snap, t) != version); - term_snapshot_free(snap); + wsap_vtcore_snapshot_free(snap); write_seq(t, "\033[4;8H\0337"); tt_resize(t, 5, 2); write_seq(t, "\0338Z"); assert(tt_cursor_y(t) == 1 && tt_cursor_x(t) == 3); assert(tt_cell(t, 2, 1)->text == 'Z'); - term_free(t); + wsap_vtcore_free(t); } static void test_unterminated_control_strings_do_not_swallow_text(void) { - struct term *t = tt_new(20, 4); + struct wsap_vtcore *t = tt_new(20, 4); assert(t); write_seq(t, "A\033]0;random bytes\tgit\r\nstatus"); @@ -417,7 +417,7 @@ static void test_unterminated_control_strings_do_not_swallow_text(void) assert(row_is(t, 1, "status branch")); assert(row_is(t, 2, "next")); - term_free(t); + wsap_vtcore_free(t); char overlong[1200]; for (int intro = 0; intro < 2; intro++) { @@ -425,35 +425,35 @@ static void test_unterminated_control_strings_do_not_swallow_text(void) memset(overlong + n, 'T', 1024); overlong[n + 1024] = '\0'; - struct term *u = tt_new(20, 4); + struct wsap_vtcore *u = tt_new(20, 4); write_seq(u, overlong); write_seq(u, "\r\n[sudo] password:"); assert(row_is(u, 0, "")); assert(row_is(u, 1, "[sudo] password:")); - term_free(u); + wsap_vtcore_free(u); - struct term *d = tt_new(20, 4); + struct wsap_vtcore *d = tt_new(20, 4); write_seq(d, overlong); write_seq(d, "\033\\after"); assert(row_is(d, 0, "after")); - term_free(d); + wsap_vtcore_free(d); } } static void test_c0_controls_after_esc_are_executed(void) { - struct term *t = tt_new(20, 4); + struct wsap_vtcore *t = tt_new(20, 4); assert(t); write_seq(t, "A\033\tB"); assert(row_is(t, 0, "A B")); - term_free(t); + wsap_vtcore_free(t); } static void test_resize_reflow(void) { - struct term *t = tt_new(8, 4); + struct wsap_vtcore *t = tt_new(8, 4); write_seq(t, "abcdefghijkl"); tt_resize(t, 16, 4); assert(row_is(t, 0, "abcdefghijkl") && row_is(t, 1, "")); @@ -469,16 +469,16 @@ static void test_resize_reflow(void) free(text); tt_resize(t, 20, 4); assert(row_is(t, 0, "abcdefghijklM")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(6, 6); write_seq(t, "\033[31mab cdef\033[m\r\nnext"); - term_color red = tt_cell(t, 0, 0)->fg; + wsap_vtcore_color red = tt_cell(t, 0, 0)->fg; tt_resize(t, 12, 6); assert(row_is(t, 0, "ab cdef") && row_is(t, 1, "next")); assert(tt_cell(t, 7, 0)->fg == red); - assert(tt_cell(t, 0, 1)->fg == TERM_COLOR_FG); - term_free(t); + assert(tt_cell(t, 0, 1)->fg == WSAP_VTCORE_COLOR_FG); + wsap_vtcore_free(t); t = tt_new(4, 2); write_seq(t, "abcdefghijkl"); @@ -493,7 +493,7 @@ static void test_resize_reflow(void) assert(row_is(t, 0, "ijkl") && row_is(t, 1, "M")); tt_resize(t, 20, 2); assert(row_is(t, 0, "abcdefghijklM")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(4, 3); write_seq(t, "abcd"); @@ -503,7 +503,7 @@ static void test_resize_reflow(void) tt_resize(t, 5, 3); write_seq(t, "F"); assert(row_is(t, 0, "abcdE") && row_is(t, 1, "F")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(4, 4); write_seq(t, "abcdefghijkl\033[?1049h12345678"); @@ -513,14 +513,14 @@ static void test_resize_reflow(void) write_seq(t, "\033[?1049lM"); assert(row_is(t, 0, "abcdefghijklM")); assert(tt_cursor_y(t) == 0 && tt_cursor_x(t) == 13); - term_free(t); + wsap_vtcore_free(t); t = tt_new(4, 2); write_seq(t, "abcd"); tt_resize(t, 4, 3); write_seq(t, "E"); assert(row_is(t, 0, "abcd") && row_is(t, 1, "E")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(80, 4); for (int i = 0; i < 1000; i++) write_seq(t, "abcdefgh"); @@ -532,22 +532,22 @@ static void test_resize_reflow(void) assert(tt_cursor_x(t) < 80 && tt_cursor_y(t) < 4); write_seq(t, "Z"); assert(tt_cell(t, 0, 3)->text == 'Z'); - term_free(t); + wsap_vtcore_free(t); } static void test_resize_exposes_blank_rows(void) { - struct term *t = tt_new(20, 2); + struct wsap_vtcore *t = tt_new(20, 2); write_seq(t, "kept"); for (int pass = 0; pass < 2; pass++) { tt_resize(t, 20, 6); assert(row_is(t, 0, "kept")); for (int y = 2; y < 6; y++) { for (int x = 0; x < 20; x++) { - const struct term_cell *cell = tt_cell(t, x, y); - assert(cell->text == ' ' && cell->fg == TERM_COLOR_FG); - assert(cell->bg == TERM_COLOR_BG && cell->attrs == 0 && cell->width == 1); + const struct wsap_vtcore_cell *cell = tt_cell(t, x, y); + assert(cell->text == ' ' && cell->fg == WSAP_VTCORE_COLOR_FG); + assert(cell->bg == WSAP_VTCORE_COLOR_BG && cell->attrs == 0 && cell->width == 1); } } write_seq(t, "\033[6;1H\tfile/"); @@ -555,12 +555,12 @@ static void test_resize_exposes_blank_rows(void) write_seq(t, "\033[1;1H"); tt_resize(t, 20, 2); } - term_free(t); + wsap_vtcore_free(t); } static void test_prompt_resize(void) { - struct term *t = tt_new(80, 6); + struct wsap_vtcore *t = tt_new(80, 6); const char *prompt = "~/Documents/GitHub/clernen_pi main> "; write_seq(t, "\033]133;A;click_events=1\033\\"); write_seq(t, prompt); @@ -596,7 +596,7 @@ static void test_prompt_resize(void) tt_resize(t, 20, 6); assert(row_is(t, 0, "~/Documents/GitHub/c")); assert(row_is(t, 1, "lernen_pi main>")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(20, 6); write_seq(t, "abcdefghijklmnop\r\n\033]133;A\007prompt> input\033]133;B\007"); @@ -605,12 +605,12 @@ static void test_prompt_resize(void) assert(row_is(t, 2, "prompt>")); tt_resize(t, 30, 6); assert(row_is(t, 0, "abcdefghijklmnop") && row_is(t, 1, "prompt>")); - term_free(t); + wsap_vtcore_free(t); } static void test_cursor_line_motion(void) { - struct term *t = tt_new(80, 9); + struct wsap_vtcore *t = tt_new(80, 9); assert(t); const char *lines = "one\r\ntwo\r\nthree\r\nfour\r\nfive\r\nsix\r\nseven\r\n"; tt_write(t, lines, strlen(lines)); @@ -619,12 +619,12 @@ static void test_cursor_line_motion(void) assert(row_is(t, 1, "two revised")); assert(row_is(t, 3, "four revised")); assert(row_is(t, 0, "one revised")); - term_free(t); + wsap_vtcore_free(t); } static void test_relative_cursor_motion(void) { - struct term *t = tt_new(10, 5); + struct wsap_vtcore *t = tt_new(10, 5); assert(t); const char *text = "0123456789\r\nabcdefghij\r\nklmnopqrst"; tt_write(t, text, strlen(text)); @@ -634,7 +634,7 @@ static void test_relative_cursor_motion(void) assert(tt_cell(t, 5, 2)->text == 'Y'); assert(tt_cell(t, 6, 3)->text == 'Z'); assert(tt_cell(t, 7, 1)->text == 'W'); - term_free(t); + wsap_vtcore_free(t); } static void test_top_region_scrollback(void) @@ -651,7 +651,7 @@ static void test_top_region_scrollback(void) {"\033[99S", 4}, }; for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { - struct term *t = tt_new(12, 6); + struct wsap_vtcore *t = tt_new(12, 6); write_seq(t, "one\r\ntwo\r\nthree\r\nfour\r\nPROMPT\r\nSTATUS"); write_seq(t, "\033[1;4r\033[4;1H"); write_seq(t, cases[i].scroll); @@ -660,15 +660,15 @@ static void test_top_region_scrollback(void) cases[i].lines == 2 ? "three" : "")); assert(row_is(t, 3, "")); assert(row_is(t, 4, "PROMPT") && row_is(t, 5, "STATUS")); - term_scroll(t, cases[i].lines); + wsap_vtcore_scroll(t, cases[i].lines); assert(tt_view_offset(t) == cases[i].lines); assert(row_is(t, 0, "one") && row_is(t, 1, "two")); - term_free(t); + wsap_vtcore_free(t); } /* Retain the same history as a full screen after the ring wraps. */ - struct term *t = tt_new(12, 6); - struct term *reference = tt_new(12, 4); + struct wsap_vtcore *t = tt_new(12, 6); + struct wsap_vtcore *reference = tt_new(12, 4); const char *footer = "\033[5;1H\033[31mPROMPT\r\nSTATUS\033[m\033[1;4r"; tt_write(t, footer, strlen(footer)); for (int i = 0; i < 2 * TEST_SCROLLBACK; i++) { @@ -682,19 +682,19 @@ static void test_top_region_scrollback(void) assert(tt_cursor_y(t) == tt_cursor_y(reference)); assert(row_is(t, 4, "PROMPT") && row_is(t, 5, "STATUS")); assert(tt_cell(t, 0, 4)->fg == tt_cell(t, 0, 5)->fg); - assert(tt_cell(t, 0, 4)->fg != TERM_COLOR_FG); + assert(tt_cell(t, 0, 4)->fg != WSAP_VTCORE_COLOR_FG); for (int i = 0; i <= tt_history(reference); i++) { assert_same_rows(t, reference, tt_rows(reference)); - term_scroll(t, 1); - term_scroll(reference, 1); + wsap_vtcore_scroll(t, 1); + wsap_vtcore_scroll(reference, 1); } - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } static void test_editor_scrolling(void) { - struct term *t = tt_new(80, 24); + struct wsap_vtcore *t = tt_new(80, 24); write_seq(t, "\033[?1049hTITLE"); for (int i = 1; i <= 20; i++) { char line[64]; @@ -711,7 +711,7 @@ static void test_editor_scrolling(void) assert(row_is(t, 22, "HELP") && row_is(t, 23, "FOOTER")); assert(tt_cursor_x(t) == 0 && tt_cursor_y(t) == 3); assert(tt_history(t) == 0); - term_free(t); + wsap_vtcore_free(t); t = tt_new(12, 6); write_seq(t, "old\r\nHEAD\r\nA\r\nB\r\nC\r\nD\r\nFOOT"); @@ -736,7 +736,7 @@ static void test_editor_scrolling(void) for (int r = 1; r <= 4; r++) { assert(row_is(t, r, "")); assert(tt_cell(t, 0, r)->bg == tt_cell(t, 11, r)->bg); - assert(tt_cell(t, 0, r)->bg != TERM_COLOR_BG); + assert(tt_cell(t, 0, r)->bg != WSAP_VTCORE_COLOR_BG); } assert(tt_history(t) == 1); @@ -746,117 +746,117 @@ static void test_editor_scrolling(void) tt_resize(t, 12, 4); write_seq(t, "\033[4;1H\033[2Kend\n"); assert(tt_cursor_y(t) == 3 && row_is(t, 2, "end")); - term_free(t); + wsap_vtcore_free(t); } static bool pending_decsca_decsed_decsel(void) { - struct term *d = tt_new(20, 3); + struct wsap_vtcore *d = tt_new(20, 3); write_seq(d, "\033[H" "AB" "\033[1\"q" "CD" "\033[0\"q" "EF"); write_seq(d, "\033[?2J"); bool ok = row_eq(d, 0, " CD"); - term_free(d); + wsap_vtcore_free(d); - struct term *l = tt_new(20, 3); + struct wsap_vtcore *l = tt_new(20, 3); write_seq(l, "\033[H" "GH" "\033[1\"q" "IJ" "\033[0\"q" "KL"); write_seq(l, "\033[H\033[?0K"); ok = ok && row_eq(l, 0, " IJ"); - term_free(l); + wsap_vtcore_free(l); return ok; } static bool pending_decfra_decera(void) { - struct term *f = tt_new(20, 3); + struct wsap_vtcore *f = tt_new(20, 3); write_seq(f, "\033[88;1;2;2;4$x"); bool ok = row_eq(f, 0, " XXX") && row_eq(f, 1, " XXX"); - term_free(f); + wsap_vtcore_free(f); - struct term *e = tt_new(20, 3); + struct wsap_vtcore *e = tt_new(20, 3); write_seq(e, "\033[Habcde\r\nfghij"); write_seq(e, "\033[1;2;2;3$z"); ok = ok && row_eq(e, 0, "a de") && row_eq(e, 1, "f ij"); - term_free(e); + wsap_vtcore_free(e); return ok; } static bool pending_deccra(void) { - struct term *t = tt_new(20, 3); + struct wsap_vtcore *t = tt_new(20, 3); write_seq(t, "\033[HAB\r\nCD"); write_seq(t, "\033[1;1;2;2;1;1;5;1$v"); bool ok = row_eq(t, 0, "AB AB") && row_eq(t, 1, "CD CD"); - term_free(t); + wsap_vtcore_free(t); return ok; } static bool pending_decrara(void) { - struct term *t = tt_new(20, 3); + struct wsap_vtcore *t = tt_new(20, 3); write_seq(t, "\033[H\033[1mAB\033[mCD"); write_seq(t, "\033[1;1;1;4;1$t"); - bool ok = !(tt_cell(t, 0, 0)->attrs & TERM_ATTR_BOLD) && - (tt_cell(t, 2, 0)->attrs & TERM_ATTR_BOLD); - term_free(t); + bool ok = !(tt_cell(t, 0, 0)->attrs & WSAP_VTCORE_ATTR_BOLD) && + (tt_cell(t, 2, 0)->attrs & WSAP_VTCORE_ATTR_BOLD); + wsap_vtcore_free(t); return ok; } static bool pending_decsera(void) { - struct term *t = tt_new(20, 3); + struct wsap_vtcore *t = tt_new(20, 3); write_seq(t, "\033[H\033[0\"qAB\033[1\"qCD"); write_seq(t, "\033[1;1;1;4${"); bool ok = row_eq(t, 0, " CD"); - term_free(t); + wsap_vtcore_free(t); return ok; } static bool pending_deccolm(void) { - struct term *t = tt_new(80, 4); + struct wsap_vtcore *t = tt_new(80, 4); write_seq(t, "\033[?40h" "keep" "\033[?3h"); bool ok = tt_cols(t) == 132 && row_eq(t, 0, "") && tt_cursor_x(t) == 0 && tt_cursor_y(t) == 0; write_seq(t, "\033[?3l"); ok = ok && tt_cols(t) == 80; - term_free(t); + wsap_vtcore_free(t); return ok; } static bool pending_decic_decdc(void) { - struct term *i = tt_new(10, 2); + struct wsap_vtcore *i = tt_new(10, 2); write_seq(i, "\033[Habcdef\033[H\033[2'}"); bool ok = row_eq(i, 0, " abcdef"); - term_free(i); + wsap_vtcore_free(i); - struct term *d = tt_new(10, 2); + struct wsap_vtcore *d = tt_new(10, 2); write_seq(d, "\033[Habcdef\033[H\033[2'~"); ok = ok && row_eq(d, 0, "cdef"); - term_free(d); + wsap_vtcore_free(d); return ok; } static bool pending_sl_sr(void) { - struct term *l = tt_new(10, 2); + struct wsap_vtcore *l = tt_new(10, 2); write_seq(l, "\033[Habcdef\033[2 @"); bool ok = row_eq(l, 0, "cdef"); - term_free(l); + wsap_vtcore_free(l); - struct term *r = tt_new(10, 2); + struct wsap_vtcore *r = tt_new(10, 2); write_seq(r, "\033[Habcdef\033[2 A"); ok = ok && row_eq(r, 0, " abcdef"); - term_free(r); + wsap_vtcore_free(r); return ok; } static bool pending_sixel(void) { - struct term *t = tt_new(20, 6); + struct wsap_vtcore *t = tt_new(20, 6); write_seq(t, "\033[H\033Pq#0;2;100;100;100#0~~~~\033\\"); bool ok = tt_cursor_y(t) > 0; - term_free(t); + wsap_vtcore_free(t); return ok; } @@ -888,7 +888,7 @@ static void test_unimplemented_da_features(void) static void test_device_attributes(void) { - struct term *t = tt_new_opts(80, 24, &reply_cb); + struct wsap_vtcore *t = tt_new_opts(80, 24, &reply_cb); write_seq(t, "\033[c"); assert(!strcmp(response, "\033[?62;22c")); @@ -903,10 +903,10 @@ static void test_device_attributes(void) write_seq(t, "\033[=c"); assert(response_len == 0); - term_free(t); + wsap_vtcore_free(t); } -static void expect_flags(struct term *t, const char *commands, const char *reply) +static void expect_flags(struct wsap_vtcore *t, const char *commands, const char *reply) { write_seq(t, commands); write_seq(t, "\033[?u"); @@ -914,12 +914,12 @@ static void expect_flags(struct term *t, const char *commands, const char *reply } static void test_keyboard_negotiation(void) { - struct term *t = tt_new_opts(80, 24, &reply_cb); - assert(!term_modes(t).app_cursor); + struct wsap_vtcore *t = tt_new_opts(80, 24, &reply_cb); + assert(!wsap_vtcore_modes(t).app_cursor); write_seq(t, "\033[?1h"); - assert(term_modes(t).app_cursor); + assert(wsap_vtcore_modes(t).app_cursor); write_seq(t, "\033[?1l"); - assert(!term_modes(t).app_cursor); + assert(!wsap_vtcore_modes(t).app_cursor); expect_flags(t, "", "\033[?0u"); expect_flags(t, "\033[=1u", "\033[?1u"); expect_flags(t, "\033[>3u\033[>31u", "\033[?31u"); @@ -943,10 +943,10 @@ static void test_keyboard_negotiation(void) expect_flags(t, "\033[<2147483647u", "\033[?0u"); write_seq(t, "hello"); assert(row_is(t, 0, "hello")); - term_free(t); + wsap_vtcore_free(t); } -static void expect_selection(struct term *t, int x1, int y1, int x2, int y2, const char *want) +static void expect_selection(struct wsap_vtcore *t, int x1, int y1, int x2, int y2, const char *want) { tt_select(t, x1, y1, x2, y2); char *text = tt_selection_text(t); @@ -958,7 +958,7 @@ static void expect_selection(struct term *t, int x1, int y1, int x2, int y2, con static void test_wide_characters(void) { - struct term *t = tt_new(8, 4); + struct wsap_vtcore *t = tt_new(8, 4); write_seq(t, "A😀界B"); assert(tt_cursor_x(t) == 6); assert(tt_cell(t, 1, 0)->text == 0x1f600 && tt_cell(t, 3, 0)->text == 0x754c); @@ -974,7 +974,7 @@ static void test_wide_characters(void) write_seq(t, "\033[4;1H😀\r \033[4;1H😀\033[4;2H\033[38;2;1;2;3mX"); assert(row_is(t, 3, " X")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(5, 8); write_seq(t, "abcd😀Z"); @@ -991,7 +991,7 @@ static void test_wide_characters(void) tt_resize(t, 12, 8); expect_selection(t, 0, 0, 11, 0, "abcd😀Z"); assert(tt_cursor_x(t) == 7); - term_free(t); + wsap_vtcore_free(t); t = tt_new(4, 3); write_seq(t, "abc©️)"); @@ -1002,16 +1002,16 @@ static void test_wide_characters(void) expect_selection(t, 0, 0, 3, 0, "😀︎x"); write_seq(t, "\033[2J\033[H\033[?7labc😀"); assert(tt_cursor_y(t) == 0 && tt_cursor_x(t) == 3); - term_free(t); + wsap_vtcore_free(t); t = tt_new(4, 2); write_seq(t, "😀😀界界AB"); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); expect_selection(t, 0, 0, 3, 1, "😀😀界界"); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); tt_resize(t, 10, 2); expect_selection(t, 0, 0, 9, 0, "😀😀界界AB"); - term_free(t); + wsap_vtcore_free(t); } static void test_wide_runs(void) @@ -1029,15 +1029,15 @@ static void test_wide_runs(void) for (size_t k = 0; k < sizeof(runs) / sizeof(*runs); k++) { char text[512]; snprintf(text, sizeof(text), "\033[999;1H%s", runs[k]); - struct term *bulk = tt_new(120, 6); - struct term *split = tt_new(120, 6); + struct wsap_vtcore *bulk = tt_new(120, 6); + struct wsap_vtcore *split = tt_new(120, 6); tt_write(bulk, text, strlen(text)); write_seq(split, text); assert_same_screen(bulk, split); expect_selection(bulk, 0, 5, 119, 5, runs[k]); - term_free(bulk); - term_free(split); + wsap_vtcore_free(bulk); + wsap_vtcore_free(split); } } @@ -1055,8 +1055,8 @@ static void test_invalid_utf8_runs(void) } memcpy(input + n, "END", 3); n += 3; - struct term *bulk = tt_new(120, 4); - struct term *split = tt_new(120, 4); + struct wsap_vtcore *bulk = tt_new(120, 4); + struct wsap_vtcore *split = tt_new(120, 4); write_seq(bulk, "\033[4;1H\n"); write_seq(split, "\033[4;1H\n"); tt_write(bulk, input, n); @@ -1067,15 +1067,15 @@ static void test_invalid_utf8_runs(void) for (int c = 0; c < 3; c++) assert(tt_cell_cp(bulk, tt_cell(bulk, 96 + c, 3)) == (uint32_t)"END"[c]); assert_same_screen(bulk, split); - term_free(bulk); - term_free(split); + wsap_vtcore_free(bulk); + wsap_vtcore_free(split); } } static void test_recycled_scrollback_blanks(void) { for (int mode = 0; mode < 3; mode++) { - struct term *t = tt_new(32, 3); + struct wsap_vtcore *t = tt_new(32, 3); write_seq(t, "\033[3;1H"); const char *line = mode == 2 ? "abcdefghijklmnopqrstuvwxyz\r\033[S" : "abcdefghijklmnopqrstuvwxyz\r\n"; @@ -1085,7 +1085,7 @@ static void test_recycled_scrollback_blanks(void) } write_seq(t, "\tfile/"); assert(row_is(t, 2, " file/")); - term_free(t); + wsap_vtcore_free(t); } } @@ -1093,26 +1093,26 @@ static void test_recycled_scrollback_blanks(void) * scroll that cannot move leaves the frame alone. */ static void test_scroll_view_clamps_extreme_deltas(void) { - struct term *t = tt_new(20, 3); + struct wsap_vtcore *t = tt_new(20, 3); for (int i = 0; i < 10; i++) write_seq(t, "line\r\n"); int max = tt_history(t); assert(max > 1); - struct term_snapshot *snap = term_snapshot_new(); - term_scroll(t, 1); - term_scroll(t, INT_MAX); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); + wsap_vtcore_scroll(t, 1); + wsap_vtcore_scroll(t, INT_MAX); assert(tt_view_offset(t) == max); uint64_t version = view_version(snap, t); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(view_version(snap, t) == version); - term_scroll(t, -1); - term_scroll(t, INT_MIN); + wsap_vtcore_scroll(t, -1); + wsap_vtcore_scroll(t, INT_MIN); assert(tt_view_offset(t) == 0); version = view_version(snap, t); - term_scroll(t, -1); + wsap_vtcore_scroll(t, -1); assert(view_version(snap, t) == version); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); } static void test_batched_recycled_lines(void) @@ -1125,8 +1125,8 @@ static void test_batched_recycled_lines(void) "short\r\nx\r\nyz\r\npartial\r", }; for (size_t k = 0; k < sizeof(endings) / sizeof(endings[0]); k++) { - struct term *bulk = tt_new(32, 3); - struct term *bytes = tt_new(32, 3); + struct wsap_vtcore *bulk = tt_new(32, 3); + struct wsap_vtcore *bytes = tt_new(32, 3); const char *old = "\033[31;44mabcdefghijklmnopqrst界界界\r\n"; for (int i = 0; i < TEST_SCROLLBACK + 10; i++) { tt_write(bulk, old, strlen(old)); @@ -1139,12 +1139,12 @@ static void test_batched_recycled_lines(void) assert_same_screen(bulk, bytes); for (int i = 0; i < tt_history(bulk); i += 3) { - term_scroll(bulk, 3); - term_scroll(bytes, 3); + wsap_vtcore_scroll(bulk, 3); + wsap_vtcore_scroll(bytes, 3); assert_same_screen(bulk, bytes); } - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } } @@ -1158,20 +1158,20 @@ static void test_full_width_line_endings(void) "aa\r\nbb\r\ncc\r\nd中d\r\nef", }; for (size_t k = 0; k < sizeof(feeds) / sizeof(feeds[0]); k++) { - struct term *bulk = tt_new(4, 3); - struct term *bytes = tt_new(4, 3); + struct wsap_vtcore *bulk = tt_new(4, 3); + struct wsap_vtcore *bytes = tt_new(4, 3); tt_write(bulk, feeds[k], strlen(feeds[k])); write_seq(bytes, feeds[k]); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } - struct term *t = tt_new(4, 3); + struct wsap_vtcore *t = tt_new(4, 3); tt_write(t, feeds[0], strlen(feeds[0])); assert(tt_history(t) == 3); assert(row_is(t, 0, "dddd") && row_is(t, 1, "eeee") && row_is(t, 2, "ffff")); - term_free(t); + wsap_vtcore_free(t); } /* CRLFs at every mask boundary, followed by complete or interrupted lines. */ @@ -1189,18 +1189,18 @@ static void test_batched_line_masks(void) memcpy(input + offset, tails[k], strlen(tails[k])); memset(input + n, 'z', 128); n += 128; - struct term *bulk = tt_new(80, 3), *bytes = tt_new(80, 3); + struct wsap_vtcore *bulk = tt_new(80, 3), *bytes = tt_new(80, 3); /* A nondefault pen exercises the queued bulk path, not streaming. */ write_both(bulk, bytes, "\033[3;1H\033[31m"); tt_write(bulk, input, n); for (size_t i = 0; i < n; i++) tt_write(bytes, input + i, 1); write_both(bulk, bytes, "\033[b"); assert_same_screen(bulk, bytes); - term_scroll_to(bulk, INT_MAX); - term_scroll_to(bytes, INT_MAX); + wsap_vtcore_scroll_to(bulk, INT_MAX); + wsap_vtcore_scroll_to(bytes, INT_MAX); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } } } @@ -1217,7 +1217,7 @@ static void test_batched_line_masks(void) */ static void test_bulk_line_flood(void) { - static const struct term_vector2i geoms[] = { + static const struct wsap_vtcore_vector2i geoms[] = { {.x = 80, .y = 24}, {.x = 27, .y = 8}, {.x = 10, .y = 5}, {.x = 120, .y = 80}, }; for (size_t g = 0; g < 2 * sizeof(geoms) / sizeof(geoms[0]); g++) { @@ -1246,28 +1246,28 @@ static void test_bulk_line_flood(void) buf[n++] = pick == 26 ? '\n' : (char)('a' + pick); } - struct term *bulk = tt_new(cols, rows); - struct term *stream = tt_new(cols, rows); - struct term *bytes = tt_new(cols, rows); - unsigned flags = g % 2 != 0 ? TERM_FEED_ONLCR : 0; + struct wsap_vtcore *bulk = tt_new(cols, rows); + struct wsap_vtcore *stream = tt_new(cols, rows); + struct wsap_vtcore *bytes = tt_new(cols, rows); + unsigned flags = g % 2 != 0 ? WSAP_VTCORE_FEED_ONLCR : 0; for (size_t i = 0; i < n; i += 65536) - term_feed(bulk, buf + i, n - i < 65536 ? n - i : 65536, flags); + wsap_vtcore_feed(bulk, buf + i, n - i < 65536 ? n - i : 65536, flags); /* One large write has enough newlines to discard old output. */ - term_feed(stream, buf, n, flags); - for (size_t i = 0; i < n; i++) term_feed(bytes, buf + i, 1, flags); + wsap_vtcore_feed(stream, buf, n, flags); + for (size_t i = 0; i < n; i++) wsap_vtcore_feed(bytes, buf + i, 1, flags); assert_same_screen(bulk, bytes); assert_same_screen(stream, bytes); for (int i = 0; i < tt_history(bulk); i += 7) { - term_scroll(bulk, 7); - term_scroll(stream, 7); - term_scroll(bytes, 7); + wsap_vtcore_scroll(bulk, 7); + wsap_vtcore_scroll(stream, 7); + wsap_vtcore_scroll(bytes, 7); assert_same_screen(bulk, bytes); assert_same_screen(stream, bytes); } - term_free(bulk); - term_free(stream); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(stream); + wsap_vtcore_free(bytes); free(buf); } } @@ -1289,29 +1289,29 @@ static void test_ascii_flood_edits(void) "\033[?1049hALT\033[?1049l\033[6;1Htail\n"; for (size_t w = 0; w < sizeof(widths) / sizeof(widths[0]); w++) { for (size_t chunk = 4096; chunk <= sizeof(input); chunk *= 16) { - struct term *bulk = tt_new(widths[w], 6); - struct term *bytes = tt_new(widths[w], 6); + struct wsap_vtcore *bulk = tt_new(widths[w], 6); + struct wsap_vtcore *bytes = tt_new(widths[w], 6); for (size_t i = 0; i < sizeof(input); i += chunk) - term_feed(bulk, input + i, chunk, TERM_FEED_ONLCR); + wsap_vtcore_feed(bulk, input + i, chunk, WSAP_VTCORE_FEED_ONLCR); for (size_t i = 0; i < sizeof(input); i++) - term_feed(bytes, input + i, 1, TERM_FEED_ONLCR); + wsap_vtcore_feed(bytes, input + i, 1, WSAP_VTCORE_FEED_ONLCR); assert_same_screen(bulk, bytes); - term_feed(bulk, edit, sizeof(edit) - 1, TERM_FEED_ONLCR); + wsap_vtcore_feed(bulk, edit, sizeof(edit) - 1, WSAP_VTCORE_FEED_ONLCR); for (size_t i = 0; i < sizeof(edit) - 1; i++) - term_feed(bytes, edit + i, 1, TERM_FEED_ONLCR); + wsap_vtcore_feed(bytes, edit + i, 1, WSAP_VTCORE_FEED_ONLCR); assert_same_screen(bulk, bytes); for (int i = 0; i < tt_history(bulk); i += 6) { - term_scroll(bulk, 6); - term_scroll(bytes, 6); + wsap_vtcore_scroll(bulk, 6); + wsap_vtcore_scroll(bytes, 6); assert_same_screen(bulk, bytes); } - term_scroll_to(bulk, 0); - term_scroll_to(bytes, 0); + wsap_vtcore_scroll_to(bulk, 0); + wsap_vtcore_scroll_to(bytes, 0); assert(tt_resize(bulk, widths[w] + 3, 7)); assert(tt_resize(bytes, widths[w] + 3, 7)); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } } } @@ -1327,8 +1327,8 @@ static void test_margin_linefeed_bursts(void) }; for (size_t k = 0; k < sizeof(bursts) / sizeof(bursts[0]); k++) { for (int mode = 0; mode < 3; mode++) { - struct term *bulk = tt_new(8, 8); - struct term *bytes = tt_new(8, 8); + struct wsap_vtcore *bulk = tt_new(8, 8); + struct wsap_vtcore *bytes = tt_new(8, 8); const char *setup = "\033[1;1Htop\033[2;1Ha\033[3;1Hb\033[4;1Hc" "\033[5;1Hd\033[6;1He\033[7;1Hf\033[8;1Hfoot" "\033[2;7r\033[7;3H"; @@ -1338,22 +1338,22 @@ static void test_margin_linefeed_bursts(void) write_seq(bulk, "\033[20h"); write_seq(bytes, "\033[20h"); } - unsigned flags = mode == 2 ? TERM_FEED_ONLCR : 0; - term_feed(bulk, bursts[k], strlen(bursts[k]), flags); + unsigned flags = mode == 2 ? WSAP_VTCORE_FEED_ONLCR : 0; + wsap_vtcore_feed(bulk, bursts[k], strlen(bursts[k]), flags); feed_seq(bytes, bursts[k], flags); assert_same_screen(bulk, bytes); assert(row_is(bulk, 0, "top")); assert(row_is(bulk, 7, "foot")); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } } } static void test_alt_linefeed_burst_after_resize(void) { - struct term *bulk = tt_new(8, 5); - struct term *bytes = tt_new(8, 5); + struct wsap_vtcore *bulk = tt_new(8, 5); + struct wsap_vtcore *bytes = tt_new(8, 5); const char *setup = "\033[?1049h\033[5;1H\n\n\n\n"; tt_write(bulk, setup, strlen(setup)); write_seq(bytes, setup); @@ -1366,8 +1366,8 @@ static void test_alt_linefeed_burst_after_resize(void) tt_resize(bulk, 12, 4); tt_resize(bytes, 12, 4); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } /* @@ -1380,24 +1380,24 @@ static void test_alt_resize_keeps_row_order(void) const char *setup = "\033[?1049h\033[5;1H\n\n\n" "\033[1;1HA\033[2;1HB\033[3;1HC\033[4;1HD\033[5;1HE"; - struct term *grow = tt_new(20, 5); + struct wsap_vtcore *grow = tt_new(20, 5); write_seq(grow, setup); tt_resize(grow, 20, 8); assert(row_is(grow, 0, "A") && row_is(grow, 4, "E")); assert(row_is(grow, 5, "") && row_is(grow, 7, "")); - term_free(grow); + wsap_vtcore_free(grow); /* The cursor is on the last row, so shrinking scrolls A and B off. */ - struct term *shrink = tt_new(20, 5); + struct wsap_vtcore *shrink = tt_new(20, 5); write_seq(shrink, setup); tt_resize(shrink, 20, 3); assert(row_is(shrink, 0, "C") && row_is(shrink, 2, "E")); - term_free(shrink); + wsap_vtcore_free(shrink); } static void test_alt_shrink_then_flood(void) { - struct term *t = tt_new(80, 40); + struct wsap_vtcore *t = tt_new(80, 40); tt_write(t, "\033[?1049h\033[40;1H", 16); for (int i = 0; i < 35; i++) tt_write(t, "x\n", 2); @@ -1409,36 +1409,36 @@ static void test_alt_shrink_then_flood(void) tt_write(t, line, (size_t)len); } assert(row_is(t, 8, "line 5999") && row_is(t, 0, "line 5991")); - term_free(t); + wsap_vtcore_free(t); } /* Regression: ED 3 on the alternate screen kept the history count, so the * normal screen came back with blank history rows. */ static void test_alt_erase_scrollback(void) { - struct term *t = tt_new(20, 5); + struct wsap_vtcore *t = tt_new(20, 5); for (int i = 0; i < 30; i++) tt_write(t, "line\r\n", 6); assert(tt_history(t) > 0); write_seq(t, "\033[?1049h\033[3J\033[?1049l"); assert(tt_history(t) == 0); - term_free(t); + wsap_vtcore_free(t); } /* Regression: a snapshot knew its terminal by address. A new terminal that * reused a freed one's memory then showed the old terminal's rows. */ static void test_snapshot_follows_new_terminal(void) { - struct term_snapshot *s = term_snapshot_new(); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); for (int i = 0; i < 8; i++) { - struct term *t = tt_new(10, 2); + struct wsap_vtcore *t = tt_new(10, 2); char text[2] = { (char)('a' + i), 0 }; tt_puts(t, text); - assert(term_snapshot_update(s, t)); - assert(term_snapshot_row(s, 0)[0].text == (uint32_t)text[0]); - term_free(t); + assert(wsap_vtcore_snapshot_update(s, t)); + assert(wsap_vtcore_snapshot_row(s, 0)[0].text == (uint32_t)text[0]); + wsap_vtcore_free(t); } - term_snapshot_free(s); + wsap_vtcore_snapshot_free(s); } /* The getters take a NULL snapshot and an out-of-range row like a NULL @@ -1446,48 +1446,48 @@ static void test_snapshot_follows_new_terminal(void) static void test_snapshot_null_and_range(void) { uint32_t cps[4] = { 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA }; - assert(term_snapshot_view(NULL) == NULL); - assert(term_snapshot_row(NULL, 0) == NULL); - assert(term_snapshot_row_key(NULL, 0) == 0); - struct term_span none = term_snapshot_row_selection(NULL, 0); + assert(wsap_vtcore_snapshot_view(NULL) == NULL); + assert(wsap_vtcore_snapshot_row(NULL, 0) == NULL); + assert(wsap_vtcore_snapshot_row_key(NULL, 0) == 0); + struct wsap_vtcore_span none = wsap_vtcore_snapshot_row_selection(NULL, 0); assert(none.begin == 0 && none.end == 0); - assert(term_snapshot_cluster(NULL, 'a', cps, 4) == 0); - assert(term_snapshot_cluster(NULL, TERM_TEXT_CLUSTER, cps, 4) == 0); + assert(wsap_vtcore_snapshot_cluster(NULL, 'a', cps, 4) == 0); + assert(wsap_vtcore_snapshot_cluster(NULL, WSAP_VTCORE_TEXT_CLUSTER, cps, 4) == 0); assert(cps[0] == 0xAAAA); - struct term *t = tt_new(4, 2); + struct wsap_vtcore *t = tt_new(4, 2); tt_write(t, "e\xcc\x81", 3); - struct term_snapshot *s = term_snapshot_new(); - assert(term_snapshot_update(s, t)); + struct wsap_vtcore_snapshot *s = wsap_vtcore_snapshot_new(); + assert(wsap_vtcore_snapshot_update(s, t)); - const struct term_view *view = term_snapshot_view(s); + const struct wsap_vtcore_view *view = wsap_vtcore_snapshot_view(s); const uint32_t *palette = view->palette; - assert(term_snapshot_update(s, t)); - assert(term_snapshot_view(s) == view && view->palette == palette); - - assert(term_snapshot_row(s, -1) == NULL); - assert(term_snapshot_row(s, 2) == NULL); - assert(term_snapshot_row_key(s, -1) == 0); - assert(term_snapshot_row_key(s, 2) == 0); - struct term_span off = term_snapshot_row_selection(s, 2); + assert(wsap_vtcore_snapshot_update(s, t)); + assert(wsap_vtcore_snapshot_view(s) == view && view->palette == palette); + + assert(wsap_vtcore_snapshot_row(s, -1) == NULL); + assert(wsap_vtcore_snapshot_row(s, 2) == NULL); + assert(wsap_vtcore_snapshot_row_key(s, -1) == 0); + assert(wsap_vtcore_snapshot_row_key(s, 2) == 0); + struct wsap_vtcore_span off = wsap_vtcore_snapshot_row_selection(s, 2); assert(off.begin == 0 && off.end == 0); /* A cluster cell gives its count with no buffer, and with cap 0 it * writes nothing. */ - uint32_t text = term_snapshot_row(s, 0)[0].text; - assert(text & TERM_TEXT_CLUSTER); - assert(term_snapshot_cluster(s, text, NULL, 0) == 2); - assert(term_snapshot_cluster(s, text, cps, 0) == 2); + uint32_t text = wsap_vtcore_snapshot_row(s, 0)[0].text; + assert(text & WSAP_VTCORE_TEXT_CLUSTER); + assert(wsap_vtcore_snapshot_cluster(s, text, NULL, 0) == 2); + assert(wsap_vtcore_snapshot_cluster(s, text, cps, 0) == 2); assert(cps[0] == 0xAAAA); - assert(term_snapshot_cluster(s, text, NULL, 4) == 2); + assert(wsap_vtcore_snapshot_cluster(s, text, NULL, 4) == 2); /* A plain code point is one code point, and cap 0 writes nothing. */ - assert(term_snapshot_cluster(s, 'a', NULL, 0) == 1); - assert(term_snapshot_cluster(s, 'a', cps, 0) == 1); + assert(wsap_vtcore_snapshot_cluster(s, 'a', NULL, 0) == 1); + assert(wsap_vtcore_snapshot_cluster(s, 'a', cps, 0) == 1); assert(cps[0] == 0xAAAA); - assert(term_snapshot_cluster(s, 'a', cps, 4) == 1 && cps[0] == 'a'); + assert(wsap_vtcore_snapshot_cluster(s, 'a', cps, 4) == 1 && cps[0] == 'a'); - term_snapshot_free(s); - term_free(t); + wsap_vtcore_snapshot_free(s); + wsap_vtcore_free(t); } static void test_string_payloads(void) @@ -1508,7 +1508,7 @@ static void test_string_payloads(void) for (size_t c = 0; c < 3; c++) { title[0] = 0; response_len = 0; - struct term *t = tt_new_opts(80, 4, &title_cb); + struct wsap_vtcore *t = tt_new_opts(80, 4, &title_cb); for (size_t i = 0; i < n;) { size_t take = n - i < chunks[c] ? n - i : chunks[c]; tt_write(t, input + i, take); @@ -1528,14 +1528,14 @@ static void test_string_payloads(void) assert(title[0] == 0); } } - term_free(t); + wsap_vtcore_free(t); } } } } } -/* term_new() refuses a name that a DCS reply could echo unsafely. */ +/* wsap_vtcore_new() refuses a name that a DCS reply could echo unsafely. */ static void test_host_name_rejected(void) { static const char *const bad[] = { @@ -1549,40 +1549,40 @@ static void test_host_name_rejected(void) fits[63] = 0; for (size_t i = 0; i < sizeof(bad) / sizeof(bad[0]); i++) { - struct term_options opt = { .size = { .x = 10, .y = 3 }, .name = bad[i] }; - assert(!term_new(&opt)); + struct wsap_vtcore_options opt = { .size = { .x = 10, .y = 3 }, .name = bad[i] }; + assert(!wsap_vtcore_new(&opt)); } - struct term_options opt = { .size = { .x = 10, .y = 3 }, .name = longest }; - assert(!term_new(&opt)); + struct wsap_vtcore_options opt = { .size = { .x = 10, .y = 3 }, .name = longest }; + assert(!wsap_vtcore_new(&opt)); opt.name = fits; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); - term_free(t); + wsap_vtcore_free(t); } static void test_newline_policy_survives_reset(void) { static const char *const resets[] = { "\033c", "\033[!p", "\033[20l" }; for (size_t i = 0; i < sizeof(resets) / sizeof(resets[0]); i++) { - struct term *t = tt_new(20, 6); - term_feed(t, "a\n", 2, TERM_FEED_ONLCR); + struct wsap_vtcore *t = tt_new(20, 6); + wsap_vtcore_feed(t, "a\n", 2, WSAP_VTCORE_FEED_ONLCR); assert(tt_cursor_x(t) == 0); write_seq(t, resets[i]); - term_feed(t, "b\nc", 3, TERM_FEED_ONLCR); + wsap_vtcore_feed(t, "b\nc", 3, WSAP_VTCORE_FEED_ONLCR); assert(tt_cursor_x(t) == 1); assert(row_is(t, tt_cursor_y(t), "c")); - term_free(t); + wsap_vtcore_free(t); } } static void test_lnm_mode_alone_is_not_sticky(void) { - struct term *t = tt_new(20, 6); + struct wsap_vtcore *t = tt_new(20, 6); write_seq(t, "\033[20h\033c"); tt_write(t, "b\nc", 3); assert(tt_cursor_x(t) == 2); - term_free(t); + wsap_vtcore_free(t); } /* A C0 control ends an unfinished UTF-8 sequence, which prints U+FFFD. A @@ -1591,13 +1591,13 @@ static void test_c0_ends_utf8_sequence(void) { static const char input[] = "\xc3\n\xa9z"; for (size_t split = 0; split < sizeof(input) - 1; split++) { - struct term *t = tt_new(20, 4); + struct wsap_vtcore *t = tt_new(20, 4); tt_write(t, input, split); tt_write(t, input + split, sizeof(input) - 1 - split); assert(tt_cell_cp(t, tt_cell(t, 0, 0)) == 0xFFFD); assert(tt_cell_cp(t, tt_cell(t, 1, 1)) == 0xFFFD); assert(tt_cell_cp(t, tt_cell(t, 2, 1)) == 'z'); - term_free(t); + wsap_vtcore_free(t); } } @@ -1611,8 +1611,8 @@ static void test_bulk_rows_survive_edits(void) for (size_t i = 0; i < sizeof(flood); i++) flood[i] = (char)('a' + (i * 7 + i / COLS) % 26); - struct term *bulk = tt_new(COLS, ROWS); - struct term *bytes = tt_new(COLS, ROWS); + struct wsap_vtcore *bulk = tt_new(COLS, ROWS); + struct wsap_vtcore *bytes = tt_new(COLS, ROWS); write_seq(bulk, "\033[1;4;38;2;9;8;7;48;2;1;2;3m"); write_seq(bytes, "\033[1;4;38;2;9;8;7;48;2;1;2;3m"); tt_write(bulk, flood, sizeof(flood)); @@ -1637,24 +1637,24 @@ static void test_bulk_rows_survive_edits(void) write_seq(bytes, "\033[?1049hALT\033[?1049l"); assert_same_screen(bulk, bytes); for (int i = 0; i < 3; i++) { - term_scroll(bulk, 100); - term_scroll(bytes, 100); + wsap_vtcore_scroll(bulk, 100); + wsap_vtcore_scroll(bytes, 100); assert_same_screen(bulk, bytes); } - term_scroll_to(bulk, 0); - term_scroll_to(bytes, 0); + wsap_vtcore_scroll_to(bulk, 0); + wsap_vtcore_scroll_to(bytes, 0); /* Selection text reads rows straight from history. */ - term_scroll(bulk, 50); - term_scroll(bytes, 50); + wsap_vtcore_scroll(bulk, 50); + wsap_vtcore_scroll(bytes, 50); tt_select(bulk, 0, 0, COLS - 1, 2); tt_select(bytes, 0, 0, COLS - 1, 2); char *a = tt_selection_text(bulk), *b = tt_selection_text(bytes); assert(a && b && !strcmp(a, b) && strlen(a) >= COLS); free(a); free(b); - term_scroll_to(bulk, 0); - term_scroll_to(bytes, 0); + wsap_vtcore_scroll_to(bulk, 0); + wsap_vtcore_scroll_to(bytes, 0); /* Reflow narrower and wider keeps history identical. */ tt_resize(bulk, 29, ROWS); @@ -1663,27 +1663,27 @@ static void test_bulk_rows_survive_edits(void) tt_resize(bulk, 61, ROWS + 2); tt_resize(bytes, 61, ROWS + 2); assert_same_screen(bulk, bytes); - term_scroll(bulk, 20); - term_scroll(bytes, 20); + wsap_vtcore_scroll(bulk, 20); + wsap_vtcore_scroll(bytes, 20); assert_same_screen(bulk, bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } static void test_erase_keeps_used_rows(void) { for (int row = 0; row < 40; row++) { - struct term *t = tt_new(20, 40); + struct wsap_vtcore *t = tt_new(20, 40); char seq[64]; int len = snprintf(seq, sizeof(seq), "\033[%d;1Hsaved\033[2J", row + 1); tt_write(t, seq, (size_t)len); assert(tt_history(t) == row + 1); for (int y = 0; y < 40; y++) assert(row_eq(t, y, "")); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(row_eq(t, 0, "saved")); - term_free(t); + wsap_vtcore_free(t); } } @@ -1691,20 +1691,20 @@ static void test_blank_rows(void) { /* ED 2 pushes used rows to scrollback; the erased screen reads as * default-color blanks through every accessor. */ - struct term *t = tt_new(10, 4); + struct wsap_vtcore *t = tt_new(10, 4); write_seq(t, "one\r\ntwo\r\nthree"); write_seq(t, "\033[2J"); assert(tt_history(t) == 3); for (int y = 0; y < 4; y++) for (int x = 0; x < 10; x++) { - const struct term_cell *c = tt_view_cell(t, x, y); - assert(c->text == ' ' && c->fg == TERM_COLOR_FG && - c->bg == TERM_COLOR_BG); + const struct wsap_vtcore_cell *c = tt_view_cell(t, x, y); + assert(c->text == ' ' && c->fg == WSAP_VTCORE_COLOR_FG && + c->bg == WSAP_VTCORE_COLOR_BG); assert(tt_cell(t, x, y)->text == ' '); } - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert(row_is(t, 0, "one") && row_is(t, 1, "two") && row_is(t, 2, "three")); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); /* A scrolled-in blank row reads as blanks, then accepts new text. */ write_seq(t, "\033[4;1Hlast\r\n\r\n\r\n"); @@ -1712,7 +1712,7 @@ static void test_blank_rows(void) assert(tt_view_cell(t, x, 3)->text == ' '); write_seq(t, "\033[4;6Hhi"); assert(row_is(t, 3, " hi")); - term_free(t); + wsap_vtcore_free(t); /* A spaces-only row does not extend ED 2 history. */ t = tt_new(10, 6); @@ -1720,23 +1720,23 @@ static void test_blank_rows(void) assert(tt_history(t) == 0); write_seq(t, "\033[2J"); assert(tt_history(t) == 1); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(row_is(t, 0, "top")); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); /* Blank rows survive a resize and still read as blanks. */ tt_resize(t, 20, 6); for (int x = 0; x < 20; x++) assert(tt_cell(t, x, 5)->text == ' ' && - tt_cell(t, x, 5)->bg == TERM_COLOR_BG); - term_free(t); + tt_cell(t, x, 5)->bg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); /* Erasing a blank row with a color still produces a colored row. */ t = tt_new(10, 4); write_seq(t, "\033[2J\033[41m\033[2K"); - assert(tt_cell(t, 0, 0)->bg != TERM_COLOR_BG); + assert(tt_cell(t, 0, 0)->bg != WSAP_VTCORE_COLOR_BG); assert(tt_cell(t, 9, 0)->bg == tt_cell(t, 0, 0)->bg); - term_free(t); + wsap_vtcore_free(t); } static void test_csi_text_chunks(void) @@ -1757,26 +1757,26 @@ static void test_csi_text_chunks(void) for (size_t c = 0; c < sizeof(cases) / sizeof(cases[0]); c++) { const char *seq = cases[c]; size_t len = strlen(seq); - struct term *expected = tt_new(20, 40); + struct wsap_vtcore *expected = tt_new(20, 40); write_seq(expected, seq); for (size_t split = 0; split <= len; split++) { - struct term *actual = tt_new(20, 40); + struct wsap_vtcore *actual = tt_new(20, 40); tt_write(actual, seq, split); tt_write(actual, seq + split, len - split); assert(tt_cursor_x(actual) == tt_cursor_x(expected)); assert(tt_cursor_y(actual) == tt_cursor_y(expected)); assert(tt_history(actual) == tt_history(expected)); int history = tt_history(expected); - term_scroll(actual, history); - term_scroll(expected, history); + wsap_vtcore_scroll(actual, history); + wsap_vtcore_scroll(expected, history); for (int page = 0; page <= history; page++) { assert_same_rows(actual, expected, 40); - term_scroll(actual, -1); - term_scroll(expected, -1); + wsap_vtcore_scroll(actual, -1); + wsap_vtcore_scroll(expected, -1); } - term_free(actual); + wsap_vtcore_free(actual); } - term_free(expected); + wsap_vtcore_free(expected); } } @@ -1785,7 +1785,7 @@ static void test_csi_text_chunks(void) * keep their text. */ static void test_grow_past_reservation(void) { - struct term *t = tt_new(40, 10); + struct wsap_vtcore *t = tt_new(40, 10); for (int i = 0; i < 30; i++) { char line[32]; int len = snprintf(line, sizeof(line), "hist %02d\r\n", i); @@ -1821,20 +1821,20 @@ static void test_grow_past_reservation(void) tt_write(t, "\033[?1049l", 8); bool found = false; - term_scroll(t, tt_history(t)); + wsap_vtcore_scroll(t, tt_history(t)); for (int y = 0; y < tt_rows(t) && !found; y++) found = row_eq(t, y, "hist 00"); assert(found); - term_scroll(t, -tt_history(t)); + wsap_vtcore_scroll(t, -tt_history(t)); bool last = false; for (int y = 0; y < tt_rows(t) && !last; y++) last = row_eq(t, y, "fill 0999"); assert(last); - term_free(t); + wsap_vtcore_free(t); } struct concurrent_worker_args { - struct term *t; + struct wsap_vtcore *t; _Atomic bool done; }; @@ -1853,7 +1853,7 @@ static void *concurrent_feed_worker(void *arg) size_t len = strlen(concurrent_stream); for (int i = 0; i < 2000; i++) { - term_feed(w->t, concurrent_stream, len, 0); + wsap_vtcore_feed(w->t, concurrent_stream, len, 0); } atomic_store(&w->done, true); return NULL; @@ -1861,11 +1861,11 @@ static void *concurrent_feed_worker(void *arg) static void test_concurrent_feed_and_snapshot(void) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = 80, .y = 24 }, .scrollback = 1000, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t != NULL); struct concurrent_worker_args w = { .t = t, .done = false }; @@ -1873,43 +1873,43 @@ static void test_concurrent_feed_and_snapshot(void) int err = pthread_create(&th, NULL, concurrent_feed_worker, &w); assert(err == 0); - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); assert(snap != NULL); while (!atomic_load(&w.done)) { - bool ok = term_snapshot_update(snap, t); + bool ok = wsap_vtcore_snapshot_update(snap, t); assert(ok); - struct term_vector2i sz = term_size(t); + struct wsap_vtcore_vector2i sz = wsap_vtcore_size(t); assert(sz.x > 0 && sz.y > 0); - term_scroll(t, 2); - term_scroll_to(t, 0); - struct term_modes m = term_modes(t); + wsap_vtcore_scroll(t, 2); + wsap_vtcore_scroll_to(t, 0); + struct wsap_vtcore_modes m = wsap_vtcore_modes(t); (void)m; - struct term_cursor c = term_cursor(t); + struct wsap_vtcore_cursor c = wsap_vtcore_cursor(t); (void)c; /* Every reader is safe while another thread feeds. */ - term_select_start(t, (struct term_vector2i){ .x = 0, .y = 0 }, false, TERM_SELECT_WORD); - term_select_extend(t, (struct term_vector2i){ .x = 40, .y = 10 }, false); - (void)term_has_selection(t); - term_text_free(term_selection_text(t)); - term_text_free(term_link_at(t, (struct term_vector2i){ .x = 1, .y = 1 })); - term_text_free(term_cwd(t)); - term_text_free(term_pointer_shape(t)); - (void)term_history_rows(t); - term_text_free(term_history_text(t, 5)); - struct term_scrollback sb = term_scrollback(t); + wsap_vtcore_select_start(t, (struct wsap_vtcore_vector2i){ .x = 0, .y = 0 }, false, WSAP_VTCORE_SELECT_WORD); + wsap_vtcore_select_extend(t, (struct wsap_vtcore_vector2i){ .x = 40, .y = 10 }, false); + (void)wsap_vtcore_has_selection(t); + wsap_vtcore_text_free(wsap_vtcore_selection_text(t)); + wsap_vtcore_text_free(wsap_vtcore_link_at(t, (struct wsap_vtcore_vector2i){ .x = 1, .y = 1 })); + wsap_vtcore_text_free(wsap_vtcore_cwd(t)); + wsap_vtcore_text_free(wsap_vtcore_pointer_shape(t)); + (void)wsap_vtcore_history_rows(t); + wsap_vtcore_text_free(wsap_vtcore_history_text(t, 5)); + struct wsap_vtcore_scrollback sb = wsap_vtcore_scrollback(t); assert(sb.offset >= 0 && sb.total >= 0); } pthread_join(th, NULL); - bool ok = term_snapshot_update(snap, t); + bool ok = wsap_vtcore_snapshot_update(snap, t); assert(ok); /* The reader changed only the view and the selection. The screen and * the history must match a terminal that got the same bytes on one * thread. */ - struct term *ref = term_new(&opt); + struct wsap_vtcore *ref = wsap_vtcore_new(&opt); assert(ref != NULL); for (int i = 0; i < 2000; i++) tt_write(ref, concurrent_stream, strlen(concurrent_stream)); @@ -1926,65 +1926,65 @@ static void test_concurrent_feed_and_snapshot(void) } free(got); free(want); - char *text = term_history_text(t, 1000); - char *text_ref = term_history_text(ref, 1000); + char *text = wsap_vtcore_history_text(t, 1000); + char *text_ref = wsap_vtcore_history_text(ref, 1000); assert(text && text_ref && !strcmp(text, text_ref)); - term_text_free(text); - term_text_free(text_ref); + wsap_vtcore_text_free(text); + wsap_vtcore_text_free(text_ref); - term_free(ref); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_free(ref); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); } static void test_reserved_options_must_be_zero(void) { - struct term_options opt = { .size = { .x = 10, .y = 2 } }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = 10, .y = 2 } }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t != NULL); - term_free(t); + wsap_vtcore_free(t); size_t words = sizeof(opt.reserved) / sizeof(opt.reserved[0]); for (size_t i = 0; i < words; i++) { opt.reserved[i] = 1; - assert(term_new(&opt) == NULL); + assert(wsap_vtcore_new(&opt) == NULL); opt.reserved[i] = 0; } opt.reserved[words - 1] = 0x80000000u; - assert(term_new(&opt) == NULL); + assert(wsap_vtcore_new(&opt) == NULL); opt.reserved[words - 1] = 0; - t = term_new(&opt); + t = wsap_vtcore_new(&opt); assert(t != NULL); - term_free(t); + wsap_vtcore_free(t); } struct lock_probe { - struct term *t; + struct wsap_vtcore *t; _Atomic bool entered; }; static void *lock_probe_worker(void *arg) { struct lock_probe *p = arg; - term_lock(p->t); + wsap_vtcore_lock(p->t); atomic_store(&p->entered, true); - term_unlock(p->t); + wsap_vtcore_unlock(p->t); return NULL; } -/* term_lock() nests on the owning thread. Another thread waits until the - * last term_unlock(). */ +/* wsap_vtcore_lock() nests on the owning thread. Another thread waits until the + * last wsap_vtcore_unlock(). */ static void test_lock_reentrant_across_threads(void) { - struct term *t = term_new(&(struct term_options){ + struct wsap_vtcore *t = wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = 80, .y = 24 }, }); assert(t != NULL); - term_lock(t); - term_lock(t); + wsap_vtcore_lock(t); + wsap_vtcore_lock(t); assert(tt_cols(t) == 80); - term_unlock(t); + wsap_vtcore_unlock(t); struct lock_probe p = { .t = t, .entered = false }; pthread_t th; @@ -1992,11 +1992,11 @@ static void test_lock_reentrant_across_threads(void) for (int i = 0; i < 1000; i++) sched_yield(); assert(!atomic_load(&p.entered)); - term_unlock(t); + wsap_vtcore_unlock(t); assert(pthread_join(th, NULL) == 0); assert(atomic_load(&p.entered)); - term_free(t); + wsap_vtcore_free(t); } int main(void) @@ -2032,21 +2032,21 @@ int main(void) test_bulk_rows_survive_edits(); test_host_name_rejected(); - assert(!strcmp(TERM_UNICODE_DATA_VERSION, "18.0.0")); - assert(!strcmp(term_unicode_version(), TERM_UNICODE_DATA_VERSION)); - assert(term_unicode_width('A') == 1); - assert(term_unicode_width(0x0301) == 0); - assert(term_unicode_width(0x754C) == 2); - assert(term_unicode_width(0x1FAE0) == 2); - assert(term_unicode_emoji_presentation(0x1FAE0)); - assert(term_unicode_width(0x1FAEB) == 2); - assert(term_unicode_emoji_presentation(0x1FAEB)); + assert(!strcmp(WSAP_VTCORE_UNICODE_DATA_VERSION, "18.0.0")); + assert(!strcmp(wsap_vtcore_unicode_version(), WSAP_VTCORE_UNICODE_DATA_VERSION)); + assert(wsap_vtcore_unicode_width('A') == 1); + assert(wsap_vtcore_unicode_width(0x0301) == 0); + assert(wsap_vtcore_unicode_width(0x754C) == 2); + assert(wsap_vtcore_unicode_width(0x1FAE0) == 2); + assert(wsap_vtcore_unicode_emoji_presentation(0x1FAE0)); + assert(wsap_vtcore_unicode_width(0x1FAEB) == 2); + assert(wsap_vtcore_unicode_emoji_presentation(0x1FAEB)); { /* A Jamo Extended-B vowel draws inside its leading consonant. */ - struct term *t = term_new(&(struct term_options){ .size = { .x = 10, .y = 2 } }); - term_feed(t, "\xe1\x84\x80\xed\x9e\xb0", 6, 0); - assert(term_cursor(t).pos.x == 2); - term_free(t); + struct wsap_vtcore *t = wsap_vtcore_new(&(struct wsap_vtcore_options){ .size = { .x = 10, .y = 2 } }); + wsap_vtcore_feed(t, "\xe1\x84\x80\xed\x9e\xb0", 6, 0); + assert(wsap_vtcore_cursor(t).pos.x == 2); + wsap_vtcore_free(t); } test_wide_characters(); @@ -2069,7 +2069,7 @@ int main(void) test_parameter_limits(); test_unterminated_control_strings_do_not_swallow_text(); test_c0_controls_after_esc_are_executed(); - struct term *t = tt_new_opts(10, 4, &reply_cb); + struct wsap_vtcore *t = tt_new_opts(10, 4, &reply_cb); write_seq(t, "\033(Babc\r\nD"); assert(tt_cell(t, 0, 0)->text == 'a'); assert(tt_cell(t, 0, 1)->text == 'D'); @@ -2133,7 +2133,7 @@ int main(void) write_seq(t, "\033[?6;69l"); write_seq(t, "\033[?1;5;1004;2026h\033[!p"); - struct term_modes modes = term_modes(t); + struct wsap_vtcore_modes modes = wsap_vtcore_modes(t); assert(!modes.app_cursor && !modes.focus_events); assert(!modes.synchronized && !modes.reverse_video); write_seq(t, "kept\033c"); @@ -2147,28 +2147,28 @@ int main(void) assert(tt_cell(t, 0, 0)->text == 'A'); write_seq(t, "\033[2;4H\033[2J"); assert(tt_cursor_x(t) == 3 && tt_cursor_y(t) == 1); - assert(term_modes(t).mouse == TERM_MOUSE_OFF); + assert(wsap_vtcore_modes(t).mouse == WSAP_VTCORE_MOUSE_OFF); write_seq(t, "\033[?1000;1006h"); - assert(term_modes(t).mouse == TERM_MOUSE_NORMAL); - assert(term_modes(t).mouse_encoding == TERM_MOUSE_ENC_SGR); + assert(wsap_vtcore_modes(t).mouse == WSAP_VTCORE_MOUSE_NORMAL); + assert(wsap_vtcore_modes(t).mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR); write_seq(t, "\033[?1002h"); - assert(term_modes(t).mouse == TERM_MOUSE_BUTTON); - assert(term_modes(t).mouse_encoding == TERM_MOUSE_ENC_SGR); + assert(wsap_vtcore_modes(t).mouse == WSAP_VTCORE_MOUSE_BUTTON); + assert(wsap_vtcore_modes(t).mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR); write_seq(t, "\033[?1003h"); - assert(term_modes(t).mouse == TERM_MOUSE_ANY); + assert(wsap_vtcore_modes(t).mouse == WSAP_VTCORE_MOUSE_ANY); write_seq(t, "\033[?1006l"); - assert(term_modes(t).mouse_encoding == TERM_MOUSE_ENC_X10); + assert(wsap_vtcore_modes(t).mouse_encoding == WSAP_VTCORE_MOUSE_ENC_X10); write_seq(t, "\033[?1015h"); - assert(term_modes(t).mouse_encoding == TERM_MOUSE_ENC_URXVT); + assert(wsap_vtcore_modes(t).mouse_encoding == WSAP_VTCORE_MOUSE_ENC_URXVT); write_seq(t, "\033[?1016h"); - assert(term_modes(t).mouse_encoding == TERM_MOUSE_ENC_SGR_PIXELS); + assert(wsap_vtcore_modes(t).mouse_encoding == WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS); write_seq(t, "\033[?1004h"); - term_focus(t, false); + wsap_vtcore_focus(t, false); assert(!strcmp(response, "\033[O")); - term_focus(t, true); + wsap_vtcore_focus(t, true); assert(!strcmp(response, "\033[I")); write_seq(t, "\033[?1003l"); - assert(term_modes(t).mouse == TERM_MOUSE_OFF); + assert(wsap_vtcore_modes(t).mouse == WSAP_VTCORE_MOUSE_OFF); response_len = 0; write_seq(t, "\033]10;?\007"); assert(!strcmp(response, "\033]10;rgb:ffff/ffff/ffff\033\\")); @@ -2176,7 +2176,7 @@ int main(void) assert(!strcmp(response, "\033P0+r696e646e\033\\")); write_seq(t, "\033P+q6b696e64\033\\"); assert(!strcmp(response, "\033P1+r6b696e64=1b5b313b3242\033\\")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(40, 4); write_seq(t, "hello 世界 \r\nsecond line\r\nhttps://example.com/path."); tt_select(t, 9, 0, 0, 0); @@ -2194,13 +2194,13 @@ int main(void) free(text); assert(!tt_link_at(t, 10, 1)); write_seq(t, "\033[?2004h"); - assert(term_modes(t).bracketed_paste); + assert(wsap_vtcore_modes(t).bracketed_paste); text = tt_selection_text(t); assert(text && !strcmp(text, "hello 世界\nsecond")); free(text); write_seq(t, "\033[?2004l\r\nlast\r\n"); - assert(!term_modes(t).bracketed_paste); - term_scroll(t, 1); + assert(!wsap_vtcore_modes(t).bracketed_paste); + wsap_vtcore_scroll(t, 1); tt_select(t, 0, 0, 9, 0); text = tt_selection_text(t); assert(text && !strcmp(text, "hello 世界")); @@ -2209,7 +2209,7 @@ int main(void) text = tt_selection_text(t); assert(text && !strcmp(text, "hello 世界")); free(text); - term_free(t); + wsap_vtcore_free(t); t = tt_new(40, 4); write_seq(t, "\033[31;44mA\033[>4;0mB\033[>4;1m\033[31mC"); assert(tt_cell(t, 0, 0)->fg == tt_cell(t, 1, 0)->fg); @@ -2218,49 +2218,49 @@ int main(void) assert(tt_cell(t, 0, 0)->bg == tt_cell(t, 2, 0)->bg); assert(tt_cursor_x(t) == 3 && tt_cursor_y(t) == 0); write_seq(t, "\033[0mD"); - assert(tt_cell(t, 3, 0)->fg == TERM_COLOR_FG); - assert(tt_cell(t, 3, 0)->bg == TERM_COLOR_BG); - term_free(t); + assert(tt_cell(t, 3, 0)->fg == WSAP_VTCORE_COLOR_FG); + assert(tt_cell(t, 3, 0)->bg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); t = tt_new(10, 4); write_seq(t, "ABCDEFGHIJ\r\n\r\n\r\n\r\n"); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(tt_view_cell(t, 0, 0)->text == 'A'); assert(tt_view_cell(t, 9, 0)->text == 'J'); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); for (int i = 0; i < TEST_SCROLLBACK; i++) write_seq(t, "xy\r\n"); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(tt_view_cell(t, 0, 0)->text == 'x'); for (int c = 2; c < 10; c++) { assert(tt_view_cell(t, c, 0)->text == ' '); - assert(tt_view_cell(t, c, 0)->bg == TERM_COLOR_BG); + assert(tt_view_cell(t, c, 0)->bg == WSAP_VTCORE_COLOR_BG); } - term_free(t); + wsap_vtcore_free(t); t = tt_new(10, 4); write_seq(t, "\033[41m\033[2K"); - term_color erased_bg = tt_cell(t, 0, 0)->bg; - assert(erased_bg != TERM_COLOR_BG); + wsap_vtcore_color erased_bg = tt_cell(t, 0, 0)->bg; + assert(erased_bg != WSAP_VTCORE_COLOR_BG); assert(tt_cell(t, 9, 0)->bg == erased_bg); write_seq(t, "\033[m\n\n\n\n"); - term_scroll(t, 1); + wsap_vtcore_scroll(t, 1); assert(tt_view_cell(t, 9, 0)->bg == erased_bg); - assert(tt_view_cell(t, 10, 0)->bg == TERM_COLOR_BG); - term_free(t); + assert(tt_view_cell(t, 10, 0)->bg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); t = tt_new(10, 4); write_seq(t, "\033[Hnormal"); write_seq(t, "\033[?1049h"); for (int c = 0; c < 10; c++) { assert(tt_cell(t, c, 0)->text == ' '); - assert(tt_cell(t, c, 0)->bg == TERM_COLOR_BG); + assert(tt_cell(t, c, 0)->bg == WSAP_VTCORE_COLOR_BG); } write_seq(t, "\033[Halt\n\033[2J"); write_seq(t, "\033[?1049l"); assert(tt_cell(t, 0, 0)->text == 'n' && tt_cell(t, 5, 0)->text == 'l'); - term_free(t); + wsap_vtcore_free(t); t = tt_new(20, 8); write_seq(t, "one\r\ntwo\r\nthree\r\nfour\r\nfive\r\n$ "); @@ -2268,9 +2268,9 @@ int main(void) tt_resize(t, 20, 3); assert(tt_cursor_y(t) == 2 && tt_history(t) == 3); assert(row_is(t, 0, "four") && row_is(t, 1, "five") && row_is(t, 2, "$")); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert(row_is(t, 0, "one") && row_is(t, 1, "two") && row_is(t, 2, "three")); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); tt_resize(t, 20, 8); assert(tt_cursor_y(t) == 5 && tt_history(t) == 0); assert(row_is(t, 0, "one") && row_is(t, 2, "three") && row_is(t, 5, "$")); @@ -2279,7 +2279,7 @@ int main(void) tt_resize(t, 20, 6); assert(tt_cursor_y(t) == 5 && tt_history(t) == 0); assert(row_is(t, 0, "one") && row_is(t, 5, "$")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(20, 6); write_seq(t, "a\r\nb\r\nc\r\nd\r\ne\r\n"); @@ -2291,7 +2291,7 @@ int main(void) assert(tt_history(t) == before); write_seq(t, "\033[?1049l"); assert(row_is(t, 0, "a") && row_is(t, 4, "e")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(40, 6); write_seq(t, "\033[?1049h\033[1;38Hxy"); @@ -2300,7 +2300,7 @@ int main(void) assert(tt_cursor_x(t) < tt_cols(t)); write_seq(t, "Q"); assert(tt_cell(t, tt_cursor_x(t) - 1, tt_cursor_y(t))->text == 'Q'); - term_free(t); + wsap_vtcore_free(t); t = tt_new(8, 4); write_seq(t, "abcdefghijkl"); @@ -2313,7 +2313,7 @@ int main(void) text = tt_selection_text(t); assert(text && !strcmp(text, "abcd\nefgh")); free(text); - term_free(t); + wsap_vtcore_free(t); t = tt_new(10, 4); write_seq(t, "abcdef"); @@ -2326,7 +2326,7 @@ int main(void) write_seq(t, "\033[10P"); assert(row_is(t, 0, "ab")); assert(tt_cursor_x(t) == 2 && tt_cursor_y(t) == 0); - term_free(t); + wsap_vtcore_free(t); t = tt_new(8, 4); write_seq(t, "abcdef"); @@ -2335,87 +2335,87 @@ int main(void) assert(tt_cursor_x(t) == 2 && tt_cursor_y(t) == 0); write_seq(t, "\033[2@"); assert(row_is(t, 0, "ab cde")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(10, 4); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK); - assert(term_cursor(t).blink == true); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK); + assert(wsap_vtcore_cursor(t).blink == true); write_seq(t, "\033[2 q"); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK); - assert(term_cursor(t).blink == false); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK); + assert(wsap_vtcore_cursor(t).blink == false); write_seq(t, "\033[3 q"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE); - assert(term_cursor(t).blink == true); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE); + assert(wsap_vtcore_cursor(t).blink == true); write_seq(t, "\033[4 q"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE); - assert(term_cursor(t).blink == false); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE); + assert(wsap_vtcore_cursor(t).blink == false); write_seq(t, "\033[5 q"); - assert(term_cursor(t).style == TERM_CURSOR_BAR); - assert(term_cursor(t).blink == true); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR); + assert(wsap_vtcore_cursor(t).blink == true); write_seq(t, "\033[6 q"); - assert(term_cursor(t).style == TERM_CURSOR_BAR); - assert(term_cursor(t).blink == false); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR); + assert(wsap_vtcore_cursor(t).blink == false); write_seq(t, "\033[0 q"); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK); - assert(term_cursor(t).blink == true); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK); + assert(wsap_vtcore_cursor(t).blink == true); write_seq(t, "\033[5 q"); write_seq(t, "\033[ q"); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK); - assert(term_cursor(t).blink == true); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK); + assert(wsap_vtcore_cursor(t).blink == true); write_seq(t, "\033[6 q"); - assert(term_cursor(t).style == TERM_CURSOR_BAR && !term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR && !wsap_vtcore_cursor(t).blink); write_seq(t, "\033[?1049h"); write_seq(t, "\033[3 q"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE && term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE && wsap_vtcore_cursor(t).blink); write_seq(t, "\033[?1049l"); - assert(term_cursor(t).style == TERM_CURSOR_BAR && !term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR && !wsap_vtcore_cursor(t).blink); - term_set_cursor_default(t, TERM_CURSOR_UNDERLINE, true); + wsap_vtcore_set_cursor_default(t, WSAP_VTCORE_CURSOR_UNDERLINE, true); write_seq(t, "\033[5 q"); - assert(term_cursor(t).style == TERM_CURSOR_BAR && term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BAR && wsap_vtcore_cursor(t).blink); write_seq(t, "\033[0 q"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE && !term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE && !wsap_vtcore_cursor(t).blink); write_seq(t, "\033[2 q"); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK && !term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK && !wsap_vtcore_cursor(t).blink); write_seq(t, "\033[ q"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE && !term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE && !wsap_vtcore_cursor(t).blink); write_seq(t, "\033[1 q"); - assert(term_cursor(t).style == TERM_CURSOR_BLOCK && term_cursor(t).blink); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_BLOCK && wsap_vtcore_cursor(t).blink); write_seq(t, "\033[!p"); - assert(term_cursor(t).style == TERM_CURSOR_UNDERLINE && !term_cursor(t).blink); - term_free(t); + assert(wsap_vtcore_cursor(t).style == WSAP_VTCORE_CURSOR_UNDERLINE && !wsap_vtcore_cursor(t).blink); + wsap_vtcore_free(t); t = tt_new(20, 4); write_seq(t, "\033[1;2;3;4;9;53mA\033[21mB\033[4:2mC\033[22;24mD\033[0mE"); - const uint16_t styles = TERM_ATTR_BOLD | TERM_ATTR_FAINT | TERM_ATTR_ITALIC | - TERM_ATTR_STRIKE | TERM_ATTR_OVERLINE; + const uint16_t styles = WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_FAINT | WSAP_VTCORE_ATTR_ITALIC | + WSAP_VTCORE_ATTR_STRIKE | WSAP_VTCORE_ATTR_OVERLINE; assert((tt_cell(t, 0, 0)->attrs & styles) == styles); - assert(term_attr_underline(tt_cell(t, 0, 0)->attrs) == TERM_UNDERLINE_SINGLE); - assert(term_attr_underline(tt_cell(t, 1, 0)->attrs) == TERM_UNDERLINE_DOUBLE); - assert(term_attr_underline(tt_cell(t, 2, 0)->attrs) == TERM_UNDERLINE_DOUBLE); - assert(!(tt_cell(t, 3, 0)->attrs & (TERM_ATTR_BOLD | TERM_ATTR_FAINT))); - assert(term_attr_underline(tt_cell(t, 3, 0)->attrs) == TERM_UNDERLINE_NONE); + assert(wsap_vtcore_attr_underline(tt_cell(t, 0, 0)->attrs) == WSAP_VTCORE_UNDERLINE_SINGLE); + assert(wsap_vtcore_attr_underline(tt_cell(t, 1, 0)->attrs) == WSAP_VTCORE_UNDERLINE_DOUBLE); + assert(wsap_vtcore_attr_underline(tt_cell(t, 2, 0)->attrs) == WSAP_VTCORE_UNDERLINE_DOUBLE); + assert(!(tt_cell(t, 3, 0)->attrs & (WSAP_VTCORE_ATTR_BOLD | WSAP_VTCORE_ATTR_FAINT))); + assert(wsap_vtcore_attr_underline(tt_cell(t, 3, 0)->attrs) == WSAP_VTCORE_UNDERLINE_NONE); assert(tt_cell(t, 4, 0)->attrs == 0); - term_free(t); + wsap_vtcore_free(t); t = tt_new(20, 4); write_seq(t, "\033[30mA\033[0;1;30mB\033[0;90mC"); assert(tt_cell(t, 0, 0)->fg == tt_cell(t, 1, 0)->fg); assert(tt_cell(t, 1, 0)->fg != tt_cell(t, 2, 0)->fg); - assert(!(tt_cell(t, 0, 0)->attrs & TERM_ATTR_BOLD)); - assert(tt_cell(t, 1, 0)->attrs & TERM_ATTR_BOLD); - term_free(t); + assert(!(tt_cell(t, 0, 0)->attrs & WSAP_VTCORE_ATTR_BOLD)); + assert(tt_cell(t, 1, 0)->attrs & WSAP_VTCORE_ATTR_BOLD); + wsap_vtcore_free(t); const char *colon_rgb = "\033[48;2;145;2;34m\033[38;2;12;34;56mA" "\033[38:2::12:34:56mB\033[;mC"; @@ -2428,16 +2428,16 @@ int main(void) assert(tt_cell(t, x, 0)->fg == 0xFF0C2238); assert(tt_cell(t, x, 0)->bg == 0xFF910222); } - assert(tt_cell(t, 2, 0)->fg == TERM_COLOR_FG); - assert(tt_cell(t, 2, 0)->bg == TERM_COLOR_BG); - term_free(t); + assert(tt_cell(t, 2, 0)->fg == WSAP_VTCORE_COLOR_FG); + assert(tt_cell(t, 2, 0)->bg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); } t = tt_new(20, 4); write_seq(t, "\033[38;2;246;226;183;49mX"); assert(tt_cell(t, 0, 0)->fg == 0xFFF6E2B7); - assert(tt_cell(t, 0, 0)->bg == TERM_COLOR_BG); - term_free(t); + assert(tt_cell(t, 0, 0)->bg == WSAP_VTCORE_COLOR_BG); + wsap_vtcore_free(t); t = tt_new(20, 4); const char *clusters = "(\xc2\xa9\xef\xb8\x8f)\xe2\x98\xba\xef\xb8\x8e" @@ -2445,17 +2445,17 @@ int main(void) write_seq(t, clusters); assert(tt_cursor_x(t) == 7); - assert((tt_cell(t, 1, 0)->attrs & TERM_ATTR_EMOJI) && tt_cell(t, 1, 0)->width == 2); + assert((tt_cell(t, 1, 0)->attrs & WSAP_VTCORE_ATTR_EMOJI) && tt_cell(t, 1, 0)->width == 2); assert(tt_cell(t, 2, 0)->width == 0); - assert((tt_cell(t, 4, 0)->attrs & TERM_ATTR_TEXT) && tt_cell(t, 4, 0)->width == 1); - assert((tt_cell(t, 5, 0)->attrs & TERM_ATTR_EMOJI) && tt_cell(t, 5, 0)->width == 2); + assert((tt_cell(t, 4, 0)->attrs & WSAP_VTCORE_ATTR_TEXT) && tt_cell(t, 4, 0)->width == 1); + assert((tt_cell(t, 5, 0)->attrs & WSAP_VTCORE_ATTR_EMOJI) && tt_cell(t, 5, 0)->width == 2); assert(tt_cell(t, 6, 0)->width == 0); tt_select(t, 0, 0, 6, 0); text = tt_selection_text(t); assert(text && !strcmp(text, clusters)); free(text); - term_free(t); + wsap_vtcore_free(t); /* BS with a pending wrap clears the wrap and moves left from the last * column, as in xterm and the VT100. */ @@ -2471,11 +2471,11 @@ int main(void) write_seq(t, "\b \b"); assert(row_is(t, 0, "123 5")); assert(tt_cursor_x(t) == 3 && tt_cursor_y(t) == 0); - term_free(t); + wsap_vtcore_free(t); /* A renderer sees each cursor move within the row. */ t = tt_new(10, 2); - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); write_seq(t, "abc"); uint64_t version = view_version(snap, t); write_seq(t, "\b"); @@ -2486,14 +2486,14 @@ int main(void) version = view_version(snap, t); write_seq(t, "\t"); assert(tt_cursor_x(t) == 8 && view_version(snap, t) != version); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); t = tt_new(20, 2); tt_write(t, "hello world", 11); assert(row_is(t, 0, "hello world")); assert(tt_cursor_x(t) == 11 && tt_cursor_y(t) == 0); - term_free(t); + wsap_vtcore_free(t); title[0] = 0; t = tt_new_opts(10, 4, &title_cb); @@ -2503,18 +2503,18 @@ int main(void) assert(!strcmp(title, "Second Title")); write_seq(t, "\033]1;Icon Name\007"); assert(!strcmp(title, "Icon Name")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(20, 4); write_seq(t, "$ /mnt/work"); const char *round_trip = "\033[?1049h\033[?1049l"; tt_write(t, round_trip, strlen(round_trip)); assert(row_is(t, 0, "$ /mnt/work")); - term_free(t); + wsap_vtcore_free(t); /* A renderer sees both switches between the screens. */ t = tt_new(20, 4); - snap = term_snapshot_new(); + snap = wsap_vtcore_snapshot_new(); write_seq(t, "$ /mnt/work"); version = view_version(snap, t); write_seq(t, "\033[?1049h"); @@ -2523,22 +2523,22 @@ int main(void) write_seq(t, "\033[?1049l"); assert(view_version(snap, t) != version); assert(row_is(t, 0, "$ /mnt/work")); - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); t = tt_new(20, 4); write_seq(t, "output"); write_seq(t, "\r\033[K../"); assert(row_is(t, 0, "../")); - term_free(t); + wsap_vtcore_free(t); t = tt_new(80, 24); - assert(!term_modes(t).alternate); + assert(!wsap_vtcore_modes(t).alternate); write_seq(t, "\033[?1049h"); - assert(term_modes(t).alternate); + assert(wsap_vtcore_modes(t).alternate); write_seq(t, "\033[?1049l"); - assert(!term_modes(t).alternate); - term_free(t); + assert(!wsap_vtcore_modes(t).alternate); + wsap_vtcore_free(t); const char *color_runs[] = { "\033[1;1H\033[48;2;10;20;30m\033[38;2;200;210;220ma" @@ -2560,9 +2560,9 @@ int main(void) assert(tt_cell(t, 1, 0)->fg == 0xffe6f0fa); assert(tt_cell(t, 1, 0)->bg == 0xff646e78); for (int col = 2; col < 100; col++) - assert(tt_cell(t, col, 0)->bg == TERM_COLOR_BG); + assert(tt_cell(t, col, 0)->bg == WSAP_VTCORE_COLOR_BG); assert(row_is(t, 1, "")); - term_free(t); + wsap_vtcore_free(t); } } diff --git a/tests/unicode/unicode_test.c b/tests/unicode/unicode_test.c index e3cf5a7..dd6534b 100644 --- a/tests/unicode/unicode_test.c +++ b/tests/unicode/unicode_test.c @@ -1,4 +1,4 @@ -#include "term/unicode/utf8.h" +#include "wsap_vtcore/unicode/utf8.h" #include <assert.h> #include <stdio.h> #include <string.h> @@ -16,17 +16,17 @@ static void test_utf8_decode_one(void) for (size_t i = 0; i < sizeof(valid) / sizeof(*valid); i++) { uint32_t cp = 0xdeadbeef; for (int n = 0; n < valid[i].len; n++) { - int r = term_utf8_decode_one(valid[i].bytes, n, &cp); + int r = wsap_vtcore_utf8_decode_one(valid[i].bytes, n, &cp); assert(r == 0); assert(cp == 0xdeadbeef); } - int r = term_utf8_decode_one(valid[i].bytes, valid[i].len, &cp); + int r = wsap_vtcore_utf8_decode_one(valid[i].bytes, valid[i].len, &cp); assert(r == valid[i].len); assert(cp == valid[i].cp); char followed[8]; memcpy(followed, valid[i].bytes, valid[i].len); memcpy(followed + valid[i].len, "next", 4); - r = term_utf8_decode_one(followed, valid[i].len + 4, &cp); + r = wsap_vtcore_utf8_decode_one(followed, valid[i].len + 4, &cp); assert(r == valid[i].len); assert(cp == valid[i].cp); } @@ -38,7 +38,7 @@ static void test_utf8_decode_one(void) }; for (size_t i = 0; i < sizeof(invalid) / sizeof(*invalid); i++) { uint32_t cp = 0xdeadbeef; - int r = term_utf8_decode_one(invalid[i], strlen(invalid[i]), &cp); + int r = wsap_vtcore_utf8_decode_one(invalid[i], strlen(invalid[i]), &cp); assert(r == 0); assert(cp == 0xdeadbeef); } @@ -48,24 +48,24 @@ static void test_scalar_roundtrips(void) { for (uint32_t cp = 0; cp <= 0x10ffff; cp++) { if (cp >= 0xd800 && cp <= 0xdfff) continue; - char bytes[TERM_UTF8_MAX_BYTES]; - int len = term_utf8_encode(cp, bytes); - uint32_t scalar = 0, streamed = 0, state = TERM_UTF8_ACCEPT; - int r = term_utf8_decode_one(bytes, (size_t)len, &scalar); + char bytes[WSAP_VTCORE_UTF8_MAX_BYTES]; + int len = wsap_vtcore_utf8_encode(cp, bytes); + uint32_t scalar = 0, streamed = 0, state = WSAP_VTCORE_UTF8_ACCEPT; + int r = wsap_vtcore_utf8_decode_one(bytes, (size_t)len, &scalar); assert(r == len); assert(scalar == cp); for (int i = 0; i < len; i++) { - term_utf8_decode(&state, &streamed, (unsigned char)bytes[i]); - if (i + 1 < len) assert(state != TERM_UTF8_ACCEPT && state != TERM_UTF8_REJECT); + wsap_vtcore_utf8_decode(&state, &streamed, (unsigned char)bytes[i]); + if (i + 1 < len) assert(state != WSAP_VTCORE_UTF8_ACCEPT && state != WSAP_VTCORE_UTF8_REJECT); } - assert(state == TERM_UTF8_ACCEPT && streamed == cp); + assert(state == WSAP_VTCORE_UTF8_ACCEPT && streamed == cp); } static const uint32_t invalid[] = {0xd800, 0xdfff, 0x110000, UINT32_MAX}; for (size_t i = 0; i < sizeof(invalid) / sizeof(*invalid); i++) { - char bytes[TERM_UTF8_MAX_BYTES]; - int len = term_utf8_encode(invalid[i], bytes); + char bytes[WSAP_VTCORE_UTF8_MAX_BYTES]; + int len = wsap_vtcore_utf8_encode(invalid[i], bytes); uint32_t cp = 0; - int r = term_utf8_decode_one(bytes, len, &cp); + int r = wsap_vtcore_utf8_decode_one(bytes, len, &cp); assert(len == 3 && r == len && cp == 0xfffd); } } @@ -74,26 +74,26 @@ static void test_utf8_sanitize(void) { char dst[64]; - term_utf8_sanitize(dst, sizeof(dst), "hello \xe2\x82\xac\xf0\x9f\x98\x80"); + wsap_vtcore_utf8_sanitize(dst, sizeof(dst), "hello \xe2\x82\xac\xf0\x9f\x98\x80"); assert(!strcmp(dst, "hello \xe2\x82\xac\xf0\x9f\x98\x80")); - term_utf8_sanitize(dst, sizeof(dst), "a\xff\x80" "b\xed\xa0\x80" "c\xe2\x82"); + wsap_vtcore_utf8_sanitize(dst, sizeof(dst), "a\xff\x80" "b\xed\xa0\x80" "c\xe2\x82"); assert(!strcmp(dst, "abc")); - term_utf8_sanitize(dst, sizeof(dst), ""); + wsap_vtcore_utf8_sanitize(dst, sizeof(dst), ""); assert(!strcmp(dst, "")); - term_utf8_sanitize(dst, sizeof(dst), "\xff\xfe"); + wsap_vtcore_utf8_sanitize(dst, sizeof(dst), "\xff\xfe"); assert(!strcmp(dst, "")); - term_utf8_sanitize(dst, 6, "ab\xe2\x82\xac" "cd"); + wsap_vtcore_utf8_sanitize(dst, 6, "ab\xe2\x82\xac" "cd"); assert(!strcmp(dst, "ab\xe2\x82\xac")); - term_utf8_sanitize(dst, 5, "ab\xe2\x82\xac" "cd"); + wsap_vtcore_utf8_sanitize(dst, 5, "ab\xe2\x82\xac" "cd"); assert(!strcmp(dst, "abcd")); memset(dst, 'x', sizeof(dst)); - term_utf8_sanitize(dst, 4, "abcdef"); + wsap_vtcore_utf8_sanitize(dst, 4, "abcdef"); assert(!strcmp(dst, "abc")); memset(dst, 'x', sizeof(dst)); - term_utf8_sanitize(dst, 0, "abc"); + wsap_vtcore_utf8_sanitize(dst, 0, "abc"); assert(dst[0] == 'x'); } @@ -101,30 +101,30 @@ static void test_utf8_sanitize(void) * stays unused. */ static void test_ground_invalid_subparts(void) { - uint32_t state = TERM_UTF8_ACCEPT, codep = 0, cp = 0xdead; - int n = term_utf8_decode_ground(&state, &codep, "\xe2\x80\x1b\xac", 4, &cp); + uint32_t state = WSAP_VTCORE_UTF8_ACCEPT, codep = 0, cp = 0xdead; + int n = wsap_vtcore_utf8_decode_ground(&state, &codep, "\xe2\x80\x1b\xac", 4, &cp); assert(n == 2); assert(cp == 0xFFFD); - assert(state == TERM_UTF8_ACCEPT); - n = term_utf8_decode_ground(&state, &codep, "\xac", 1, &cp); + assert(state == WSAP_VTCORE_UTF8_ACCEPT); + n = wsap_vtcore_utf8_decode_ground(&state, &codep, "\xac", 1, &cp); assert(n == 1); assert(cp == 0xFFFD); - assert(state == TERM_UTF8_ACCEPT); - n = term_utf8_decode_ground(&state, &codep, "\xe2\x82z", 3, &cp); + assert(state == WSAP_VTCORE_UTF8_ACCEPT); + n = wsap_vtcore_utf8_decode_ground(&state, &codep, "\xe2\x82z", 3, &cp); assert(n == 2); assert(cp == 0xFFFD); - assert(state == TERM_UTF8_ACCEPT); - n = term_utf8_decode_ground(&state, &codep, "\xe2\x82", 2, &cp); + assert(state == WSAP_VTCORE_UTF8_ACCEPT); + n = wsap_vtcore_utf8_decode_ground(&state, &codep, "\xe2\x82", 2, &cp); assert(n == 2); assert(cp == 0); - assert(state != TERM_UTF8_ACCEPT); + assert(state != WSAP_VTCORE_UTF8_ACCEPT); - state = TERM_UTF8_ACCEPT; + state = WSAP_VTCORE_UTF8_ACCEPT; codep = 0; - n = term_utf8_decode_ground(&state, &codep, "\xe2\x82\xac", 3, &cp); + n = wsap_vtcore_utf8_decode_ground(&state, &codep, "\xe2\x82\xac", 3, &cp); assert(n == 3); assert(cp == 0x20ac); - assert(state == TERM_UTF8_ACCEPT); + assert(state == WSAP_VTCORE_UTF8_ACCEPT); } int main(void) diff --git a/tests/version_test.c b/tests/version_test.c index 0eb889e..9893e2f 100644 --- a/tests/version_test.c +++ b/tests/version_test.c @@ -1,27 +1,27 @@ -#include "term/term.h" +#include "wsap_vtcore/wsap_vtcore.h" #include <assert.h> #include <stdio.h> #include <string.h> /* The project version from meson.build. The build defines it. */ -#ifndef TERM_TEST_PROJECT_VERSION -#error "define TERM_TEST_PROJECT_VERSION as the project version, such as \"0.1.0\"" +#ifndef WSAP_VTCORE_TEST_PROJECT_VERSION +#error "define WSAP_VTCORE_TEST_PROJECT_VERSION as the project version, such as \"0.1.0\"" #endif int main(void) { char text[32]; snprintf(text, sizeof(text), "%d.%d.%d", - TERM_VERSION_MAJOR, TERM_VERSION_MINOR, TERM_VERSION_PATCH); - assert(!strcmp(text, TERM_TEST_PROJECT_VERSION)); + WSAP_VTCORE_VERSION_MAJOR, WSAP_VTCORE_VERSION_MINOR, WSAP_VTCORE_VERSION_PATCH); + assert(!strcmp(text, WSAP_VTCORE_TEST_PROJECT_VERSION)); int major, minor, patch; - assert(sscanf(TERM_TEST_PROJECT_VERSION, "%d.%d.%d", &major, &minor, &patch) == 3); - assert(TERM_VERSION_CODE == TERM_VERSION(major, minor, patch)); - assert(term_version() == TERM_VERSION_CODE); + assert(sscanf(WSAP_VTCORE_TEST_PROJECT_VERSION, "%d.%d.%d", &major, &minor, &patch) == 3); + assert(WSAP_VTCORE_VERSION_CODE == WSAP_VTCORE_VERSION(major, minor, patch)); + assert(wsap_vtcore_version() == WSAP_VTCORE_VERSION_CODE); - assert(TERM_VERSION(0, 2, 0) > TERM_VERSION(0, 1, 255)); - assert(TERM_VERSION(1, 0, 0) > TERM_VERSION(0, 255, 255)); + assert(WSAP_VTCORE_VERSION(0, 2, 0) > WSAP_VTCORE_VERSION(0, 1, 255)); + assert(WSAP_VTCORE_VERSION(1, 0, 0) > WSAP_VTCORE_VERSION(0, 255, 255)); return 0; } diff --git a/tests/view_test.c b/tests/view_test.c index 5e17450..02eeede 100644 --- a/tests/view_test.c +++ b/tests/view_test.c @@ -16,9 +16,9 @@ #define VIEW_TEXT_CAP 256 /* The text of a view row, trailing blanks cut. */ -static void view_row_text(struct term *t, int row, char *buf, size_t cap) +static void view_row_text(struct wsap_vtcore *t, int row, char *buf, size_t cap) { - const struct term_cell *cells = term_snapshot_row(tt_snapshot_for(t), row); + const struct wsap_vtcore_cell *cells = wsap_vtcore_snapshot_row(tt_snapshot_for(t), row); size_t n = 0; for (int c = 0; c < tt_cols(t) && n + 1 < cap; c++) { uint32_t cp = tt_cell_cp(t, &cells[c]); @@ -29,7 +29,7 @@ static void view_row_text(struct term *t, int row, char *buf, size_t cap) buf[n] = 0; } -static bool view_row_is(struct term *t, int row, const char *want) +static bool view_row_is(struct wsap_vtcore *t, int row, const char *want) { char got[VIEW_TEXT_CAP]; view_row_text(t, row, got, sizeof(got)); @@ -38,7 +38,7 @@ static bool view_row_is(struct term *t, int row, const char *want) /* Every view row holds the text of the same row in want. A view row that * resolves to no row at all fails the text compare. */ -static void assert_view_rows_equal(struct term *t, struct term *want) +static void assert_view_rows_equal(struct wsap_vtcore *t, struct wsap_vtcore *want) { for (int row = 0; row < tt_rows(t); row++) { char got[VIEW_TEXT_CAP], expect[VIEW_TEXT_CAP]; @@ -51,30 +51,30 @@ static void assert_view_rows_equal(struct term *t, struct term *want) /* The view offset, in range, and the same as the snapshot reports. The two * must come from one field: a second copy of the offset is what let the * scrollbar and the rows disagree. */ -static void assert_offset_agrees(struct term *t) +static void assert_offset_agrees(struct wsap_vtcore *t) { - const struct term_view *v = term_snapshot_view(tt_snapshot_for(t)); - struct term_scrollback sb = term_scrollback(t); + const struct wsap_vtcore_view *v = wsap_vtcore_snapshot_view(tt_snapshot_for(t)); + struct wsap_vtcore_scrollback sb = wsap_vtcore_scrollback(t); assert(sb.offset == v->scroll_offset); assert(sb.offset >= 0); assert(sb.offset <= sb.total); } /* A terminal whose history is small enough to fill. */ -static struct term *small_history_term(int cols, int rows, int scrollback) +static struct wsap_vtcore *small_history_term(int cols, int rows, int scrollback) { - struct term_options opt = { + struct wsap_vtcore_options opt = { .size = { .x = cols, .y = rows }, .scrollback = scrollback, }; - struct term *t = term_new(&opt); + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); return t; } /* Fill the history with count lines of "Lnn" and leave the cursor on the * last screen row. */ -static void feed_lines(struct term *t, const char *tag, int count) +static void feed_lines(struct wsap_vtcore *t, const char *tag, int count) { char line[64]; for (int i = 0; i < count; i++) { @@ -87,12 +87,12 @@ static void feed_lines(struct term *t, const char *tag, int count) * on the same text. */ static void view_holds_text_while_output_arrives(void) { - struct term *t = tt_new(12, 5); - struct term *reference = tt_new(12, 5); + struct wsap_vtcore *t = tt_new(12, 5); + struct wsap_vtcore *reference = tt_new(12, 5); feed_lines(t, "L", 15); feed_lines(reference, "L", 15); - term_scroll(t, 2); - term_scroll(reference, 2); + wsap_vtcore_scroll(t, 2); + wsap_vtcore_scroll(reference, 2); assert(tt_view_offset(t) == 2); assert_view_rows_equal(t, reference); @@ -101,8 +101,8 @@ static void view_holds_text_while_output_arrives(void) assert_offset_agrees(t); /* Nothing was evicted, so the view still shows the rows it showed. */ assert_view_rows_equal(t, reference); - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } /* A view that sits at the top of the history keeps the oldest text there @@ -111,12 +111,12 @@ static void view_holds_text_while_output_arrives(void) static void view_at_the_top_keeps_the_oldest_text(void) { const int scrollback = 20; - struct term *t = small_history_term(12, 5, scrollback); - struct term *reference = small_history_term(12, 5, scrollback); + struct wsap_vtcore *t = small_history_term(12, 5, scrollback); + struct wsap_vtcore *reference = small_history_term(12, 5, scrollback); feed_lines(t, "L", 12); feed_lines(reference, "L", 12); - term_scroll_to(t, INT_MAX); - term_scroll_to(reference, INT_MAX); + wsap_vtcore_scroll_to(t, INT_MAX); + wsap_vtcore_scroll_to(reference, INT_MAX); int total = tt_history(t); assert(total > 0 && total + tt_rows(t) <= scrollback); assert(tt_view_offset(t) == total); @@ -131,8 +131,8 @@ static void view_at_the_top_keeps_the_oldest_text(void) assert(tt_view_offset(t) == total + 3); assert(view_row_is(t, 0, "L00")); assert_view_rows_equal(t, reference); - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } /* Output larger than the history evicts the rows the view was anchored to. @@ -141,11 +141,11 @@ static void view_at_the_top_keeps_the_oldest_text(void) static void view_survives_output_larger_than_history(void) { const int scrollback = 20; - struct term *t = small_history_term(12, 5, scrollback); - struct term *reference = small_history_term(12, 5, scrollback); + struct wsap_vtcore *t = small_history_term(12, 5, scrollback); + struct wsap_vtcore *reference = small_history_term(12, 5, scrollback); feed_lines(t, "L", 15); feed_lines(reference, "L", 15); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); feed_lines(t, "M", 40); feed_lines(reference, "M", 40); @@ -155,12 +155,12 @@ static void view_survives_output_larger_than_history(void) assert(tt_view_offset(t) > 0); /* The top of the history is where the view ends up. */ - term_scroll(reference, INT_MAX); + wsap_vtcore_scroll(reference, INT_MAX); assert(tt_view_offset(reference) == tt_history(reference)); assert(tt_view_offset(t) == tt_history(t)); assert_view_rows_equal(t, reference); - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } /* An eviction can drop a line that wraps to more rows than the push adds. @@ -169,16 +169,16 @@ static void view_survives_output_larger_than_history(void) static void view_survives_eviction_of_a_wrapped_line(void) { const int scrollback = 20; - struct term *t = small_history_term(12, 5, scrollback); - struct term *reference = small_history_term(12, 5, scrollback); + struct wsap_vtcore *t = small_history_term(12, 5, scrollback); + struct wsap_vtcore *reference = small_history_term(12, 5, scrollback); /* The oldest line wraps to three rows. */ const char *wrapped = "0123456789012345678901234\r\n"; tt_puts(t, wrapped); tt_puts(reference, wrapped); feed_lines(t, "s", 22); feed_lines(reference, "s", 22); - term_scroll_to(t, INT_MAX); - term_scroll_to(reference, INT_MAX); + wsap_vtcore_scroll_to(t, INT_MAX); + wsap_vtcore_scroll_to(reference, INT_MAX); assert_offset_agrees(t); /* The next line evicts the wrapped one: three rows go, one arrives. */ @@ -189,11 +189,11 @@ static void view_survives_eviction_of_a_wrapped_line(void) assert(tt_view_offset(t) <= tt_history(t)); } /* The view sits on the oldest text the terminal still keeps. */ - term_scroll_to(reference, INT_MAX); + wsap_vtcore_scroll_to(reference, INT_MAX); assert(tt_view_offset(t) == tt_view_offset(reference)); assert_view_rows_equal(t, reference); - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } /* A resize keeps the same retained text at the top of the view. */ @@ -203,21 +203,21 @@ static void view_keeps_anchor_on_resize(void) int cols, rows; } sizes[] = { { 12, 6 }, { 20, 5 }, { 6, 5 } }; for (size_t i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) { - struct term *t = tt_new(12, 5); - struct term *reference = tt_new(12, 5); + struct wsap_vtcore *t = tt_new(12, 5); + struct wsap_vtcore *reference = tt_new(12, 5); feed_lines(t, "L", 15); feed_lines(reference, "L", 15); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert(tt_view_offset(t) == 3); assert(tt_resize(t, sizes[i].cols, sizes[i].rows)); assert(tt_resize(reference, sizes[i].cols, sizes[i].rows)); assert_offset_agrees(t); assert(tt_view_offset(t) > 0); assert(view_row_is(t, 0, "L08")); - term_scroll_to(t, 0); + wsap_vtcore_scroll_to(t, 0); assert_view_rows_equal(t, reference); - term_free(t); - term_free(reference); + wsap_vtcore_free(t); + wsap_vtcore_free(reference); } } @@ -225,9 +225,9 @@ static void view_keeps_anchor_on_resize(void) * back at its own bottom. */ static void view_follows_the_alternate_screen(void) { - struct term *t = tt_new(12, 5); + struct wsap_vtcore *t = tt_new(12, 5); feed_lines(t, "L", 15); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert(tt_view_offset(t) == 3); tt_puts(t, "\033[?1049hALT"); @@ -239,66 +239,66 @@ static void view_follows_the_alternate_screen(void) assert_offset_agrees(t); assert(tt_view_offset(t) == 0); assert(view_row_is(t, 0, "L11")); - term_free(t); + wsap_vtcore_free(t); } /* The view offset has one owner. Every operation that moves or clears the * view leaves the public offset and the snapshot offset equal. */ static void view_offset_has_one_owner(void) { - struct term *t = tt_new(12, 5); + struct wsap_vtcore *t = tt_new(12, 5); feed_lines(t, "L", 15); assert_offset_agrees(t); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert_offset_agrees(t); - term_scroll_to(t, INT_MAX); + wsap_vtcore_scroll_to(t, INT_MAX); assert_offset_agrees(t); assert(tt_view_offset(t) == tt_history(t)); - term_scroll(t, INT_MIN); + wsap_vtcore_scroll(t, INT_MIN); assert_offset_agrees(t); assert(tt_view_offset(t) == 0); - term_free(t); + wsap_vtcore_free(t); } /* ED2 and ED3 return the view to the live screen. RIS keeps the offset, as * it did before the view had an anchor of its own. */ static void view_returns_to_bottom_on_erase(void) { - struct term *t = tt_new(12, 5); + struct wsap_vtcore *t = tt_new(12, 5); feed_lines(t, "L", 15); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); assert(tt_view_offset(t) == 3); tt_puts(t, "\033[2J"); assert_offset_agrees(t); assert(tt_view_offset(t) == 0); - term_scroll(t, 2); + wsap_vtcore_scroll(t, 2); assert(tt_view_offset(t) == 2); tt_puts(t, "\033[3J"); assert_offset_agrees(t); assert(tt_view_offset(t) == 0); assert(tt_history(t) == 0); - term_free(t); + wsap_vtcore_free(t); t = tt_new(12, 5); feed_lines(t, "L", 15); - term_scroll(t, 3); + wsap_vtcore_scroll(t, 3); int before = tt_view_offset(t); tt_puts(t, "\033c"); assert_offset_agrees(t); assert(tt_view_offset(t) == before); - term_free(t); + wsap_vtcore_free(t); } /* Rewrap keeps the cell that selected the anchored segment in view. */ static void wrapped_anchor_survives_resize(void) { - struct term *t = tt_new(10, 3); + struct wsap_vtcore *t = tt_new(10, 3); tt_puts(t, "abcdefghijKLMNOPQRSTuvwxyz\r\n"); feed_lines(t, "L", 10); - term_scroll_to(t, INT_MAX); - term_scroll(t, -1); + wsap_vtcore_scroll_to(t, INT_MAX); + wsap_vtcore_scroll(t, -1); assert(view_row_is(t, 0, "KLMNOPQRST")); tt_select(t, 0, 0, 2, 0); char *selected = tt_selection_text(t); @@ -317,17 +317,17 @@ static void wrapped_anchor_survives_resize(void) assert(tt_resize(t, 6, 3)); assert(view_row_is(t, 0, "ghijKL")); assert_offset_agrees(t); - term_free(t); + wsap_vtcore_free(t); } /* A wide glyph leaves a wrap pad. That pad does not move the anchor. */ static void wide_anchor_survives_resize(void) { - struct term *t = tt_new(5, 3); + struct wsap_vtcore *t = tt_new(5, 3); tt_puts(t, "abcd日本語XYZ\r\n"); feed_lines(t, "L", 10); - term_scroll_to(t, INT_MAX); - term_scroll(t, -1); + wsap_vtcore_scroll_to(t, INT_MAX); + wsap_vtcore_scroll(t, -1); assert(tt_cell_cp(t, tt_view_cell(t, 0, 0)) == 0x65e5); assert(tt_resize(t, 3, 3)); assert_offset_agrees(t); @@ -337,14 +337,14 @@ static void wide_anchor_survives_resize(void) assert(tt_cell_cp(t, tt_view_cell(t, 0, 0)) == 'a'); assert(tt_resize(t, 3, 3)); assert(tt_cell_cp(t, tt_view_cell(t, 1, 0)) == 0x65e5); - term_free(t); + wsap_vtcore_free(t); } /* Incremental and new snapshots must show the same retained rows. */ static void snapshots_agree_after_eviction_and_rewrap(void) { - struct term *t = small_history_term(11, 5, 23); - struct term_snapshot *persistent = term_snapshot_new(); + struct wsap_vtcore *t = small_history_term(11, 5, 23); + struct wsap_vtcore_snapshot *persistent = wsap_vtcore_snapshot_new(); assert(persistent); for (int n = 0; n < 120; n++) { char line[120]; @@ -353,67 +353,67 @@ static void snapshots_agree_after_eviction_and_rewrap(void) if (n % 13 == 0) assert(tt_resize(t, 6 + n % 17, 5)); int total = tt_history(t); - term_scroll_to(t, n % (total + 1)); - assert(term_snapshot_update(persistent, t)); - struct term_snapshot *fresh = term_snapshot_new(); - assert(fresh && term_snapshot_update(fresh, t)); - struct term_vector2i size = term_size(t); + wsap_vtcore_scroll_to(t, n % (total + 1)); + assert(wsap_vtcore_snapshot_update(persistent, t)); + struct wsap_vtcore_snapshot *fresh = wsap_vtcore_snapshot_new(); + assert(fresh && wsap_vtcore_snapshot_update(fresh, t)); + struct wsap_vtcore_vector2i size = wsap_vtcore_size(t); for (int y = 0; y < size.y; y++) { - const struct term_cell *a = term_snapshot_row(persistent, y); - const struct term_cell *b = term_snapshot_row(fresh, y); + const struct wsap_vtcore_cell *a = wsap_vtcore_snapshot_row(persistent, y); + const struct wsap_vtcore_cell *b = wsap_vtcore_snapshot_row(fresh, y); for (int x = 0; x < size.x; x++) { assert(a[x].fg == b[x].fg && a[x].bg == b[x].bg); assert(a[x].width == b[x].width && a[x].attrs == b[x].attrs); uint32_t acp[32], bcp[32]; - int an = term_snapshot_cluster(persistent, a[x].text, acp, 32); - int bn = term_snapshot_cluster(fresh, b[x].text, bcp, 32); + int an = wsap_vtcore_snapshot_cluster(persistent, a[x].text, acp, 32); + int bn = wsap_vtcore_snapshot_cluster(fresh, b[x].text, bcp, 32); assert(an == bn); if (an) assert(!memcmp(acp, bcp, (size_t)an * sizeof(*acp))); else assert(a[x].text == b[x].text); } - assert(term_snapshot_row_key(persistent, y) == term_snapshot_row_key(fresh, y)); + assert(wsap_vtcore_snapshot_row_key(persistent, y) == wsap_vtcore_snapshot_row_key(fresh, y)); } assert_offset_agrees(t); - term_snapshot_free(fresh); + wsap_vtcore_snapshot_free(fresh); } - term_snapshot_free(persistent); - term_free(t); + wsap_vtcore_snapshot_free(persistent); + wsap_vtcore_free(t); } static void snapshots_agree_after_prefix_eviction(void) { - struct term *t = tt_new(1000, 3); + struct wsap_vtcore *t = tt_new(1000, 3); char line[1000]; for (int i = 0; i < 9500; i++) { memset(line, 'A' + i % 26, sizeof(line)); tt_write(t, line, sizeof(line)); } tt_write(t, "\r\n", 2); - term_scroll(t, INT_MAX); - struct term_snapshot *persistent = term_snapshot_new(); - assert(persistent && term_snapshot_update(persistent, t)); - uint64_t old_key = term_snapshot_row_key(persistent, 0); + wsap_vtcore_scroll(t, INT_MAX); + struct wsap_vtcore_snapshot *persistent = wsap_vtcore_snapshot_new(); + assert(persistent && wsap_vtcore_snapshot_update(persistent, t)); + uint64_t old_key = wsap_vtcore_snapshot_row_key(persistent, 0); memset(line, 'z', sizeof(line)); for (int i = 0; i < 1200; i++) { tt_write(t, line, sizeof(line)); tt_write(t, "\r\n", 2); } - assert(term_snapshot_update(persistent, t)); - assert(term_snapshot_row_key(persistent, 0) != old_key); - struct term_snapshot *fresh = term_snapshot_new(); - assert(fresh && term_snapshot_update(fresh, t)); + assert(wsap_vtcore_snapshot_update(persistent, t)); + assert(wsap_vtcore_snapshot_row_key(persistent, 0) != old_key); + struct wsap_vtcore_snapshot *fresh = wsap_vtcore_snapshot_new(); + assert(fresh && wsap_vtcore_snapshot_update(fresh, t)); for (int y = 0; y < 3; y++) { - const struct term_cell *a = term_snapshot_row(persistent, y); - const struct term_cell *b = term_snapshot_row(fresh, y); + const struct wsap_vtcore_cell *a = wsap_vtcore_snapshot_row(persistent, y); + const struct wsap_vtcore_cell *b = wsap_vtcore_snapshot_row(fresh, y); for (int x = 0; x < 1000; x++) assert(a[x].text == b[x].text && a[x].fg == b[x].fg && a[x].bg == b[x].bg); - assert(term_snapshot_row_key(persistent, y) == term_snapshot_row_key(fresh, y)); + assert(wsap_vtcore_snapshot_row_key(persistent, y) == wsap_vtcore_snapshot_row_key(fresh, y)); } - term_snapshot_free(fresh); - term_snapshot_free(persistent); - term_free(t); + wsap_vtcore_snapshot_free(fresh); + wsap_vtcore_snapshot_free(persistent); + wsap_vtcore_free(t); } /* A line that needs more than one storage part stays scannable. Every @@ -422,8 +422,8 @@ static void snapshots_agree_after_prefix_eviction(void) static void view_scrolls_a_line_that_needs_several_parts(void) { const int cols = 40, rows = 6, cells = 2000000; - struct term_options opt = { .size = { .x = cols, .y = rows }, .scrollback = 60000 }; - struct term *t = term_new(&opt); + struct wsap_vtcore_options opt = { .size = { .x = cols, .y = rows }, .scrollback = 60000 }; + struct wsap_vtcore *t = wsap_vtcore_new(&opt); assert(t); char *big = malloc((size_t)cells); assert(big); @@ -436,23 +436,23 @@ static void view_scrolls_a_line_that_needs_several_parts(void) /* The rows still on the screen are not history rows. */ int total = tt_history(t); assert(total == cells / cols - (rows - 1)); - struct term_snapshot *snap = term_snapshot_new(); + struct wsap_vtcore_snapshot *snap = wsap_vtcore_snapshot_new(); assert(snap); for (int off = 1; off <= total; off += 5) { - term_scroll_to(t, off); + wsap_vtcore_scroll_to(t, off); assert(tt_view_offset(t) == off); - assert(term_snapshot_update(snap, t)); + assert(wsap_vtcore_snapshot_update(snap, t)); for (int y = 0; y < rows; y++) { int row = total - off + y; if (row >= total) continue; - const struct term_cell *line = term_snapshot_row(snap, y); + const struct wsap_vtcore_cell *line = wsap_vtcore_snapshot_row(snap, y); for (int x = 0; x < cols; x++) assert(line[x].text == (uint32_t)('0' + (row * cols + x) % 10)); } } - term_snapshot_free(snap); - term_free(t); + wsap_vtcore_snapshot_free(snap); + wsap_vtcore_free(t); } int main(void) diff --git a/tests/write_fuzz_test.c b/tests/write_fuzz_test.c index 8c1475a..d415c5e 100644 --- a/tests/write_fuzz_test.c +++ b/tests/write_fuzz_test.c @@ -1,5 +1,5 @@ /* - * Differential fuzz test for term_feed. Each seed makes random terminal + * Differential fuzz test for wsap_vtcore_feed. Each seed makes random terminal * output: text, controls, CSI and ESC sequences, raw bytes, and resizes. * One terminal gets the output in a few large writes; the bulk fast paths * handle it. A second terminal gets it one byte at a time; the generic @@ -17,18 +17,18 @@ /* Each terminal has its own snapshot, so cells of both stay readable at * the same time. */ -static struct term_snapshot *snap_bulk, *snap_bytes; +static struct wsap_vtcore_snapshot *snap_bulk, *snap_bytes; /* The code points of a cell's text. A cluster has handles that differ * between snapshots, so the test compares its code points. */ -static int cell_text(const struct term_snapshot *s, const struct term_cell *cell, +static int cell_text(const struct wsap_vtcore_snapshot *s, const struct wsap_vtcore_cell *cell, uint32_t *cps, int cap) { - int n = term_snapshot_cluster(s, cell->text, cps, cap); + int n = wsap_vtcore_snapshot_cluster(s, cell->text, cps, cap); return n < cap ? n : cap; } -static bool same_cell(const struct term_cell *a, const struct term_cell *b) +static bool same_cell(const struct wsap_vtcore_cell *a, const struct wsap_vtcore_cell *b) { if (a->fg != b->fg || a->bg != b->bg || a->attrs != b->attrs || a->width != b->width) return false; @@ -38,24 +38,24 @@ static bool same_cell(const struct term_cell *a, const struct term_cell *b) return na == nb && memcmp(ta, tb, (size_t)na * sizeof(ta[0])) == 0; } -static void assert_same(struct term *bulk, struct term *bytes, int seed, int step) +static void assert_same(struct wsap_vtcore *bulk, struct wsap_vtcore *bytes, int seed, int step) { int cols = tt_cols(bulk), rows = tt_rows(bulk); int history = tt_history(bulk); bool same = tt_cursor_x(bulk) == tt_cursor_x(bytes) && tt_cursor_y(bulk) == tt_cursor_y(bytes) && history == tt_history(bytes); - term_scroll(bulk, history); - term_scroll(bytes, history); + wsap_vtcore_scroll(bulk, history); + wsap_vtcore_scroll(bytes, history); for (int page = 0; same && page <= history; page += rows) { - bool copied = term_snapshot_update(snap_bulk, bulk); - copied &= term_snapshot_update(snap_bytes, bytes); + bool copied = wsap_vtcore_snapshot_update(snap_bulk, bulk); + copied &= wsap_vtcore_snapshot_update(snap_bytes, bytes); assert(copied); for (int y = 0; same && y < rows; y++) { - const struct term_cell *ra = term_snapshot_row(snap_bulk, y); - const struct term_cell *rb = term_snapshot_row(snap_bytes, y); + const struct wsap_vtcore_cell *ra = wsap_vtcore_snapshot_row(snap_bulk, y); + const struct wsap_vtcore_cell *rb = wsap_vtcore_snapshot_row(snap_bytes, y); for (int x = 0; x < cols; x++) { - const struct term_cell *a = &ra[x], *b = &rb[x]; + const struct wsap_vtcore_cell *a = &ra[x], *b = &rb[x]; if (!same_cell(a, b)) { fprintf(stderr, "seed %d step %d: page %d row %d col %d: " "bulk %x/%x/%x/%x/%u, bytes %x/%x/%x/%x/%u\n", @@ -66,11 +66,11 @@ static void assert_same(struct term *bulk, struct term *bytes, int seed, int ste } } } - term_scroll(bulk, -rows); - term_scroll(bytes, -rows); + wsap_vtcore_scroll(bulk, -rows); + wsap_vtcore_scroll(bytes, -rows); } - term_scroll_to(bulk, 0); - term_scroll_to(bytes, 0); + wsap_vtcore_scroll_to(bulk, 0); + wsap_vtcore_scroll_to(bytes, 0); if (!same) fprintf(stderr, "seed %d step %d: cursor %d,%d vs %d,%d, history %d vs %d\n", seed, step, tt_cursor_x(bulk), tt_cursor_y(bulk), @@ -85,12 +85,12 @@ int main(int argc, char **argv) for (int seed = 1; seed <= seeds; seed++) { rng = 0x9e3779b97f4a7c15ull * (uint64_t)seed; int cols = 4 + rn(30), rows = 2 + rn(10); - struct term *bulk = tt_new(cols, rows); - struct term *bytes = tt_new(cols, rows); + struct wsap_vtcore *bulk = tt_new(cols, rows); + struct wsap_vtcore *bytes = tt_new(cols, rows); /* A new terminal can get the address of a freed one, so each seed * uses new snapshots. */ - snap_bulk = term_snapshot_new(); - snap_bytes = term_snapshot_new(); + snap_bulk = wsap_vtcore_snapshot_new(); + snap_bytes = wsap_vtcore_snapshot_new(); assert(bulk && bytes && snap_bulk && snap_bytes); for (int step = 0; step < 6; step++) { blen = 0; @@ -110,10 +110,10 @@ int main(int argc, char **argv) assert_same(bulk, bytes, seed, step); } } - term_snapshot_free(snap_bulk); - term_snapshot_free(snap_bytes); - term_free(bulk); - term_free(bytes); + wsap_vtcore_snapshot_free(snap_bulk); + wsap_vtcore_snapshot_free(snap_bytes); + wsap_vtcore_free(bulk); + wsap_vtcore_free(bytes); } return 0; } diff --git a/tools/amalgamate.py b/tools/amalgamate.py index 09c6c91..79f011a 100644 --- a/tools/amalgamate.py +++ b/tools/amalgamate.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 -"""Write the term core as one term.c and one term.h. +"""Write the wsap_vtcore core as one wsap_vtcore.c and one wsap_vtcore.h. -term.h joins the public headers. term.c joins every source file and puts -each private header in at its first include. A host compiles term.c once, -with any C11 compiler, and links libm and the thread library. +wsap_vtcore.h joins the public headers. wsap_vtcore.c joins every source +file and puts each private header in at its first include. A host compiles +wsap_vtcore.c once, with any C11 compiler, and links libm and the thread +library. - amalgamate.py TERM_DIR OUT_DIR [DEPFILE] + amalgamate.py WSAP_VTCORE_DIR OUT_DIR [DEPFILE] -TERM_DIR is the directory with src/ and include/. DEPFILE lists every file +WSAP_VTCORE_DIR is the directory with src/ and include/. DEPFILE lists every file read, for the build system. """ @@ -16,14 +17,14 @@ import sys from pathlib import Path INCLUDE = re.compile(r'^\s*#\s*include\s+"([^"]+)"') -PUBLIC = ("term_types.h", "term_input.h", "term.h") +PUBLIC = ("wsap_vtcore_types.h", "wsap_vtcore_input.h", "wsap_vtcore.h") class Joiner: def __init__(self, root: Path): self.root = root - # The sources find the public headers without the term/ prefix. - self.search = (root / "src", root / "include" / "term") + # The sources find the public headers without the wsap_vtcore/ prefix. + self.search = (root / "src", root / "include" / "wsap_vtcore") self.seen: set[Path] = set() def resolve(self, name: str, base: Path) -> Path: @@ -60,15 +61,15 @@ def main() -> int: print(__doc__, file=sys.stderr) return 2 root = Path(sys.argv[1]).resolve() - public = root / "include" / "term" + public = root / "include" / "wsap_vtcore" out_dir = Path(sys.argv[2]) out_dir.mkdir(parents=True, exist_ok=True) banner = "/* Generated by tools/amalgamate.py. Do not edit. */\n" header = Joiner(root) text = [banner] - header.emit(public / "term.h", text) - (out_dir / "term.h").write_text("".join(text)) + header.emit(public / "wsap_vtcore.h", text) + (out_dir / "wsap_vtcore.h").write_text("".join(text)) body = Joiner(root) text = [banner, @@ -77,16 +78,16 @@ def main() -> int: "#if defined(__clang__)\n" '#pragma clang diagnostic ignored "-Wunused-function"\n' "#endif\n", - '#include "term.h"\n'] - # The public headers are in term.h, so the sources skip them. + '#include "wsap_vtcore.h"\n'] + # The public headers are in wsap_vtcore.h, so the sources skip them. body.seen.update((public / name).resolve() for name in PUBLIC) for src in sources(root / "src"): body.emit(src, text) - (out_dir / "term.c").write_text("".join(text)) + (out_dir / "wsap_vtcore.c").write_text("".join(text)) if len(sys.argv) == 4: read = sorted(header.seen | body.seen) deps = " ".join(str(p).replace(" ", "\\ ") for p in read) - Path(sys.argv[3]).write_text(f"{out_dir / 'term.c'}: {deps}\n") + Path(sys.argv[3]).write_text(f"{out_dir / 'wsap_vtcore.c'}: {deps}\n") return 0 diff --git a/tools/generate_unicode.py b/tools/generate_unicode.py index 22f12a6..340509a 100644 --- a/tools/generate_unicode.py +++ b/tools/generate_unicode.py @@ -71,7 +71,7 @@ def unicode_categories(path): return by_category def emit_table(out, name, ranges): - out.append(f"static const struct term_unicode_range {name}[] = {{") + out.append(f"static const struct wsap_vtcore_unicode_range {name}[] = {{") for i in range(0, len(ranges), 4): chunk = ranges[i:i + 4] out.append("\t" + ",".join(f"{{0x{lo:X},0x{hi:X}}}" for lo, hi in chunk) + ",") @@ -104,13 +104,13 @@ def main(): emoji_presentation = field_ranges(args.emoji_data, {"Emoji_Presentation"}) out = [f"/* Generated from Unicode {version} data by tools/generate_unicode.py. */", "", - f'#define TERM_UNICODE_DATA_VERSION "{version}"', ""] - emit_table(out, "term_zero_width", zero) - emit_table(out, "term_nonprintable", nonprint) - emit_table(out, "term_unicode_wide", wide) - emit_table(out, "term_spacing_mark", spacing) - emit_table(out, "term_extended_pictographic", pictographic) - emit_table(out, "term_emoji_presentation", emoji_presentation) + f'#define WSAP_VTCORE_UNICODE_DATA_VERSION "{version}"', ""] + emit_table(out, "wsap_vtcore_zero_width", zero) + emit_table(out, "wsap_vtcore_nonprintable", nonprint) + emit_table(out, "wsap_vtcore_unicode_wide", wide) + emit_table(out, "wsap_vtcore_spacing_mark", spacing) + emit_table(out, "wsap_vtcore_extended_pictographic", pictographic) + emit_table(out, "wsap_vtcore_emoji_presentation", emoji_presentation) args.output.write_text("\n".join(out)) if __name__ == "__main__": |
