Skip to content

Commit

Permalink
fix bug with adding combining chars to a full-width char
Browse files Browse the repository at this point in the history
the logic was incorrectly sending the combinin char to x-1, but that
assumed a wcwidth==1 char. save last printed x coord and use that
instead.

xterm's ansi output for this is a little strange. unlike other
`expected.ansi` files, cat-ing this one to stdout doesn't seem to
render the correct output, and if you peek at its contents you'll see
some "\xef\xbf\xbf" (U+FFFF) which is an invalid codepoint. in any
case, it still picks up the regression so i'm adding it.
  • Loading branch information
adsr committed Dec 18, 2024
1 parent 02e28d0 commit 7487f1b
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 12 deletions.
14 changes: 8 additions & 6 deletions termbox2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1869,7 +1869,7 @@ int tb_print(int x, int y, uintattr_t fg, uintattr_t bg, const char *str) {

int tb_print_ex(int x, int y, uintattr_t fg, uintattr_t bg, size_t *out_w,
const char *str) {
int rv, w, ix;
int rv, w, ix, x_prev;
uint32_t uni;

if_not_init_return();
Expand All @@ -1879,6 +1879,7 @@ int tb_print_ex(int x, int y, uintattr_t fg, uintattr_t bg, size_t *out_w,
}

ix = x;
x_prev = x;
if (out_w) *out_w = 0;

while (*str) {
Expand All @@ -1895,6 +1896,7 @@ int tb_print_ex(int x, int y, uintattr_t fg, uintattr_t bg, size_t *out_w,

if (uni == '\n') { // TODO: \r, \t, \v, \f, etc?
x = ix;
x_prev = x;
y += 1;
continue;
} else if (!iswprint((wint_t)uni)) {
Expand All @@ -1905,17 +1907,17 @@ int tb_print_ex(int x, int y, uintattr_t fg, uintattr_t bg, size_t *out_w,
if (w < 0) {
return TB_ERR; // shouldn't happen if iswprint
} else if (w == 0) { // combining character
if (cellbuf_in_bounds(&global.back, x - 1, y)) {
if_err_return(rv, tb_extend_cell(x - 1, y, uni));
if (cellbuf_in_bounds(&global.back, x_prev, y)) {
if_err_return(rv, tb_extend_cell(x_prev, y, uni));
}
} else {
if (cellbuf_in_bounds(&global.back, x, y)) {
if_err_return(rv, tb_set_cell(x, y, uni, fg, bg));
}
x_prev = x;
x += w;
if (out_w) *out_w += w;
}

x += w;
if (out_w) *out_w += w;
}

return TB_OK;
Expand Down
4 changes: 2 additions & 2 deletions tests/test_egc/expected.ansi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#5aёb
#5cёd


#5I￿̤ͯ
#5I￿̤ͯ



Expand Down
12 changes: 11 additions & 1 deletion tests/test_egc/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@
$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
++$y;
$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);

// Another example with 2 combining characters
++$y;
$test->ffi->tb_set_cell(0, $y, 0xff29, 0, 0); // fullwidth latin capital letter i
$test->ffi->tb_extend_cell(0, $y, 0x0324); // combining diaeresis below
$test->ffi->tb_extend_cell(0, $y, 0x036f); // combining latin small letter x

// Same as above via tb_print (should be equivalent)
++$y;
$test->ffi->tb_print(0, $y, 0, 0, "\xef\xbc\xa9\xcc\xa4\xcd\xaf");

$test->ffi->tb_present();
$test->screencap();
4 changes: 1 addition & 3 deletions tests/test_prepend.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ public function __construct($ffi, $test) {
$this->test = $test;
}
public function __call(string $name, array $args) {
if ($name !== 'tb_set_cell') {
$this->test->log("ffi $name " . json_encode($args));
}
$this->test->log("ffi $name " . json_encode($args));
return $this->ffi->$name(...$args);
}
};
Expand Down

0 comments on commit 7487f1b

Please sign in to comment.