summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-15 12:31:21 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-15 12:31:21 +0300
commit212f1cc9109aa0deb9e5d990bb2dba2b167618fb (patch)
tree0044818d9e12d602b4da3b6823d9997557e5cfae
parent5f03033b0e211f9ed13e7a1351f9a8f9011ab665 (diff)
Keep installed headers from shadowing or polluting host names
The pkg-config file put include/term on the host's include path, so ncurses' term.h could be picked up in place of ours. Hosts now write <term/term.h> and the package adds only its include directory. The installed Unicode API had unprefixed names that collide with host symbols and macros. Rename them: term_ for functions, types, and static tables, TERM_ for macros and include guards. unicode_data.inc and tools/generate_unicode.py are renamed to match. The generator's inputs here are Unicode 15.1 and the checked-in table is 18.0.0, so the table data was not regenerated. Only the declarations were checked against the generator. utf8.h casts the malloc result so it compiles as C++. header_test.sh now includes <term/term.h> with only include/ on the path. It also checks that a host which defines unicode_width, UTF8_ACCEPT, GRAPHEME_MAX_LEN, in_ranges, and similar names compiles with the Unicode headers as C11 and C++, in both declaration orders. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
-rw-r--r--README.md7
-rw-r--r--include/term/unicode/grapheme.h12
-rw-r--r--include/term/unicode/unicode_data.inc14
-rw-r--r--include/term/unicode/utf8.h72
-rw-r--r--include/term/unicode/width.h30
-rw-r--r--meson.build2
-rw-r--r--src/core.c24
-rw-r--r--src/gstore.c28
-rw-r--r--src/hist.c14
-rw-r--r--src/input.c4
-rw-r--r--src/selection.c10
-rw-r--r--src/snapshot.c6
-rw-r--r--src/term.c2
-rw-r--r--src/text.c38
-rw-r--r--src/text_run.c24
-rw-r--r--src/text_run.h18
-rw-r--r--tests/gstore_test.c38
-rw-r--r--tests/header_test.sh75
-rw-r--r--tests/hist_test.c12
-rw-r--r--tests/model.c26
-rw-r--r--tests/model.h2
-rw-r--r--tests/model_test.c12
-rw-r--r--tests/term_test.c18
-rw-r--r--tests/unicode/unicode_test.c68
-rw-r--r--tools/generate_unicode.py16
25 files changed, 310 insertions, 262 deletions
diff --git a/README.md b/README.md
index e877a01..1294116 100644
--- a/README.md
+++ b/README.md
@@ -50,8 +50,11 @@ no flags to get them:
`simd.h` states the rules for a new kernel.
-- `term.h` is the only header a host includes. It includes
- `term_input.h` and `term_types.h`. It compiles as C11 and as C++.
+- `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.
diff --git a/include/term/unicode/grapheme.h b/include/term/unicode/grapheme.h
index 5573949..0946bb6 100644
--- a/include/term/unicode/grapheme.h
+++ b/include/term/unicode/grapheme.h
@@ -5,20 +5,20 @@
#include <stddef.h>
#include <stdint.h>
-#define GRAPHEME_MAX_LEN 20
-#define GRAPHEME_HANDLE_BASE 0x7F000000u
+#define TERM_GRAPHEME_MAX_LEN 20
+#define TERM_GRAPHEME_HANDLE_BASE 0x7F000000u
-static inline bool grapheme_is_handle(uint32_t c)
+static inline bool term_grapheme_is_handle(uint32_t c)
{
- return c >= GRAPHEME_HANDLE_BASE;
+ return c >= TERM_GRAPHEME_HANDLE_BASE;
}
-static inline bool grapheme_regional_indicator(uint32_t cp)
+static inline bool term_grapheme_regional_indicator(uint32_t cp)
{
return cp >= 0x1F1E6 && cp <= 0x1F1FF;
}
-static inline bool grapheme_emoji_modifier(uint32_t cp)
+static inline bool term_grapheme_emoji_modifier(uint32_t cp)
{
return cp >= 0x1F3FB && cp <= 0x1F3FF;
}
diff --git a/include/term/unicode/unicode_data.inc b/include/term/unicode/unicode_data.inc
index 8053b01..4ab1461 100644
--- a/include/term/unicode/unicode_data.inc
+++ b/include/term/unicode/unicode_data.inc
@@ -1,8 +1,8 @@
/* Generated from Unicode 18.0.0 data by tools/generate_unicode.py. */
-#define UNICODE_DATA_VERSION "18.0.0"
+#define TERM_UNICODE_DATA_VERSION "18.0.0"
-static const struct unicode_range zero_width[] = {
+static const struct term_unicode_range term_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 unicode_range zero_width[] = {
{0xE0020,0xE007F},{0xE0100,0xE01EF},
};
-static const struct unicode_range nonprintable[] = {
+static const struct term_unicode_range term_nonprintable[] = {
{0x0,0x1F},{0x7F,0x9F},{0xD800,0xDFFF},
};
-static const struct unicode_range unicode_wide[] = {
+static const struct term_unicode_range term_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 unicode_range unicode_wide[] = {
{0x20000,0x2FFFD},{0x30000,0x3FFFD},
};
-static const struct unicode_range spacing_mark[] = {
+static const struct term_unicode_range term_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 unicode_range spacing_mark[] = {
{0x1D16D,0x1D172},{0x1D250,0x1D252},{0x1D25F,0x1D25F},{0x1D280,0x1D281},
};
-static const struct unicode_range extended_pictographic[] = {
+static const struct term_unicode_range term_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 unicode_range extended_pictographic[] = {
{0x1F947,0x1F9FF},{0x1FA58,0x1FA5F},{0x1FA6E,0x1FAFF},{0x1FC00,0x1FFFD},
};
-static const struct unicode_range emoji_presentation[] = {
+static const struct term_unicode_range term_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/term/unicode/utf8.h
index 1c3cc3f..ad44465 100644
--- a/include/term/unicode/utf8.h
+++ b/include/term/unicode/utf8.h
@@ -1,19 +1,19 @@
-#ifndef UTF_8_H
-#define UTF_8_H
+#ifndef TERM_UNICODE_UTF8_H
+#define TERM_UNICODE_UTF8_H
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-#define UTF8_ACCEPT 0
-#define UTF8_REJECT 1
+#define TERM_UTF8_ACCEPT 0
+#define TERM_UTF8_REJECT 1
-#define UTF8_3BYTE_MIN 0x800u
-#define UTF8_SURROGATE_LO 0xd800u
-#define UTF8_SURROGATE_HI 0xdfffu
+#define TERM_UTF8_3BYTE_MIN 0x800u
+#define TERM_UTF8_SURROGATE_LO 0xd800u
+#define TERM_UTF8_SURROGATE_HI 0xdfffu
-static const uint8_t utf8d[] = {
+static const uint8_t term_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 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 utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) {
+static inline uint32_t term_utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) {
byte &= 0xff;
- uint32_t type = utf8d[byte];
+ uint32_t type = term_utf8d[byte];
- *codep = (*state != UTF8_ACCEPT) ?
+ *codep = (*state != TERM_UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
- *state = utf8d[256 + *state*16 + type];
+ *state = term_utf8d[256 + *state*16 + type];
return *state;
}
-static const uint8_t utf8_acc_state[256] = {
+static const uint8_t term_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 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 utf8_acc_codep[256] = {
+static const uint8_t term_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 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 utf8_decode_ground(uint32_t *state, uint32_t *codep,
+static inline int term_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 utf8_decode_ground(uint32_t *state, uint32_t *codep,
do {
unsigned char c = (unsigned char)buf[n];
if (c < 0x20) {
- if (st != UTF8_ACCEPT) *cp = 0xFFFD;
- st = UTF8_ACCEPT;
+ if (st != TERM_UTF8_ACCEPT) *cp = 0xFFFD;
+ st = TERM_UTF8_ACCEPT;
break;
}
uint32_t before = st;
n++;
- if (st == UTF8_ACCEPT) {
- cpv = utf8_acc_codep[c];
- st = utf8_acc_state[c];
+ if (st == TERM_UTF8_ACCEPT) {
+ cpv = term_utf8_acc_codep[c];
+ st = term_utf8_acc_state[c];
} else {
- uint32_t type = utf8d[c];
+ uint32_t type = term_utf8d[c];
cpv = (c & 0x3fu) | (cpv << 6);
- st = utf8d[256 + st*16 + type];
+ st = term_utf8d[256 + st*16 + type];
}
- if (st == UTF8_ACCEPT) { *cp = cpv; break; }
- if (st == UTF8_REJECT) {
- st = UTF8_ACCEPT;
+ if (st == TERM_UTF8_ACCEPT) { *cp = cpv; break; }
+ if (st == TERM_UTF8_REJECT) {
+ st = TERM_UTF8_ACCEPT;
*cp = 0xFFFD;
- if (before != UTF8_ACCEPT) n--;
+ if (before != TERM_UTF8_ACCEPT) n--;
break;
}
} while ((size_t)n < len);
@@ -125,7 +125,7 @@ static inline int utf8_decode_ground(uint32_t *state, uint32_t *codep,
}
static inline int
-utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
+term_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 @@ 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 < UTF8_3BYTE_MIN ||
- (cp >= UTF8_SURROGATE_LO && cp <= UTF8_SURROGATE_HI))
+ if (cp < TERM_UTF8_3BYTE_MIN ||
+ (cp >= TERM_UTF8_SURROGATE_LO && cp <= TERM_UTF8_SURROGATE_HI))
return 0;
*codep = cp;
return 3;
@@ -183,14 +183,14 @@ utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
}
static inline void
-utf8_sanitize(char *dst, size_t cap, const char *src)
+term_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 = utf8_decode_one(src + off, len - off, &cp);
+ int n = term_utf8_decode_one(src + off, len - off, &cp);
if (n <= 0 || i + (size_t)n >= cap) {
off++;
continue;
@@ -204,17 +204,17 @@ 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 *utf8_sanitize_dup(const char *src)
+static inline char *term_utf8_sanitize_dup(const char *src)
{
size_t cap = strlen(src) + 1;
- char *dst = malloc(cap);
+ char *dst = (char *)malloc(cap);
if (dst)
- utf8_sanitize(dst, cap, src);
+ term_utf8_sanitize(dst, cap, src);
return dst;
}
-#define UTF8_MAX_BYTES 4
-static inline int utf8_encode(uint32_t cp, char *out)
+#define TERM_UTF8_MAX_BYTES 4
+static inline int term_utf8_encode(uint32_t cp, char *out)
{
if (cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
cp = 0xfffd;
diff --git a/include/term/unicode/width.h b/include/term/unicode/width.h
index a7dfe66..a85ec77 100644
--- a/include/term/unicode/width.h
+++ b/include/term/unicode/width.h
@@ -5,15 +5,15 @@
#include <stddef.h>
#include <stdint.h>
-struct unicode_range { uint32_t lo, hi; };
+struct term_unicode_range { uint32_t lo, hi; };
#include "unicode_data.inc"
-static inline bool in_ranges(const struct unicode_range *ranges, size_t count, uint32_t cp)
+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 unicode_range *base = ranges;
+ const struct term_unicode_range *base = ranges;
size_t n = count;
while (n > 1) {
size_t half = n / 2;
@@ -23,34 +23,34 @@ static inline bool in_ranges(const struct unicode_range *ranges, size_t count, u
return cp <= base->hi;
}
-#define IN_TABLE(table, cp) in_ranges(table, sizeof(table) / sizeof(table[0]), cp)
+#define TERM_IN_TABLE(table, cp) term_in_ranges(table, sizeof(table) / sizeof(table[0]), cp)
-static inline int unicode_width(uint32_t cp)
+static inline int term_unicode_width(uint32_t cp)
{
- if (cp > 0x10FFFF || IN_TABLE(nonprintable, cp))
+ if (cp > 0x10FFFF || TERM_IN_TABLE(term_nonprintable, cp))
return -1;
- if (IN_TABLE(zero_width, cp))
+ if (TERM_IN_TABLE(term_zero_width, cp))
return 0;
- return IN_TABLE(unicode_wide, cp) ? 2 : 1;
+ return TERM_IN_TABLE(term_unicode_wide, cp) ? 2 : 1;
}
-static inline bool unicode_extended_pictographic(uint32_t cp)
+static inline bool term_unicode_extended_pictographic(uint32_t cp)
{
- return IN_TABLE(extended_pictographic, cp);
+ return TERM_IN_TABLE(term_extended_pictographic, cp);
}
-static inline bool unicode_emoji_presentation(uint32_t cp)
+static inline bool term_unicode_emoji_presentation(uint32_t cp)
{
- return IN_TABLE(emoji_presentation, cp);
+ return TERM_IN_TABLE(term_emoji_presentation, cp);
}
-static inline bool unicode_spacing_mark(uint32_t cp)
+static inline bool term_unicode_spacing_mark(uint32_t cp)
{
if (cp < 0x903 || ((cp - 0xABEDu) < (0x11000u - 0xABEDu)) || cp > 0x1D281)
return false;
- return IN_TABLE(spacing_mark, cp);
+ return TERM_IN_TABLE(term_spacing_mark, cp);
}
-#undef IN_TABLE
+#undef TERM_IN_TABLE
#endif
diff --git a/meson.build b/meson.build
index d23c0b4..d35e800 100644
--- a/meson.build
+++ b/meson.build
@@ -70,7 +70,7 @@ pkg.generate(
name: 'term',
description: 'Headless terminal emulator core library',
version: meson.project_version(),
- subdirs: ['.', 'term'],
+ subdirs: ['.'],
)
if get_option('tests')
diff --git a/src/core.c b/src/core.c
index b352be1..dd6232a 100644
--- a/src/core.c
+++ b/src/core.c
@@ -16,13 +16,13 @@ static uint16_t cluster_presentation(const uint32_t *cps, int len)
{
if (len <= 1)
return 0;
- bool pictographic = unicode_extended_pictographic(cps[0]);
+ bool pictographic = term_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 || grapheme_regional_indicator(c1) ||
- (pictographic && (c1 == 0x200D || grapheme_emoji_modifier(c1) ||
+ if (c1 == 0x20E3 || term_grapheme_regional_indicator(c1) ||
+ (pictographic && (c1 == 0x200D || term_grapheme_emoji_modifier(c1) ||
(c1 >= 0xE0020 && c1 <= 0xE007F))))
return CELL_EMOJI;
return 0;
@@ -33,8 +33,8 @@ 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 || grapheme_regional_indicator(cps[i]) ||
- (pictographic && (cps[i] == 0x200D || grapheme_emoji_modifier(cps[i]) ||
+ if (cps[i] == 0x20E3 || term_grapheme_regional_indicator(cps[i]) ||
+ (pictographic && (cps[i] == 0x200D || term_grapheme_emoji_modifier(cps[i]) ||
(cps[i] >= 0xE0020 && cps[i] <= 0xE007F))))
emoji = true;
}
@@ -44,9 +44,9 @@ static uint16_t cluster_presentation(const uint32_t *cps, int len)
void term_sc_print_glyph(struct term *t, uint32_t cp, int width, uint16_t flags)
{
uint32_t base = cp;
- if (TERM_EXPECT(grapheme_is_handle(cp), 0)) {
- uint32_t cps[GRAPHEME_MAX_LEN];
- int len = term_gstore_expand(t->gstore, cp, cps, GRAPHEME_MAX_LEN);
+ 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);
base = cps[0];
flags = (flags & ~(CELL_EMOJI | CELL_TEXT)) | cluster_presentation(cps, len);
}
@@ -179,13 +179,13 @@ bool term_sc_extend_cluster(struct term *t, uint32_t cp, int klass)
return false;
struct cell *prev = last_written_cell(t);
- uint32_t cps[GRAPHEME_MAX_LEN];
- int len = prev && prev->c > ' ' ? term_gstore_expand(t->gstore, prev->c, cps, GRAPHEME_MAX_LEN) : 0;
+ 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;
if (!len)
return joins_cluster(cp, klass);
if (!cluster_joins(cps, len, cp, klass))
return false;
- if (len >= GRAPHEME_MAX_LEN)
+ if (len >= TERM_GRAPHEME_MAX_LEN)
return true;
cps[len++] = cp;
@@ -517,7 +517,7 @@ static inline bool next_byte_wraps(const char *buf, size_t len, size_t pos, uint
{
if (pos >= len) return false;
uint32_t cp;
- if (!utf8_decode_one(buf + pos, len - pos, &cp)) return false;
+ if (!term_utf8_decode_one(buf + pos, len - pos, &cp)) return false;
int w = term_text_class(cp);
return w > 0 && !can_extend_cluster(last, cp, w);
}
diff --git a/src/gstore.c b/src/gstore.c
index d2bc57f..813ea7d 100644
--- a/src/gstore.c
+++ b/src/gstore.c
@@ -72,11 +72,11 @@ int term_gstore_expand(const struct gstore *g, uint32_t handle, uint32_t *cps, i
{
if (cap <= 0)
return 0;
- if (!g || !grapheme_is_handle(handle)) {
+ if (!g || !term_grapheme_is_handle(handle)) {
cps[0] = handle;
return 1;
}
- uint32_t idx = handle - GRAPHEME_HANDLE_BASE;
+ uint32_t idx = handle - TERM_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[GRAPHEME_MAX_LEN];
- int n = term_gstore_expand(g, GRAPHEME_HANDLE_BASE + i, cps_buf, GRAPHEME_MAX_LEN);
+ 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);
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,7 +147,7 @@ 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 GRAPHEME_HANDLE_BASE + e_idx;
+ return TERM_GRAPHEME_HANDLE_BASE + e_idx;
}
idx = (idx + 1) & mask;
}
@@ -193,9 +193,9 @@ void term_gstore_unpin(struct gstore *g)
void term_gstore_mark(struct gstore *g, uint32_t handle)
{
- if (!g || !grapheme_is_handle(handle))
+ if (!g || !term_grapheme_is_handle(handle))
return;
- uint32_t idx = handle - GRAPHEME_HANDLE_BASE;
+ uint32_t idx = handle - TERM_GRAPHEME_HANDLE_BASE;
if (idx < g->entries_count && g->entries[idx].allocated)
g->entries[idx].mark = true;
}
@@ -204,7 +204,7 @@ 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 (grapheme_is_handle(c))
+ if (term_grapheme_is_handle(c))
term_gstore_mark(g, c);
}
}
@@ -215,7 +215,7 @@ void term_gstore_sweep(struct gstore *g, struct term *t)
return;
if (t) {
- if (grapheme_is_handle(t->last_char))
+ if (term_grapheme_is_handle(t->last_char))
term_gstore_mark(g, t->last_char);
struct screen *s = &t->scr;
@@ -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[GRAPHEME_MAX_LEN];
- int n = term_gstore_expand(g, GRAPHEME_HANDLE_BASE + i, cps_buf, GRAPHEME_MAX_LEN);
+ 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);
uint64_t h = hash_cps(cps_buf, n);
uint32_t h32 = (uint32_t)h ? (uint32_t)h : 1;
gstore_insert_slot(g, h32, i);
@@ -300,8 +300,8 @@ uint32_t term_gstore_intern(struct gstore *g, const uint32_t *cps, int n)
return 0;
if (n == 1)
return cps[0];
- if (n > GRAPHEME_MAX_LEN)
- n = GRAPHEME_MAX_LEN;
+ if (n > TERM_GRAPHEME_MAX_LEN)
+ n = TERM_GRAPHEME_MAX_LEN;
uint64_t h = hash_cps(cps, n);
uint32_t h32 = (uint32_t)h ? (uint32_t)h : 1;
@@ -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 GRAPHEME_HANDLE_BASE + entry_idx;
+ return TERM_GRAPHEME_HANDLE_BASE + entry_idx;
}
diff --git a/src/hist.c b/src/hist.c
index 344cdc8..fff0bfe 100644
--- a/src/hist.c
+++ b/src/hist.c
@@ -42,7 +42,7 @@
#define ROWS_UNKNOWN 255
/* Bytes one cell can need, except a cluster. */
#define CELL_BYTES 5
-#define CLUSTER_BYTES (2 + GRAPHEME_MAX_LEN * 4)
+#define CLUSTER_BYTES (2 + TERM_GRAPHEME_MAX_LEN * 4)
/* ---- Parts and pages ---- */
@@ -1039,8 +1039,8 @@ static int uniform_utf8_prefix(const struct cell *cells, int len, uint8_t *dst,
static TERM_NOINLINE size_t encode_cluster(uint8_t *dst, const struct gstore *g,
uint32_t handle, uint16_t f)
{
- uint32_t cps[GRAPHEME_MAX_LEN];
- int n = term_gstore_expand(g, handle, cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN];
+ int n = term_gstore_expand(g, handle, cps, TERM_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 (grapheme_is_handle(cp)) {
+ if (term_grapheme_is_handle(cp)) {
*flags |= HLINE_HAS_CLUSTER | ((f & CELL_WIDE) ? HLINE_HAS_WIDE : 0);
return encode_cluster(dst, g, cp, f);
}
@@ -1155,7 +1155,7 @@ 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 && grapheme_is_handle(cp) &&
+ if (!simple && term_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);
@@ -2516,12 +2516,12 @@ 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[GRAPHEME_MAX_LEN];
+ uint32_t cps[TERM_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 < GRAPHEME_MAX_LEN)
+ if (n < TERM_GRAPHEME_MAX_LEN)
cps[n++] = c;
}
*cp = n == 0 ? ' ' : (g && n > 1) ? term_gstore_intern(g, cps, n) : cps[0];
diff --git a/src/input.c b/src/input.c
index 9fee179..2f0cd5c 100644
--- a/src/input.c
+++ b/src/input.c
@@ -53,7 +53,7 @@ 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)utf8_encode(cp, tmp);
+ size_t n = (size_t)term_utf8_encode(cp, tmp);
sb_bytes(sb, tmp, n);
}
@@ -695,7 +695,7 @@ struct term_input_result term_input_encode_paste(const struct term_modes *m,
continue;
}
uint32_t cp;
- int n = utf8_decode_one(text + i, len - i, &cp);
+ int n = term_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);
diff --git a/src/selection.c b/src/selection.c
index 3ac2ee3..40fb1f1 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -742,17 +742,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 GRAPHEME_MAX_LEN code points of up
+ /* One cell expands to TERM_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)GRAPHEME_MAX_LEN * 4 + 1))
+ if (!text_reserve(&text, &cap, n + (size_t)TERM_GRAPHEME_MAX_LEN * 4 + 1))
break;
if (cp > 0 && cp < 128) {
text[n++] = (char)cp;
} else {
- uint32_t cps[GRAPHEME_MAX_LEN];
- int len = term_gstore_expand(t->gstore, cp ? cp : ' ', cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN];
+ int len = term_gstore_expand(t->gstore, cp ? cp : ' ', cps, TERM_GRAPHEME_MAX_LEN);
for (int k = 0; k < len; k++)
- n += (size_t)utf8_encode(cps[k], text + n);
+ n += (size_t)term_utf8_encode(cps[k], text + n);
}
}
if (text && !is_last && !wrapped && text_reserve(&text, &cap, n + 2))
diff --git a/src/snapshot.c b/src/snapshot.c
index 8dbb498..d763425 100644
--- a/src/snapshot.c
+++ b/src/snapshot.c
@@ -90,8 +90,8 @@ static void invalidate(struct term_snapshot *s)
static uint32_t arena_add(struct term_snapshot *s, const struct gstore *g, uint32_t handle,
bool *ok)
{
- uint32_t cps[GRAPHEME_MAX_LEN];
- int n = term_gstore_expand(g, handle, cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN];
+ int n = term_gstore_expand(g, handle, cps, TERM_GRAPHEME_MAX_LEN);
if (n <= 0)
return ' ';
if (s->arena_len + (uint32_t)n + 1 > s->arena_cap) {
@@ -124,7 +124,7 @@ static uint32_t convert_row(struct term_snapshot *s, const struct gstore *g,
uint32_t text = c->c;
if (TERM_EXPECT(text < 0x20, 0))
text = text ? ' ' : 0;
- else if (TERM_EXPECT(grapheme_is_handle(text), 0)) {
+ else if (TERM_EXPECT(term_grapheme_is_handle(text), 0)) {
text = arena_add(s, g, text, ok);
if (!*ok)
return 0;
diff --git a/src/term.c b/src/term.c
index 1b16670..bd0394e 100644
--- a/src/term.c
+++ b/src/term.c
@@ -5,7 +5,7 @@ _Thread_local char term_thread_anchor;
const char *term_unicode_version(void)
{
- return UNICODE_DATA_VERSION;
+ return TERM_UNICODE_DATA_VERSION;
}
void term_lock(struct term *t)
diff --git a/src/text.c b/src/text.c
index 43c3ef5..e41a2e5 100644
--- a/src/text.c
+++ b/src/text.c
@@ -50,15 +50,15 @@ static inline void emit_decoded(struct term *t, uint32_t cp, uint16_t flags)
* sequence prints U+FFFD (Unicode 3.9, maximal subparts). */
void term_text_utf8_interrupt(struct term *t)
{
- if (TERM_EXPECT(t->utf8_state == UTF8_ACCEPT, 1))
+ if (TERM_EXPECT(t->utf8_state == TERM_UTF8_ACCEPT, 1))
return;
- t->utf8_state = UTF8_ACCEPT;
+ t->utf8_state = TERM_UTF8_ACCEPT;
emit_decoded(t, 0xFFFD, term_current_flags(t));
}
void term_text_ground(struct term *t, unsigned char ch)
{
- if (ch >= 0x20 && ch < 0x7f && t->utf8_state == UTF8_ACCEPT) {
+ if (ch >= 0x20 && ch < 0x7f && t->utf8_state == TERM_UTF8_ACCEPT) {
emit_codepoint(t, ch, 1, term_current_flags(t));
return;
}
@@ -92,14 +92,14 @@ 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 = utf8_decode(&t->utf8_state, &t->utf8_codep, ch);
- if (st == UTF8_ACCEPT) {
+ 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 == UTF8_REJECT) {
- t->utf8_state = UTF8_ACCEPT;
+ } else if (st == TERM_UTF8_REJECT) {
+ t->utf8_state = TERM_UTF8_ACCEPT;
emit_decoded(t, 0xFFFD, term_current_flags(t));
/* The byte that ended an unfinished sequence starts anew. */
- if (before != UTF8_ACCEPT)
+ if (before != TERM_UTF8_ACCEPT)
term_text_ground(t, ch);
}
}
@@ -109,7 +109,7 @@ static inline bool can_stream_bottom(const struct term *t)
{
return t->state == ST_GROUND && !t->graphics && !t->insert_mode && t->autowrap &&
!t->lr_margin_mode &&
- t->utf8_state == UTF8_ACCEPT && !t->inverse &&
+ t->utf8_state == TERM_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 &&
@@ -123,14 +123,14 @@ static inline bool try_text_run(struct term *t, const char *buf, size_t len,
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 || grapheme_is_handle(t->last_char))
+ t->last_char == 0x200D || term_grapheme_is_handle(t->last_char))
return false;
if (t->cursor_x != 0 &&
t->cursor_x != term_row(t, t->cursor_y)->len)
return false;
if ((unsigned char)buf[i] >= 0x80) {
uint32_t cp;
- int bytes = utf8_decode_one(buf + i, len - i, &cp);
+ int bytes = term_utf8_decode_one(buf + i, len - i, &cp);
if (!bytes || term_text_class(cp) <= 0)
return false;
}
@@ -181,7 +181,7 @@ static inline bool try_text_run(struct term *t, const char *buf, size_t len,
newline = true;
}
if (!newline || i + 4 > len || t->pending_wrap ||
- t->last_char == 0x200D || grapheme_is_handle(t->last_char) ||
+ t->last_char == 0x200D || term_grapheme_is_handle(t->last_char) ||
(t->cursor_x != 0 &&
t->cursor_x != term_row(t, t->cursor_y)->len))
break;
@@ -212,7 +212,7 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
unsigned char ch = (unsigned char)buf[i];
if (TERM_EXPECT(ch >= 0x20 && ch < 0x7f && !t->insert_mode && !t->lr_margin_mode &&
t->state == ST_GROUND && !t->graphics &&
- t->utf8_state == UTF8_ACCEPT, 1)) {
+ t->utf8_state == TERM_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;
@@ -239,7 +239,7 @@ 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 (utf8_decode_one(buf + i + 1, len - i - 1, &next_cp) &&
+ if (term_utf8_decode_one(buf + i + 1, len - i - 1, &next_cp) &&
term_text_class(next_cp) > 0 &&
try_text_run(t, buf, len, &i))
continue;
@@ -249,7 +249,7 @@ 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 (utf8_decode_one(buf + i + run, len - i - (size_t)run, &next_cp) &&
+ if (term_utf8_decode_one(buf + i + run, len - i - (size_t)run, &next_cp) &&
term_text_class(next_cp) > 0 &&
try_text_run(t, buf, len, &i))
continue;
@@ -274,21 +274,21 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
if (TERM_EXPECT(ch >= 0x80, 1)) {
if (TERM_EXPECT(t->state == ST_GROUND &&
- t->utf8_state == UTF8_ACCEPT && !t->graphics, 1)) {
+ t->utf8_state == TERM_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 && !grapheme_is_handle(t->last_char), 1))
+ if (TERM_EXPECT(t->last_char != 0x200D && !term_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 = utf8_decode_ground(&t->utf8_state, &t->utf8_codep, buf + i, len - i, &cp);
+ int cp_len = term_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);
@@ -328,7 +328,7 @@ static void term_feed_inner(struct term *t, const char *buf, size_t len, unsigne
}
continue;
case 0x1b:
- if (t->utf8_state == UTF8_ACCEPT && i + 1 < len &&
+ if (t->utf8_state == TERM_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);
diff --git a/src/text_run.c b/src/text_run.c
index 028b160..c48b73e 100644
--- a/src/text_run.c
+++ b/src/text_run.c
@@ -19,7 +19,7 @@ static int width_run_count;
void term_text_tables_init(void)
{
for (uint32_t cp = 0; cp < 65536; cp++) {
- int w = unicode_width(cp);
+ int w = term_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;
@@ -92,7 +92,7 @@ static TERM_MAYBE_UNUSED bool width_cache_extend(struct width_cache *wc, const u
int term_text_class(uint32_t cp)
{
assert(term_tables_ready());
- return TERM_EXPECT(cp < 65536, 1) ? (int)unicode_width_bmp[cp] : unicode_width(cp);
+ return TERM_EXPECT(cp < 65536, 1) ? (int)unicode_width_bmp[cp] : term_unicode_width(cp);
}
#if defined(TERM_KERNEL_AVX512)
@@ -189,10 +189,10 @@ static inline bool classify_3byte_block(__m512i in, struct width_ranges *ranges,
_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)UTF8_3BYTE_MIN)) ||
+ if (_mm512_cmplt_epu32_mask(*cps, _mm512_set1_epi32((int)TERM_UTF8_3BYTE_MIN)) ||
_mm512_cmple_epu32_mask(
- _mm512_sub_epi32(*cps, _mm512_set1_epi32((int)UTF8_SURROGATE_LO)),
- _mm512_set1_epi32((int)(UTF8_SURROGATE_HI - UTF8_SURROGATE_LO))))
+ _mm512_sub_epi32(*cps, _mm512_set1_epi32((int)TERM_UTF8_SURROGATE_LO)),
+ _mm512_set1_epi32((int)(TERM_UTF8_SURROGATE_HI - TERM_UTF8_SURROGATE_LO))))
return false;
__mmask16 covered = width_ranges_cover(ranges, *cps);
if (TERM_EXPECT(covered != 0xFFFF || wc->klass == 0, 0)) {
@@ -289,7 +289,7 @@ text_3byte_blocks(uint8_t * restrict dst, const char * restrict buf, int len, in
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)
{
- if (TERM_EXPECT(last == 0x200D || grapheme_is_handle(last), 0))
+ if (TERM_EXPECT(last == 0x200D || term_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
* buf: the cells path writes those characters one by one with the same
@@ -335,7 +335,7 @@ struct text_run_bytes term_text_run_bytes(uint8_t *restrict dst, const char *res
}
#endif
uint32_t cp;
- int bytes = utf8_decode_one(buf + i, (size_t)(len - i), &cp);
+ int bytes = term_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);
@@ -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)UTF8_3BYTE_MIN)),
+ _mm_cmplt_epi32(cps, _mm_set1_epi32((int)TERM_UTF8_3BYTE_MIN)),
_mm_cmpeq_epi32(_mm_and_si128(cps, _mm_set1_epi32(0xF800)),
- _mm_set1_epi32((int)UTF8_SURROGATE_LO)));
+ _mm_set1_epi32((int)TERM_UTF8_SURROGATE_LO)));
if (_mm_movemask_epi8(bad))
break;
alignas(16) uint32_t cp[4];
@@ -530,7 +530,7 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int
{
int i = 0;
int cx = 0;
- if (TERM_EXPECT(last == 0x200D || grapheme_is_handle(last), 0))
+ if (TERM_EXPECT(last == 0x200D || term_grapheme_is_handle(last), 0))
return (struct text_run_result){0, 0, last};
const struct cell_bases bases = cell_bases_make(fg, bg, flags);
@@ -593,14 +593,14 @@ text_run_body(struct cell *restrict row, const char *restrict buf, int len, int
}
#endif
uint32_t cp;
- int bytes = utf8_decode_one(buf + i, (size_t)(len - i), &cp);
+ int bytes = term_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);
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) {
uint32_t next_cp;
- if (utf8_decode_one(buf + i + 3, (size_t)(len - i - 3), &next_cp) == 3 &&
+ if (term_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;
diff --git a/src/text_run.h b/src/text_run.h
index fac638f..3ff432b 100644
--- a/src/text_run.h
+++ b/src/text_run.h
@@ -53,25 +53,25 @@ static inline bool joins_cluster(uint32_t cp, int klass)
{
if (cp < 0x0300)
return false;
- if (klass == 0 || grapheme_emoji_modifier(cp))
+ if (klass == 0 || term_grapheme_emoji_modifier(cp))
return true;
- return klass == 1 && unicode_spacing_mark(cp);
+ return klass == 1 && term_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))
+ if (last_char == 0x200D || term_grapheme_is_handle(last_char)) return true;
+ if (cp - 0x1F1E6u <= 0x19u && term_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));
+ return term_unicode_spacing_mark(cp) || term_grapheme_emoji_modifier(cp) ||
+ (cp - 0x1F1E6u <= 0x19u && term_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 unicode_extended_pictographic(cp);
+ return term_unicode_extended_pictographic(cp);
return len == 1 && cp - 0x1F1E6u <= 0x19u &&
- grapheme_regional_indicator(cp) &&
- grapheme_regional_indicator(cps[0]);
+ term_grapheme_regional_indicator(cp) &&
+ term_grapheme_regional_indicator(cps[0]);
}
#endif
diff --git a/tests/gstore_test.c b/tests/gstore_test.c
index 637b136..ea582f3 100644
--- a/tests/gstore_test.c
+++ b/tests/gstore_test.c
@@ -32,7 +32,7 @@ static void test_direct_unit(void)
/* Cluster returns a handle. */
uint32_t c1[2] = { 'e', 0x0301 };
uint32_t h1 = term_gstore_intern(g, c1, 2);
- assert(grapheme_is_handle(h1));
+ assert(term_grapheme_is_handle(h1));
assert(term_gstore_count(g) == 1);
/* Identical cluster deduplicates to the same handle. */
@@ -43,17 +43,17 @@ static void test_direct_unit(void)
/* Different cluster gets a distinct handle. */
uint32_t c2[2] = { 'a', 0x0300 };
uint32_t h2 = term_gstore_intern(g, c2, 2);
- assert(grapheme_is_handle(h2));
+ assert(term_grapheme_is_handle(h2));
assert(h2 != h1);
assert(term_gstore_count(g) == 2);
/* Expand both handles. */
- uint32_t out[GRAPHEME_MAX_LEN] = {0};
- int n = term_gstore_expand(g, h1, out, GRAPHEME_MAX_LEN);
+ uint32_t out[TERM_GRAPHEME_MAX_LEN] = {0};
+ int n = term_gstore_expand(g, h1, out, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(out[0] == 'e' && out[1] == 0x0301);
- n = term_gstore_expand(g, h2, out, GRAPHEME_MAX_LEN);
+ n = term_gstore_expand(g, h2, out, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(out[0] == 'a' && out[1] == 0x0300);
@@ -63,20 +63,20 @@ static void test_direct_unit(void)
assert(term_gstore_count(g) == 1);
/* h1 is still valid. */
- n = term_gstore_expand(g, h1, out, GRAPHEME_MAX_LEN);
+ n = term_gstore_expand(g, h1, out, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(out[0] == 'e' && out[1] == 0x0301);
/* h2 was reclaimed. */
- n = term_gstore_expand(g, h2, out, GRAPHEME_MAX_LEN);
+ n = term_gstore_expand(g, h2, out, TERM_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(grapheme_is_handle(h3));
+ assert(term_grapheme_is_handle(h3));
assert(term_gstore_count(g) == 2);
- n = term_gstore_expand(g, h3, out, GRAPHEME_MAX_LEN);
+ n = term_gstore_expand(g, h3, out, TERM_GRAPHEME_MAX_LEN);
assert(n == 3);
assert(out[0] == 'o' && out[1] == 0x0308 && out[2] == 0x0301);
@@ -105,8 +105,8 @@ static void test_two_terminals_isolation(void)
const struct term_cell *row = term_snapshot_row(snap, 0);
assert(row[0].text & TERM_TEXT_CLUSTER);
- uint32_t cps[GRAPHEME_MAX_LEN] = {0};
- int n = term_snapshot_cluster(snap, row[0].text, cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0};
+ int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(cps[0] == 'e' && cps[1] == 0x0301);
@@ -143,16 +143,16 @@ static void test_screen_clusters_survive_sweep(void)
const struct term_cell *row = term_snapshot_row(snap, 0);
assert(row[0].text & TERM_TEXT_CLUSTER);
- uint32_t cps[GRAPHEME_MAX_LEN] = {0};
- int n = term_snapshot_cluster(snap, row[0].text, cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0};
+ int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(cps[0] == 'a' && cps[1] == 0x0300);
- n = term_snapshot_cluster(snap, row[1].text, cps, GRAPHEME_MAX_LEN);
+ n = term_snapshot_cluster(snap, row[1].text, cps, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(cps[0] == 'b' && cps[1] == 0x0301);
- n = term_snapshot_cluster(snap, row[2].text, cps, GRAPHEME_MAX_LEN);
+ n = term_snapshot_cluster(snap, row[2].text, cps, TERM_GRAPHEME_MAX_LEN);
assert(n == 2);
assert(cps[0] == 'c' && cps[1] == 0x0302);
@@ -183,8 +183,8 @@ static void test_more_than_65536_clusters(void)
size_t len = 0;
buf[len++] = base;
- len += (size_t)utf8_encode(cp1, buf + len);
- len += (size_t)utf8_encode(cp2, buf + len);
+ len += (size_t)term_utf8_encode(cp1, buf + len);
+ len += (size_t)term_utf8_encode(cp2, buf + len);
buf[len++] = '\r';
buf[len++] = '\n';
@@ -204,8 +204,8 @@ static void test_more_than_65536_clusters(void)
const struct term_cell *row = term_snapshot_row(snap, y);
assert(row[0].text & TERM_TEXT_CLUSTER);
- uint32_t cps[GRAPHEME_MAX_LEN] = {0};
- int n = term_snapshot_cluster(snap, row[0].text, cps, GRAPHEME_MAX_LEN);
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0};
+ int n = term_snapshot_cluster(snap, row[0].text, cps, TERM_GRAPHEME_MAX_LEN);
assert(n == 3);
/* Live cluster count must be small (only bounded screen and history). */
diff --git a/tests/header_test.sh b/tests/header_test.sh
index 4ba091b..9fd1041 100644
--- a/tests/header_test.sh
+++ b/tests/header_test.sh
@@ -1,25 +1,70 @@
#!/usr/bin/env bash
-# A host includes term.h and nothing else. The header compiles alone as
-# strict C11 and as C++, with only include/term on the include path.
+# 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
+# C11 and as C++.
set -euo pipefail
cd "${1:-$(dirname "$0")/..}"
cc=${CC:-cc}
cxx=${CXX:-c++}
status=0
-echo '#include "term.h"' | "$cc" -std=c11 -Wall -Wextra -Wpedantic -Werror \
- -Iinclude/term -x c -fsyntax-only - || { echo "term.h: not valid C11" >&2; status=1; }
-if command -v "$cxx" >/dev/null; then
- echo '#include "term.h"' | "$cxx" -std=c++17 -Wall -Wextra -Wpedantic -Werror \
- -Iinclude/term -x c++ -fsyntax-only - || { echo "term.h: not valid C++" >&2; status=1; }
-fi
+
+# check LABEL: compile the code on stdin as C11 and as C++, with include/
+# on the path.
+check() {
+ local label=$1 src
+ src=$(cat)
+ printf '%s\n' "$src" | "$cc" -std=c11 -Wall -Wextra -Wpedantic -Werror \
+ -Iinclude -x c -fsyntax-only - || { echo "$label: not valid C11" >&2; status=1; }
+ if command -v "$cxx" >/dev/null; then
+ printf '%s\n' "$src" | "$cxx" -std=c++17 -Wall -Wextra -Wpedantic -Werror \
+ -Iinclude -x c++ -fsyntax-only - || { echo "$label: not valid C++" >&2; status=1; }
+ fi
+}
+
+check term.h <<'EOF'
+#include <term/term.h>
+EOF
# Apple headers define wide before a host includes the Unicode API.
-unicode_header=$'typedef struct wide { int value; } wide;\n#include "unicode/width.h"'
-echo "$unicode_header" | "$cc" -std=c11 -Wall -Wextra -Wpedantic -Werror \
- -Iinclude/term -x c -fsyntax-only - || { echo "unicode/width.h: conflicts with host types" >&2; status=1; }
-if command -v "$cxx" >/dev/null; then
- echo "$unicode_header" | "$cxx" -std=c++17 -Wall -Wextra -Wpedantic -Werror \
- -Iinclude/term -x c++ -fsyntax-only - || { echo "unicode/width.h: conflicts with C++ host types" >&2; status=1; }
-fi
+check "unicode/width.h: conflicts with host types" <<'EOF'
+typedef struct wide { int value; } wide;
+#include <term/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.
+check "unicode API: host names declared first" <<'EOF'
+int unicode_width(int);
+static int in_ranges;
+static int zero_width;
+static int utf8d;
+struct unicode_range { int lo; };
+#define UTF8_ACCEPT 7
+#define GRAPHEME_MAX_LEN 3
+#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>
+int host_use(void)
+{
+ return in_ranges + zero_width + utf8d + unicode_width(1) + UTF8_ACCEPT + GRAPHEME_MAX_LEN;
+}
+EOF
+
+check "unicode API: host names declared after" <<'EOF'
+#include <term/unicode/utf8.h>
+#include <term/unicode/width.h>
+#include <term/unicode/grapheme.h>
+int unicode_width(int);
+static int in_ranges;
+#define UTF8_ACCEPT 7
+#define GRAPHEME_MAX_LEN 3
+int host_use(void)
+{
+ return in_ranges + unicode_width(1) + UTF8_ACCEPT + GRAPHEME_MAX_LEN;
+}
+EOF
exit $status
diff --git a/tests/hist_test.c b/tests/hist_test.c
index d772c5a..691ae3c 100644
--- a/tests/hist_test.c
+++ b/tests/hist_test.c
@@ -129,9 +129,9 @@ static void test_clusters_roundtrip(void)
struct cell out[2];
assert(term_hist_decode_segment(&h, 0, 0, 2, out, g) == 2);
- assert(grapheme_is_handle(out[0].c));
- uint32_t got[GRAPHEME_MAX_LEN];
- assert(term_gstore_expand(g, out[0].c, got, GRAPHEME_MAX_LEN) == 3);
+ 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(got[0] == cps[0] && got[1] == cps[1] && got[2] == cps[2]);
assert(out[1].c == 'X');
@@ -623,9 +623,9 @@ static void test_fuzz_rows(void)
continue;
}
assert(a->fg == b->fg && a->flags == b->flags);
- if (grapheme_is_handle(a->c)) {
- uint32_t got[GRAPHEME_MAX_LEN];
- assert(term_gstore_expand(g, b->c, got, GRAPHEME_MAX_LEN) == 2 && got[1] == 0x0301);
+ 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);
} else {
assert(a->c == b->c);
}
diff --git a/tests/model.c b/tests/model.c
index 8dead6c..7934d4f 100644
--- a/tests/model.c
+++ b/tests/model.c
@@ -31,7 +31,7 @@
#define STR_KEEP 1024
struct cell {
- uint32_t cp[GRAPHEME_MAX_LEN];
+ uint32_t cp[TERM_GRAPHEME_MAX_LEN];
uint8_t n, width;
uint16_t attrs;
term_color fg, bg;
@@ -98,7 +98,7 @@ struct model {
bool tabs[MAX_TABS];
struct keyboard keyboard[2];
/* The last printed glyph, for REP and cluster joins. */
- uint32_t last[GRAPHEME_MAX_LEN];
+ uint32_t last[TERM_GRAPHEME_MAX_LEN];
int last_n;
int prompt; /* screen row of the last OSC 133;A, or -1 */
unsigned flags;
@@ -158,7 +158,7 @@ static bool pristine(const struct model *m)
static bool is_ri(uint32_t cp)
{
- return cp - 0x1F1E6u <= 0x19u && grapheme_regional_indicator(cp);
+ return cp - 0x1F1E6u <= 0x19u && term_grapheme_regional_indicator(cp);
}
/* ---- replies ---- */
@@ -417,13 +417,13 @@ static void fill_gap(struct row *r, int x)
static uint16_t presentation(const uint32_t *cps, int n)
{
- bool pictographic = unicode_extended_pictographic(cps[0]);
+ bool pictographic = term_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 || grapheme_regional_indicator(cps[i]) ||
- (pictographic && (cps[i] == 0x200D || grapheme_emoji_modifier(cps[i]) ||
+ if (cps[i] == 0x20E3 || term_grapheme_regional_indicator(cps[i]) ||
+ (pictographic && (cps[i] == 0x200D || term_grapheme_emoji_modifier(cps[i]) ||
(cps[i] >= 0xE0020 && cps[i] <= 0xE007F))))
emoji = true;
}
@@ -443,7 +443,7 @@ static void put_glyph(struct model *m, const uint32_t *cps, int n, uint16_t attr
{
if (n > 1)
attrs = (uint16_t)((attrs & ~(TERM_ATTR_EMOJI | TERM_ATTR_TEXT)) | presentation(cps, n));
- int width = unicode_width(cps[0]) == 2 ? 2 : 1;
+ int width = term_unicode_width(cps[0]) == 2 ? 2 : 1;
if (attrs & TERM_ATTR_EMOJI) width = 2;
if (attrs & TERM_ATTR_TEXT) width = 1;
if (m->pending) wrap_to_next_row(m);
@@ -495,14 +495,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 || grapheme_emoji_modifier(cp) ||
- (width == 1 && unicode_spacing_mark(cp));
+ return width == 0 || term_grapheme_emoji_modifier(cp) ||
+ (width == 1 && term_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 unicode_extended_pictographic(cp);
+ if (cps[n - 1] == 0x200D) return term_unicode_extended_pictographic(cp);
return n == 1 && is_ri(cp) && is_ri(cps[0]);
}
@@ -527,10 +527,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 >= GRAPHEME_MAX_LEN)
+ if (prev->n >= TERM_GRAPHEME_MAX_LEN)
return true;
struct cell old = *prev;
- uint32_t cps[GRAPHEME_MAX_LEN];
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN];
memcpy(cps, old.cp, (size_t)old.n * sizeof(*cps));
cps[old.n] = cp;
int n = old.n + 1;
@@ -590,7 +590,7 @@ static void print_cp(struct model *m, uint32_t cp)
emit(m, cp);
return;
}
- int width = unicode_width(cp);
+ int width = term_unicode_width(cp);
if (!extend_cluster(m, cp, width))
emit(m, cp);
}
diff --git a/tests/model.h b/tests/model.h
index 9a4316f..a6b5572 100644
--- a/tests/model.h
+++ b/tests/model.h
@@ -19,7 +19,7 @@
#include <stdint.h>
struct model_cell {
- uint32_t cp[GRAPHEME_MAX_LEN];
+ uint32_t cp[TERM_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_* */
diff --git a/tests/model_test.c b/tests/model_test.c
index 395097e..6af30b5 100644
--- a/tests/model_test.c
+++ b/tests/model_test.c
@@ -122,8 +122,8 @@ static void dump_all(struct model *m, struct term *t, struct term_snapshot *snap
term_snapshot_update(snap, t);
const struct term_cell *row = term_snapshot_row(snap, r < total ? 0 : r - total);
for (int x = 0; x < size.x; x++) {
- uint32_t cp[GRAPHEME_MAX_LEN] = {0};
- if (row[x].text) term_snapshot_cluster(snap, row[x].text, cp, GRAPHEME_MAX_LEN);
+ uint32_t cp[TERM_GRAPHEME_MAX_LEN] = {0};
+ if (row[x].text) term_snapshot_cluster(snap, row[x].text, cp, TERM_GRAPHEME_MAX_LEN);
fputc(glyph(cp[0]), log);
}
} else {
@@ -201,9 +201,9 @@ static const char *compare(struct model *m, struct term *t, struct term_snapshot
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[GRAPHEME_MAX_LEN] = {0};
+ uint32_t cps[TERM_GRAPHEME_MAX_LEN] = {0};
int n = row[x].text ? term_snapshot_cluster(snap, row[x].text, cps,
- GRAPHEME_MAX_LEN) : 0;
+ TERM_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[GRAPHEME_MAX_LEN] = {0};
+ uint32_t cp[TERM_GRAPHEME_MAX_LEN] = {0};
if (row[k].text)
- term_snapshot_cluster(snap, row[k].text, cp, GRAPHEME_MAX_LEN);
+ term_snapshot_cluster(snap, row[k].text, cp, TERM_GRAPHEME_MAX_LEN);
fputc(glyph(cp[0]), log);
}
fprintf(log, "\n model: ");
diff --git a/tests/term_test.c b/tests/term_test.c
index 66dbd96..9dbe902 100644
--- a/tests/term_test.c
+++ b/tests/term_test.c
@@ -1861,15 +1861,15 @@ int main(void)
test_snapshot_follows_new_terminal();
test_bulk_rows_survive_edits();
- assert(!strcmp(UNICODE_DATA_VERSION, "18.0.0"));
- assert(!strcmp(term_unicode_version(), UNICODE_DATA_VERSION));
- assert(unicode_width('A') == 1);
- assert(unicode_width(0x0301) == 0);
- assert(unicode_width(0x754C) == 2);
- assert(unicode_width(0x1FAE0) == 2);
- assert(unicode_emoji_presentation(0x1FAE0));
- assert(unicode_width(0x1FAEB) == 2);
- assert(unicode_emoji_presentation(0x1FAEB));
+ 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));
{
/* A Jamo Extended-B vowel draws inside its leading consonant. */
struct term *t = term_new(&(struct term_options){ .size = { .x = 10, .y = 2 } });
diff --git a/tests/unicode/unicode_test.c b/tests/unicode/unicode_test.c
index 7fc6e3e..e3cf5a7 100644
--- a/tests/unicode/unicode_test.c
+++ b/tests/unicode/unicode_test.c
@@ -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 = utf8_decode_one(valid[i].bytes, n, &cp);
+ int r = term_utf8_decode_one(valid[i].bytes, n, &cp);
assert(r == 0);
assert(cp == 0xdeadbeef);
}
- int r = utf8_decode_one(valid[i].bytes, valid[i].len, &cp);
+ int r = term_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 = utf8_decode_one(followed, valid[i].len + 4, &cp);
+ r = term_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 = utf8_decode_one(invalid[i], strlen(invalid[i]), &cp);
+ int r = term_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[UTF8_MAX_BYTES];
- int len = utf8_encode(cp, bytes);
- uint32_t scalar = 0, streamed = 0, state = UTF8_ACCEPT;
- int r = utf8_decode_one(bytes, (size_t)len, &scalar);
+ 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);
assert(r == len);
assert(scalar == cp);
for (int i = 0; i < len; i++) {
- utf8_decode(&state, &streamed, (unsigned char)bytes[i]);
- if (i + 1 < len) assert(state != UTF8_ACCEPT && state != UTF8_REJECT);
+ term_utf8_decode(&state, &streamed, (unsigned char)bytes[i]);
+ if (i + 1 < len) assert(state != TERM_UTF8_ACCEPT && state != TERM_UTF8_REJECT);
}
- assert(state == UTF8_ACCEPT && streamed == cp);
+ assert(state == TERM_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[UTF8_MAX_BYTES];
- int len = utf8_encode(invalid[i], bytes);
+ char bytes[TERM_UTF8_MAX_BYTES];
+ int len = term_utf8_encode(invalid[i], bytes);
uint32_t cp = 0;
- int r = utf8_decode_one(bytes, len, &cp);
+ int r = term_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];
- utf8_sanitize(dst, sizeof(dst), "hello \xe2\x82\xac\xf0\x9f\x98\x80");
+ term_utf8_sanitize(dst, sizeof(dst), "hello \xe2\x82\xac\xf0\x9f\x98\x80");
assert(!strcmp(dst, "hello \xe2\x82\xac\xf0\x9f\x98\x80"));
- utf8_sanitize(dst, sizeof(dst), "a\xff\x80" "b\xed\xa0\x80" "c\xe2\x82");
+ term_utf8_sanitize(dst, sizeof(dst), "a\xff\x80" "b\xed\xa0\x80" "c\xe2\x82");
assert(!strcmp(dst, "abc"));
- utf8_sanitize(dst, sizeof(dst), "");
+ term_utf8_sanitize(dst, sizeof(dst), "");
assert(!strcmp(dst, ""));
- utf8_sanitize(dst, sizeof(dst), "\xff\xfe");
+ term_utf8_sanitize(dst, sizeof(dst), "\xff\xfe");
assert(!strcmp(dst, ""));
- utf8_sanitize(dst, 6, "ab\xe2\x82\xac" "cd");
+ term_utf8_sanitize(dst, 6, "ab\xe2\x82\xac" "cd");
assert(!strcmp(dst, "ab\xe2\x82\xac"));
- utf8_sanitize(dst, 5, "ab\xe2\x82\xac" "cd");
+ term_utf8_sanitize(dst, 5, "ab\xe2\x82\xac" "cd");
assert(!strcmp(dst, "abcd"));
memset(dst, 'x', sizeof(dst));
- utf8_sanitize(dst, 4, "abcdef");
+ term_utf8_sanitize(dst, 4, "abcdef");
assert(!strcmp(dst, "abc"));
memset(dst, 'x', sizeof(dst));
- utf8_sanitize(dst, 0, "abc");
+ term_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 = UTF8_ACCEPT, codep = 0, cp = 0xdead;
- int n = utf8_decode_ground(&state, &codep, "\xe2\x80\x1b\xac", 4, &cp);
+ uint32_t state = TERM_UTF8_ACCEPT, codep = 0, cp = 0xdead;
+ int n = term_utf8_decode_ground(&state, &codep, "\xe2\x80\x1b\xac", 4, &cp);
assert(n == 2);
assert(cp == 0xFFFD);
- assert(state == UTF8_ACCEPT);
- n = utf8_decode_ground(&state, &codep, "\xac", 1, &cp);
+ assert(state == TERM_UTF8_ACCEPT);
+ n = term_utf8_decode_ground(&state, &codep, "\xac", 1, &cp);
assert(n == 1);
assert(cp == 0xFFFD);
- assert(state == UTF8_ACCEPT);
- n = utf8_decode_ground(&state, &codep, "\xe2\x82z", 3, &cp);
+ assert(state == TERM_UTF8_ACCEPT);
+ n = term_utf8_decode_ground(&state, &codep, "\xe2\x82z", 3, &cp);
assert(n == 2);
assert(cp == 0xFFFD);
- assert(state == UTF8_ACCEPT);
- n = utf8_decode_ground(&state, &codep, "\xe2\x82", 2, &cp);
+ assert(state == TERM_UTF8_ACCEPT);
+ n = term_utf8_decode_ground(&state, &codep, "\xe2\x82", 2, &cp);
assert(n == 2);
assert(cp == 0);
- assert(state != UTF8_ACCEPT);
+ assert(state != TERM_UTF8_ACCEPT);
- state = UTF8_ACCEPT;
+ state = TERM_UTF8_ACCEPT;
codep = 0;
- n = utf8_decode_ground(&state, &codep, "\xe2\x82\xac", 3, &cp);
+ n = term_utf8_decode_ground(&state, &codep, "\xe2\x82\xac", 3, &cp);
assert(n == 3);
assert(cp == 0x20ac);
- assert(state == UTF8_ACCEPT);
+ assert(state == TERM_UTF8_ACCEPT);
}
int main(void)
diff --git a/tools/generate_unicode.py b/tools/generate_unicode.py
index 85c646d..22f12a6 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 unicode_range {name}[] = {{")
+ out.append(f"static const struct term_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 UNICODE_DATA_VERSION "{version}"', ""]
- emit_table(out, "zero_width", zero)
- emit_table(out, "nonprintable", nonprint)
- emit_table(out, "unicode_wide", wide)
- emit_table(out, "spacing_mark", spacing)
- emit_table(out, "extended_pictographic", pictographic)
- emit_table(out, "emoji_presentation", emoji_presentation)
+ 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)
args.output.write_text("\n".join(out))
if __name__ == "__main__":