Skip to content

Commit 3c9a21c

Browse files
pm100Copilot
andauthored
fix: use correct cursor scroll position for wide (CJK) characters (#10)
Use unicode display width instead of char count when computing the horizontal scroll offset so the cursor stays in view when lines contain wide characters such as CJK ideographs. Ported from rhysd/tui-textarea#94. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a91e715 commit 3c9a21c

1 file changed

Lines changed: 8 additions & 1 deletion

File tree

src/widget.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use ratatui_core::widgets::Widget;
77
use ratatui_widgets::paragraph::Paragraph;
88
use std::cmp;
99
use std::sync::atomic::{AtomicU64, Ordering};
10+
use unicode_width::UnicodeWidthChar;
1011

1112
// &mut 'a (u16, u16, u16, u16) is not available since `render` method takes immutable reference of TextArea
1213
// instance. In the case, the TextArea instance cannot be accessed from any other objects since it is mutablly
@@ -111,7 +112,13 @@ impl<'a> TextArea<'a> {
111112
}
112113

113114
fn scroll_top_col(&self, prev_top: u16, width: u16) -> u16 {
114-
let mut cursor = self.cursor().1 as u16;
115+
let (row, col) = self.cursor();
116+
// Adjust the cursor position to account for the display width of non-ASCII characters.
117+
let mut cursor = self.lines()[row]
118+
.chars()
119+
.take(col)
120+
.map(|c| c.width().unwrap_or(0))
121+
.sum::<usize>() as u16;
115122
// Adjust the cursor position due to the width of line number.
116123
if self.line_number_style().is_some() {
117124
let lnum = num_digits(self.lines().len()) as u16 + 2; // `+ 2` for margins

0 commit comments

Comments
 (0)