diff options
| author | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 17:49:34 +0300 |
|---|---|---|
| committer | Berke Güzel <wenekar1@gmail.com> | 2026-10-12 17:49:34 +0300 |
| commit | 4384435941b8c7658856b381d071aee2e0035e89 (patch) | |
| tree | 5ece99c3dd1decb8ec3fd404c0ece2b5865a552a /src/text_run.h | |
term: move the term core to subprojects/term
The core now builds, tests, and benchmarks alone, as a Meson subproject
with no dependency on the main tree.
- include/term/ holds term.h and the header-only unicode/. src/ holds
the core and its private headers. The main tree gets only
include/term through term_dep, so it cannot reach a private header.
- The term tests, the term benchmarks, the Kitty parser suite, and
tools/amalgamate.py and tools/generate_unicode.py move with it. The
tests run as term:<name>.
- The main build passes its -march (arch_flag) and b_ndebug to the
subproject. A directory configured before this commit needs
meson configure -Dterm:arch_flag=-march=... once.
- The term tests compile with -UNDEBUG. They do work inside assert.
- The subproject exports term_test_dep with term_api.h, for the main
tree's render, thumbnail, color, and selection tests.
- The Kitty bridge used struct vector2i and has not compiled since the
public API redesign. It builds again. 2 of its 14 tests fail: REP
after a tab, and a cursor report after a resize.
- dirgraph.py drops the term and unicode layers. Its self-test uses pty.
- The symbols test ignores the __odr_asan symbols that ASan adds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/text_run.h')
| -rw-r--r-- | src/text_run.h | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/text_run.h b/src/text_run.h new file mode 100644 index 0000000..d546062 --- /dev/null +++ b/src/text_run.h @@ -0,0 +1,90 @@ +#ifndef TERM_TEXT_RUN_H +#define TERM_TEXT_RUN_H + +#include "cell.h" +#include "unicode/unicode.h" +#include "unicode/grapheme.h" + +#define UTF8_LEAD_MIN 0xc2 +#define UTF8_LEAD_MAX 0xf4 +#define UTF8_LEAD3_TAG 0xE0 +#define UTF8_LEAD3_MASK 0xF0 + +#define TERM_WIDTH_SLOTS 4 +struct width_cache { + uint32_t lo[TERM_WIDTH_SLOTS]; + uint32_t span[TERM_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); +void term_snapshot_tables_init(void); + +int term_text_class(uint32_t cp); + +struct text_run_result { + int bytes; + int cols; + uint32_t last; +}; + +struct text_run_result term_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); + +struct text_run_bytes { + int bytes; /* input used */ + int cols; + int out; /* bytes written */ + int chars; + uint32_t last; + bool wide, narrow; /* narrow: every character was one ASCII byte */ +}; + +/* term_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, + 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 || grapheme_emoji_modifier(cp)) + return true; + + return klass == 1 && 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 || grapheme_is_handle(last_char)) return true; + if (cp - 0x1F1E6u <= 0x19u && grapheme_regional_indicator(cp)) + return true; + return joins_cluster(cp, klass); +} + +static inline bool cluster_contextual(uint32_t cp) +{ + return unicode_spacing_mark(cp) || grapheme_emoji_modifier(cp) || + (cp - 0x1F1E6u <= 0x19u && grapheme_regional_indicator(cp)); +} + +static inline bool cluster_joins(const uint32_t *cps, int len, + uint32_t cp, int klass) +{ + if (joins_cluster(cp, klass)) + return true; + if (cps[len - 1] == 0x200D) + return unicode_extended_pictographic(cp); + return len == 1 && cp - 0x1F1E6u <= 0x19u && + grapheme_regional_indicator(cp) && + grapheme_regional_indicator(cps[0]); +} + +#endif |
