Fix ensure_scoll bug where logical and visual lines were mixed up.

This commit is contained in:
2025-12-10 22:08:30 +00:00
parent 3927899428
commit 260867e225
+43 -19
View File
@@ -347,29 +347,53 @@ void cursor_left(Editor *editor, uint32_t number) {
} }
void ensure_scroll(Editor *editor) { void ensure_scroll(Editor *editor) {
if (editor->cursor.row < editor->scroll.row) {
uint32_t visual_delta = 0;
LineIterator *it = begin_l_iter(editor->root, editor->cursor.row);
for (uint32_t i = editor->cursor.row; i < editor->scroll.row; i++) {
char *line = next_line(it);
if (!line)
break;
uint32_t len = grapheme_strlen(line);
visual_delta += (len + editor->size.col - 1) / editor->size.col;
free(line);
}
free(it);
scroll_up(editor, visual_delta);
return;
}
uint32_t current_visual_y = 0;
LineIterator *it = begin_l_iter(editor->root, editor->scroll.row); LineIterator *it = begin_l_iter(editor->root, editor->scroll.row);
uint32_t rendered_lines = 0; uint32_t i = editor->scroll.row;
uint32_t line_index = editor->scroll.row; char *line = nullptr;
char *line_content = nullptr; bool found_cursor = false;
while (rendered_lines <= editor->size.row) { while ((line = next_line(it)) != nullptr) {
line_content = next_line(it); uint32_t lines_in_chunk;
if (!line_content) uint32_t offset = (i == editor->scroll.row) ? editor->scroll.col : 0;
if (i == editor->cursor.row) {
uint32_t cursor_sub_row = editor->cursor.col / editor->size.col;
if (i == editor->scroll.row)
cursor_sub_row -= offset / editor->size.col;
current_visual_y += cursor_sub_row;
found_cursor = true;
free(line);
break; break;
char *line_content_t = line_content; }
if (rendered_lines == 0) uint32_t len = grapheme_strlen(line);
line_content_t = line_content + editor->scroll.col; uint32_t visible_len = len - offset;
uint32_t len = grapheme_strlen(line_content_t); if (visible_len == 0)
free(line_content); visible_len = 1;
uint32_t wrapped_lines = (len + editor->size.col - 1) / editor->size.col; lines_in_chunk = (visible_len + editor->size.col - 1) / editor->size.col;
rendered_lines += wrapped_lines; current_visual_y += lines_in_chunk;
line_index++; free(line);
i++;
} }
line_index -= 2;
free(it); free(it);
if (editor->cursor.row >= line_index && line_content) if (found_cursor)
scroll_down(editor, editor->cursor.row - line_index); if (current_visual_y >= editor->size.row) {
if (editor->cursor.row < editor->scroll.row) uint32_t needed_scroll = current_visual_y - editor->size.row + 1;
scroll_up(editor, editor->scroll.row - editor->cursor.row); scroll_down(editor, needed_scroll);
}
} }
void fold(Editor *editor, uint32_t start_line, uint32_t end_line) { void fold(Editor *editor, uint32_t start_line, uint32_t end_line) {