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/csi.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/csi.h')
| -rw-r--r-- | src/csi.h | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/csi.h b/src/csi.h new file mode 100644 index 0000000..b4609ea --- /dev/null +++ b/src/csi.h @@ -0,0 +1,109 @@ +#ifndef CSI_H +#define CSI_H + +#include <stddef.h> +#include <stdint.h> +#include <limits.h> + +#define MAX_PARAMS 16 + +struct csi { + int params[MAX_PARAMS]; + int nparams; + uint16_t subparams; + char prefix, intermediate, final; +}; + +enum csi_phase { CSI_ENTRY, CSI_PARAMETERS, CSI_INTERMEDIATES, CSI_IGNORE }; +enum csi_result { CSI_MORE, CSI_DISPATCH, CSI_DISCARD, CSI_CONTROL }; + +struct csi_parser { + struct csi csi; + enum csi_phase phase; +}; + +static inline void csi_parser_reset(struct csi_parser *p) +{ + p->csi.params[0] = 0; + p->csi.nparams = 0; + p->csi.subparams = 0; + p->csi.prefix = p->csi.intermediate = p->csi.final = 0; + p->phase = CSI_ENTRY; +} + +static inline int csi_count(const struct csi *csi) +{ + return csi->params[0] > 0 ? csi->params[0] : 1; +} + +static inline enum csi_result csi_read(struct csi_parser *restrict p, const char *restrict s, + size_t len, size_t *restrict consumed) +{ + size_t i = 0; + enum csi_result result = CSI_MORE; + while (i < len) { + unsigned char ch = (unsigned char)s[i]; + if (ch < 0x20 || ch >= 0x80) { + result = CSI_CONTROL; + break; + } + i++; + if (ch == 0x7f) continue; + if (ch >= 0x40) { + p->csi.final = (char)ch; + result = p->phase == CSI_IGNORE ? CSI_DISCARD : CSI_DISPATCH; + break; + } + if (p->phase == CSI_IGNORE) continue; + + if (ch >= '0' && ch <= ';') { + if (p->phase == CSI_INTERMEDIATES) { + p->phase = CSI_IGNORE; + continue; + } + p->phase = CSI_PARAMETERS; + int n = p->csi.nparams ? p->csi.nparams : 1; + int value = p->csi.params[n - 1]; + for (;;) { + if (ch <= '9') { + for (;;) { + int digit = ch - '0'; + value = value < 214748364 ? value * 10 + digit : INT_MAX; + if (i == len) break; + ch = (unsigned char)s[i]; + if (ch < '0' || ch > '9') break; + i++; + } + } else { + p->csi.params[n - 1] = value; + if (n == MAX_PARAMS) { + p->phase = CSI_IGNORE; + break; + } + if (ch == ':') p->csi.subparams |= (uint16_t)(1u << n); + n++; + value = 0; + } + if (i == len) break; + ch = (unsigned char)s[i]; + if (ch < '0' || ch > ';') break; + i++; + } + p->csi.params[n - 1] = value; + p->csi.nparams = n; + } else if (ch >= '<') { + if (p->phase != CSI_ENTRY || p->csi.prefix) p->phase = CSI_IGNORE; + else p->csi.prefix = (char)ch; + } else { + if (p->phase == CSI_INTERMEDIATES) p->phase = CSI_IGNORE; + else { + p->phase = CSI_INTERMEDIATES; + p->csi.intermediate = (char)ch; + } + } + } + *consumed = i; + return result; +} + +#endif |
