From 1fa298cbdd5a7ab4cc29938960fd3c2a470f2022 Mon Sep 17 00:00:00 2001 From: ProofOfConcept Date: Thu, 19 Mar 2026 00:46:17 -0400 Subject: [PATCH] tui: fix cursor position to use character count, not byte count self.cursor is a byte index into the string. When scanning the buffer, we need to compare character positions, not byte positions or widths. Convert self.cursor to a character count before comparing with the buffer scan. Count each non-empty cell as 1 character (the buffer already represents visual cells, so width doesn't matter here). --- poc-agent/src/tui.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/poc-agent/src/tui.rs b/poc-agent/src/tui.rs index 6f6c90b..0507068 100644 --- a/poc-agent/src/tui.rs +++ b/poc-agent/src/tui.rs @@ -821,7 +821,11 @@ impl App { // Cursor position: scan the rendered buffer to find where the cursor should be. // This matches ratatui's actual word wrapping instead of trying to simulate it. let buffer = frame.buffer_mut(); - let cursor_char = prompt.len() + self.cursor; // Total chars from start (prompt + input) + + // Convert byte index to character index for the input portion + let input_chars_before_cursor = self.input[..self.cursor].chars().count(); + let cursor_char_pos = prompt.chars().count() + input_chars_before_cursor; + let mut char_count = 0usize; let mut cursor_x = input_area.x; let mut cursor_y = input_area.y; @@ -833,14 +837,13 @@ impl App { let symbol = cell.symbol(); // Count visible characters (skip zero-width and empty) if !symbol.is_empty() { - let width = symbol.width(); - if char_count + width > cursor_char { + if char_count == cursor_char_pos { // Found the cursor position cursor_x = x; cursor_y = y; break; } - char_count += width; + char_count += 1; } } }