:: commit 87ee50c69f41fea1d317f66c2f06e2057779bfa1

Mintsuki <mintsuki@protonmail.com> — 2026-04-11 22:01

parents: c1a093ef3b

drivers/vga_textmode: Defer line wrap to next putchar

diff --git a/common/drivers/vga_textmode.c b/common/drivers/vga_textmode.c
index fefb982f..0a5c5961 100644
--- a/common/drivers/vga_textmode.c
+++ b/common/drivers/vga_textmode.c
@@ -162,6 +162,7 @@ static void text_set_cursor_pos(struct flanterm_context *_ctx, size_t x, size_t
         }
     }
     ctx->cursor_offset = y * VD_COLS + x * 2;
+    ctx->cursor_overflow = false;
 }
 
 static uint8_t ansi_colours[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
@@ -219,17 +220,32 @@ static void text_set_text_bg_default_bright(struct flanterm_context *_ctx) {
 static void text_putchar(struct flanterm_context *_ctx, uint8_t c) {
     struct textmode_context *ctx = (void *)_ctx;
 
-    ctx->back_buffer[ctx->cursor_offset] = c;
-    ctx->back_buffer[ctx->cursor_offset + 1] = ctx->text_palette;
-    if (ctx->cursor_offset / VD_COLS == _ctx->scroll_bottom_margin - 1
-     && ctx->cursor_offset % VD_COLS == VD_COLS - 2) {
-        if (_ctx->scroll_enabled) {
-            text_scroll(_ctx);
+    // Handle overflow from previous putchar
+    if (ctx->cursor_overflow) {
+        ctx->cursor_overflow = false;
+        if (_ctx->wrap_enabled
+         && (ctx->cursor_offset / VD_COLS < _ctx->scroll_bottom_margin - 1
+             || _ctx->scroll_enabled)) {
             ctx->cursor_offset -= ctx->cursor_offset % VD_COLS;
+            ctx->cursor_offset += VD_COLS;
+            if (ctx->cursor_offset / VD_COLS == _ctx->scroll_bottom_margin) {
+                ctx->cursor_offset -= VD_COLS;
+                text_scroll(_ctx);
+            }
+            if (ctx->cursor_offset >= VD_ROWS * VD_COLS) {
+                ctx->cursor_offset = (VD_ROWS - 1) * VD_COLS;
+            }
+        } else {
+            ctx->cursor_offset = ctx->cursor_offset - (ctx->cursor_offset % VD_COLS) + VD_COLS - 2;
         }
-    } else if (ctx->cursor_offset >= (VIDEO_BOTTOM - 1)) {
-        ctx->cursor_offset -= ctx->cursor_offset % VD_COLS;
-    } else {
+    }
+
+    ctx->back_buffer[ctx->cursor_offset] = c;
+    ctx->back_buffer[ctx->cursor_offset + 1] = ctx->text_palette;
+    if (ctx->cursor_offset % VD_COLS == VD_COLS - 2) {
+        // At last column - flag overflow for next putchar
+        ctx->cursor_overflow = true;
+    } else if (ctx->cursor_offset < (VIDEO_BOTTOM - 1)) {
         ctx->cursor_offset += 2;
     }
 }
@@ -285,6 +301,7 @@ void vga_textmode_init(bool managed) {
     }
 
     ctx->cursor_offset = 0;
+    ctx->cursor_overflow = false;
     ctx->text_palette = 0x07;
 
     ctx->video_mem = (volatile uint8_t *)0xb8000;
diff --git a/common/drivers/vga_textmode.h b/common/drivers/vga_textmode.h
index c7bca53b..e8b56ce3 100644
--- a/common/drivers/vga_textmode.h
+++ b/common/drivers/vga_textmode.h
@@ -22,6 +22,7 @@ struct textmode_context {
     size_t cursor_offset;
     size_t old_cursor_offset;
     bool cursor_status;
+    bool cursor_overflow;
     uint8_t text_palette;
 
     uint8_t saved_state_text_palette;
tab: 248 wrap: offon