summaryrefslogtreecommitdiff
path: root/src/pen.h
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 17:49:34 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 17:49:34 +0300
commit4384435941b8c7658856b381d071aee2e0035e89 (patch)
tree5ece99c3dd1decb8ec3fd404c0ece2b5865a552a /src/pen.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/pen.h')
-rw-r--r--src/pen.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/pen.h b/src/pen.h
new file mode 100644
index 0000000..d7118b5
--- /dev/null
+++ b/src/pen.h
@@ -0,0 +1,165 @@
+#ifndef WSAP_TERM_PEN_H
+#define WSAP_TERM_PEN_H
+
+#include "term.h"
+#include <stdbool.h>
+#include <stdint.h>
+
+struct term_pen {
+ uint32_t fg;
+ uint32_t bg;
+ uint32_t ul;
+ uint8_t underline;
+ bool bold : 1;
+ bool faint : 1;
+ bool italic : 1;
+ bool strike : 1;
+ bool overline : 1;
+ bool inverse : 1;
+};
+
+/* The pen of a stored cell. A cell has no underline color, so neither has
+ * this. */
+struct pen_attr {
+ uint32_t fg;
+ uint32_t bg;
+ uint16_t flags;
+ uint16_t link;
+};
+
+static inline struct pen_attr pen_attr_default(void)
+{
+ return (struct pen_attr){ .fg = TERM_COLOR_FG, .bg = TERM_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;
+}
+
+static inline bool pen_attr_equal(const struct pen_attr *a, const struct pen_attr *b)
+{
+ 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)
+{
+ return term_color_rgb((uint8_t)r, (uint8_t)g, (uint8_t)b);
+}
+
+static inline void pen_reset(struct term_pen *p)
+{
+ p->fg = TERM_COLOR_FG;
+ p->bg = TERM_COLOR_BG;
+ p->ul = 0;
+ p->underline = 0;
+ p->bold = false;
+ p->faint = false;
+ p->italic = false;
+ p->strike = false;
+ p->overline = false;
+ p->inverse = false;
+}
+
+static inline int sgr_extended_color(const int *params, int nparams, uint16_t subparams, int i,
+ uint32_t *color, bool *assigned)
+{
+ *assigned = false;
+ if (i + 1 >= nparams)
+ return 0;
+ if (i + 2 < nparams && params[i + 1] == 5) {
+ int index = params[i + 2];
+ if (index >= 0 && index <= 255) {
+ *color = term_color_index(index);
+ *assigned = true;
+ }
+ return 2;
+ }
+ if (params[i + 1] != 2)
+ return 0;
+ int colon = 0;
+ while (i + 2 + colon < nparams && i + 2 + colon < 16 &&
+ (subparams & (1u << (i + 2 + colon))))
+ colon++;
+ 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]);
+ *assigned = true;
+ return 4 + skip;
+}
+
+static inline bool pen_set_standard_color(struct term_pen *p, int code)
+{
+ if ((unsigned)(code - 30) < 8)
+ p->fg = term_color_index(code - 30);
+ else if ((unsigned)(code - 40) < 8)
+ p->bg = term_color_index(code - 40);
+ else if ((unsigned)(code - 90) < 8)
+ p->fg = term_color_index(code - 90 + 8);
+ else if ((unsigned)(code - 100) < 8)
+ p->bg = term_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)
+{
+ if (nparams == 0) {
+ pen_reset(pen);
+ return;
+ }
+ for (int i = 0; i < nparams; i++) {
+ int p = params[i];
+ switch (p) {
+ case 0: pen_reset(pen); break;
+ case 1: pen->bold = true; break;
+ case 2: pen->faint = true; break;
+ case 3: pen->italic = true; break;
+ case 4: {
+ int style = 1;
+ if (i + 1 < nparams && (subparams & (1u << (i + 1))))
+ style = params[++i];
+ pen->underline = (uint8_t)(style <= 5 ? style : 1);
+ break;
+ }
+ case 7: pen->inverse = true; break;
+ case 9: pen->strike = true; break;
+ case 21: pen->underline = 2; break;
+ case 22: pen->bold = false; pen->faint = false; break;
+ case 23: pen->italic = false; break;
+ case 24: pen->underline = 0; break;
+ case 27: pen->inverse = false; break;
+ case 29: pen->strike = false; break;
+ case 38: {
+ uint32_t c; bool ok;
+ i += sgr_extended_color(params, nparams, subparams, i, &c, &ok);
+ if (ok) pen->fg = c;
+ break;
+ }
+ case 39: pen->fg = TERM_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 53: pen->overline = true; break;
+ case 55: pen->overline = false; break;
+ case 58: {
+ uint32_t c; bool ok;
+ i += sgr_extended_color(params, nparams, subparams, i, &c, &ok);
+ if (ok) pen->ul = c;
+ break;
+ }
+ case 59: pen->ul = 0; break;
+ default:
+ pen_set_standard_color(pen, p);
+ break;
+ }
+ }
+}
+
+#endif