summaryrefslogtreecommitdiffstats
path: root/rsnix/src/vt.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rsnix/src/vt.rs33
1 files changed, 26 insertions, 7 deletions
diff --git a/rsnix/src/vt.rs b/rsnix/src/vt.rs
index 3b81d68..4db08fc 100644
--- a/rsnix/src/vt.rs
+++ b/rsnix/src/vt.rs
@@ -485,20 +485,29 @@ pub fn clear_all() {
485// --------------------------------------------------------------------------- 485// ---------------------------------------------------------------------------
486 486
487/// Blit every cell whose content differs from what the framebuffer shows, 487/// Blit every cell whose content differs from what the framebuffer shows,
488/// then draw the logical cursor (inverse video) on top. 488/// then draw the logical cursor (inverse video) on top. The cursor's
489/// inverse colours are mirrored into RENDERED so that pixel shifts
490/// (scrolling) or full clears can never leave a stale inverse block that
491/// the diff can't see (blank-vs-blank).
489fn flush() { 492fn flush() {
490 let rows = unsafe { ROWS }; 493 let rows = unsafe { ROWS };
491 let cols = unsafe { COLS }; 494 let cols = unsafe { COLS };
492 let n = rows * cols; 495 let n = rows * cols;
496 let cursor_visible = unsafe { CURSOR_VISIBLE };
497 let (cr, cc) = unsafe { (CURSOR_R, CURSOR_C) };
493 { 498 {
494 let cells = cells(); 499 let cells = cells();
495 let rendered = rendered_cells(); 500 let rendered = rendered_cells();
496 for i in 0..n { 501 for i in 0..n {
502 let row = i / cols;
503 let col = i % cols;
504 // The visible cursor cell is owned by the cursor pass below.
505 if cursor_visible && row == cr && col == cc {
506 continue;
507 }
497 let c = cells[i]; 508 let c = cells[i];
498 let r = rendered[i]; 509 let r = rendered[i];
499 if c != r { 510 if c != r {
500 let row = i / cols;
501 let col = i % cols;
502 let fg = PALETTE[c.fg as usize]; 511 let fg = PALETTE[c.fg as usize];
503 let bg = PALETTE[c.bg as usize]; 512 let bg = PALETTE[c.bg as usize];
504 gop::blit_glyph(col, row, c.ch, fg, bg); 513 gop::blit_glyph(col, row, c.ch, fg, bg);
@@ -510,20 +519,30 @@ fn flush() {
510 unsafe { 519 unsafe {
511 let (lr, lc) = LAST_CURSOR; 520 let (lr, lc) = LAST_CURSOR;
512 let moved = (lr, lc) != (CURSOR_R, CURSOR_C); 521 let moved = (lr, lc) != (CURSOR_R, CURSOR_C);
513 // Erase the previous cursor position (restore its normal colours). 522 // Erase the previous cursor position (restore its normal colours)
523 // and record it in RENDERED so the diff stays in sync.
514 if (moved || !CURSOR_VISIBLE) && lr < rows && lc < cols { 524 if (moved || !CURSOR_VISIBLE) && lr < rows && lc < cols {
515 let c = cells()[idx(lr, lc)]; 525 let i = idx(lr, lc);
526 let c = cells()[i];
516 let fg = PALETTE[c.fg as usize]; 527 let fg = PALETTE[c.fg as usize];
517 let bg = PALETTE[c.bg as usize]; 528 let bg = PALETTE[c.bg as usize];
518 gop::blit_glyph(lc, lr, c.ch, fg, bg); 529 gop::blit_glyph(lc, lr, c.ch, fg, bg);
530 rendered_cells()[i] = c;
519 } 531 }
520 LAST_CURSOR = (CURSOR_R, CURSOR_C); 532 LAST_CURSOR = (CURSOR_R, CURSOR_C);
521 // Draw the cursor as an inverse-video cell. 533 // Draw the cursor as an inverse-video cell, mirroring the inverse
534 // colours into RENDERED (scrolling/clearing then repair it).
522 if CURSOR_VISIBLE && CURSOR_R < rows && CURSOR_C < cols { 535 if CURSOR_VISIBLE && CURSOR_R < rows && CURSOR_C < cols {
523 let c = cells()[idx(CURSOR_R, CURSOR_C)]; 536 let i = idx(CURSOR_R, CURSOR_C);
537 let c = cells()[i];
524 let fg = PALETTE[c.fg as usize]; 538 let fg = PALETTE[c.fg as usize];
525 let bg = PALETTE[c.bg as usize]; 539 let bg = PALETTE[c.bg as usize];
526 gop::blit_glyph(CURSOR_C, CURSOR_R, c.ch, bg, fg); 540 gop::blit_glyph(CURSOR_C, CURSOR_R, c.ch, bg, fg);
541 rendered_cells()[i] = Cell {
542 ch: c.ch,
543 fg: c.bg,
544 bg: c.fg,
545 };
527 } 546 }
528 } 547 }
529} 548}