-
Notifications
You must be signed in to change notification settings - Fork 63
Some unicode characters cause glitches #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I wonder if this could be a |
Thanks for the reproducer @cleac . I should prioritize this. |
This patch fixes the issue: diff --git a/termbox/cbits/termbox.c b/termbox/cbits/termbox.c
index 37f00d0..705978c 100644
--- a/termbox/cbits/termbox.c
+++ b/termbox/cbits/termbox.c
@@ -160,10 +160,6 @@ void tb_present(void)
front = &CELL(&front_buffer, x, y);
w = wcwidth(back->ch);
if (w < 1) w = 1;
- if (memcmp(back, front, sizeof(struct tb_cell)) == 0) {
- x += w;
- continue;
- }
memcpy(front, back, sizeof(struct tb_cell));
send_attr(back->fg, back->bg);
if (w > 1 && x >= front_buffer.width - (w - 1)) { (https://github.com/nsf/termbox/blob/master/src/termbox.c#L190-L193) It's still not 100% clear to me that the bug is in that code though, perhaps the bug is something else and removing this code hides it. |
I believe there's a bug in passing Rust characters to termbox: termbox is expecting (although this is not mentioned anywhere in the code) system-specific wide chars (wchar_t) but I'm passing utf-8 encoded chars instead. |
Here's how we'll fix this: when I paste |
Here's a example showing none of Rust's default encoding of chars as u32 or our utf-8 encoding is what extern "C" {
fn wcwidth(c: libc::wchar_t) -> libc::c_int;
}
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;
fn char_to_utf8(c: char) -> u32 {
let code = c as u32;
if code < MAX_ONE_B {
code as u32
} else if code < MAX_TWO_B {
((u32::from((code >> 6 & 0x1F) as u8 | TAG_TWO_B)) << 8)
+ u32::from((code & 0x3F) as u8 | TAG_CONT)
} else if code < MAX_THREE_B {
(u32::from((code >> 12 & 0x0F) as u8 | TAG_THREE_B) << 16)
+ (u32::from((code >> 6 & 0x3F) as u8 | TAG_CONT) << 8)
+ (u32::from((code & 0x3F) as u8 | TAG_CONT))
} else {
((u32::from((code >> 18 & 0x07) as u8 | TAG_FOUR_B)) << 24)
+ ((u32::from((code >> 12 & 0x3F) as u8 | TAG_CONT)) << 16)
+ ((u32::from((code >> 6 & 0x3F) as u8 | TAG_CONT)) << 8)
+ (u32::from((code & 0x3F) as u8 | TAG_CONT))
}
}
fn main() {
let c = 'h';
println!("{}", unsafe { wcwidth(c as libc::wchar_t) });
println!("{}", unsafe { wcwidth(char_to_utf8(c) as libc::wchar_t) });
} Both lines print |
I found this crate which implements the functionality we need for this: https://unicode-rs.github.io/unicode-width/unicode_width/ With this crate I also added a comment about this in termbox upstream: nsf/termbox#126 (comment) but given how active the development is I don't expect to get any answers any time soon. I think using |
Another idea is to get rid of termbox and use termion instead. termion is lacking termbox's "cell" abstraction but that's easy to implement. Only downside is we'll have to implement multi-column char support (as that's part of the "cell" abstraction termbox provides). Input handling should still be done by another library (term_input for the time being) as termion's input support is nowhere near enough for tiny. |
This should be fixed for real now. The previous patched fixed another bug where we treated wide characters as single-column, so no need to revert that. |
I'll post a screenshot next time this happens, but basically some unicode characters cause glithces that even a
tb_clear()
doesn't fix.What happens that the unicode character stays visible in its original location when you scroll (either with
shift+arrow
or as new messages appear), and even changing tabs don't make the character go away.Only way to fix the glitch that I could find is to force a resize.
Probably termbox related.
The text was updated successfully, but these errors were encountered: