From f5d6386ea580569cce8ea2bbfadd25de70291bfd Mon Sep 17 00:00:00 2001 From: Adam Saponara Date: Mon, 6 Nov 2023 22:21:02 -0500 Subject: [PATCH] fix egc bug, clarify docs, add test --- termbox2.h | 10 +++++----- tests/test_egc/expected.ansi | 24 ++++++++++++++++++++++++ tests/test_egc/test.php | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 tests/test_egc/expected.ansi create mode 100755 tests/test_egc/test.php diff --git a/termbox2.h b/termbox2.h index 8f8cb4b..a716dbd 100644 --- a/termbox2.h +++ b/termbox2.h @@ -411,13 +411,13 @@ typedef uint16_t uintattr_t; * See tb_present() for implementation. */ struct tb_cell { - uint32_t ch; /* a Unicode character */ + uint32_t ch; /* a Unicode code point */ uintattr_t fg; /* bitwise foreground attributes */ uintattr_t bg; /* bitwise background attributes */ #ifdef TB_OPT_EGC - uint32_t *ech; /* a grapheme cluster of Unicode code points */ - size_t nech; /* length in bytes of ech, 0 means use ch instead of ech */ - size_t cech; /* capacity in bytes of ech */ + uint32_t *ech; /* a grapheme cluster of Unicode code points, 0-terminated */ + size_t nech; /* num elements in ech, 0 means use ch instead of ech */ + size_t cech; /* num elements allocated for ech */ #endif }; @@ -3232,7 +3232,7 @@ static int cell_set(struct tb_cell *cell, uint32_t *ch, size_t nch, } else { int rv; if_err_return(rv, cell_reserve_ech(cell, nch + 1)); - memcpy(cell->ech, ch, nch); + memcpy(cell->ech, ch, sizeof(ch) * nch); cell->ech[nch] = '\0'; cell->nech = nch; } diff --git a/tests/test_egc/expected.ansi b/tests/test_egc/expected.ansi new file mode 100644 index 0000000..69cda5c --- /dev/null +++ b/tests/test_egc/expected.ansi @@ -0,0 +1,24 @@ +#5aёb +#5cёd + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_egc/test.php b/tests/test_egc/test.php new file mode 100755 index 0000000..f6a59ff --- /dev/null +++ b/tests/test_egc/test.php @@ -0,0 +1,29 @@ +ffi->tb_has_egc()) { + // This will only work with extended grapheme cluster support + $test->skip(); +} + +$test->ffi->tb_init(); + +$ech = $test->ffi->new('uint32_t[2]'); +$test->ffi->tb_utf8_char_to_unicode(FFI::addr($ech[0]), "\xd0\xb5"); // cyrillic small letter ie +$test->ffi->tb_utf8_char_to_unicode(FFI::addr($ech[1]), "\xcc\x88"); // combining diaeresis + +// Set EGC using tb_set_cell_ex +$y = 0; +$test->ffi->tb_set_cell(0, $y, ord('a'), 0, 0); +$test->ffi->tb_set_cell_ex(1, $y, $test->ffi->cast('uint32_t *', FFI::addr($ech)), 2, 0, 0); +$test->ffi->tb_set_cell(2, $y, ord('b'), 0, 0); + +++$y; +// Same effect with tb_extend_cell +$test->ffi->tb_set_cell(0, $y, ord('c'), 0, 0); +$test->ffi->tb_set_cell(1, $y, $ech[0], 0, 0); +$test->ffi->tb_extend_cell(1, $y, $ech[1]); +$test->ffi->tb_set_cell(2, $y, ord('d'), 0, 0); + +$test->ffi->tb_present(); +$test->screencap(); -- 2.39.5