@@ -285,6 +285,9 @@ impl<'a> TtfConsole<'a> {
285285 self . cursor_needs_redraw = true ;
286286
287287 if actual_lines. abs ( ) < self . height_chars as i32 {
288+ if !self . hidden_cursor {
289+ self . restore_cursor_bg ( ) ;
290+ }
288291 let pixel_offset = -( actual_lines * self . font_height as i32 ) ;
289292 self . renderer . scroll_y ( pixel_offset as i64 ) ;
290293
@@ -367,6 +370,9 @@ impl<'a> TtfConsole<'a> {
367370 self . cursor_y = self . height_chars - 1 ;
368371
369372 if old_scroll_offset_y != self . scroll_offset_y {
373+ if !self . hidden_cursor {
374+ self . restore_cursor_bg ( ) ;
375+ }
370376 let pixel_offset = -( lines_to_scroll as i32 * self . font_height as i32 ) ;
371377 self . renderer . scroll_y ( pixel_offset as i64 ) ;
372378
@@ -484,10 +490,7 @@ impl<'a> TtfConsole<'a> {
484490 }
485491 }
486492
487- pub fn draw_cursor ( & mut self ) {
488- if !self . cursor_needs_redraw || self . hidden_cursor {
489- return ;
490- }
493+ fn restore_cursor_bg ( & mut self ) {
491494 if self . prev_cursor_y < self . height_chars {
492495 let prev_x = self . prev_cursor_x ;
493496 let prev_y = self . prev_cursor_y ;
@@ -514,6 +517,14 @@ impl<'a> TtfConsole<'a> {
514517 ) ;
515518 }
516519 }
520+ }
521+
522+ pub fn draw_cursor ( & mut self ) {
523+ if !self . cursor_needs_redraw || self . hidden_cursor {
524+ return ;
525+ }
526+ self . restore_cursor_bg ( ) ;
527+
517528 if self . cursor_y < self . height_chars {
518529 let cursor_x_px = self . cursor_x * self . font_width ;
519530 let cursor_y_px = self . cursor_y * self . font_height ;
@@ -626,6 +637,29 @@ impl<'a> TtfConsole<'a> {
626637 }
627638 }
628639 }
640+ '\x08' => {
641+ if self . cursor_x > 0 {
642+ self . cursor_x -= 1 ;
643+ // Clear the character in the buffer
644+ let buf_y = ( self . cursor_y + self . scroll_offset_y as u32 ) as usize ;
645+ let idx = buf_y * self . width_chars as usize + self . cursor_x as usize ;
646+
647+ if let Some ( cell) = self . buffer . get_mut ( idx) {
648+ * cell = None ;
649+ }
650+
651+ // Clear visually
652+ self . renderer . fill_rect (
653+ Pixel :: new (
654+ ( self . cursor_x * self . font_width ) as u64 ,
655+ ( self . cursor_y * self . font_height ) as u64 ,
656+ ) ,
657+ self . font_width as u64 ,
658+ self . font_height as u64 ,
659+ self . current_bg_color ,
660+ ) ;
661+ }
662+ }
629663 _ => {
630664 self . put_char_impl ( c) ;
631665 self . cursor_x += 1 ;
@@ -674,6 +708,15 @@ impl<'a> TtfConsole<'a> {
674708
675709 self . apply_ansi_codes ( & params[ ..count] ) ;
676710 self . ansi_parse_state = AnsiParseState :: Normal ;
711+ } else if c == 'J' {
712+ // Handle erase display command
713+ let param = if self . ansi_has_digit {
714+ self . ansi_params [ 0 ]
715+ } else {
716+ 0
717+ } ;
718+ self . handle_erase_display ( param) ;
719+ self . ansi_parse_state = AnsiParseState :: Normal ;
677720 } else {
678721 self . ansi_parse_state = AnsiParseState :: Normal ;
679722 }
@@ -773,6 +816,50 @@ impl<'a> TtfConsole<'a> {
773816 self . redraw ( ) ;
774817 }
775818 }
819+
820+ /// Handle erase display ANSI command (ESC [ n J)
821+ /// n=0: clear from cursor to end of screen
822+ /// n=1: clear from beginning to cursor
823+ /// n=2: clear entire screen and move cursor to top-left
824+ fn handle_erase_display ( & mut self , n : u32 ) {
825+ match n {
826+ 2 => {
827+ // Clear entire screen and reset cursor
828+ self . buffer . clear ( ) ;
829+ self . buffer
830+ . resize ( ( self . width_chars * self . height_chars ) as usize , None ) ;
831+ self . cursor_x = 0 ;
832+ self . cursor_y = 0 ;
833+ self . scroll_offset_y = 0 ;
834+ self . cursor_needs_redraw = true ;
835+ self . redraw ( ) ;
836+ }
837+ 0 => {
838+ // Clear from cursor to end of screen
839+ let start_buf_y = ( self . cursor_y + self . scroll_offset_y as u32 ) as usize ;
840+ let start_idx = start_buf_y * self . width_chars as usize + self . cursor_x as usize ;
841+ for i in start_idx..self . buffer . len ( ) {
842+ if let Some ( cell) = self . buffer . get_mut ( i) {
843+ * cell = None ;
844+ }
845+ }
846+ // Clear visually from cursor to end
847+ self . redraw ( ) ;
848+ }
849+ 1 => {
850+ // Clear from beginning to cursor
851+ let end_buf_y = ( self . cursor_y + self . scroll_offset_y as u32 ) as usize ;
852+ let end_idx = end_buf_y * self . width_chars as usize + self . cursor_x as usize ;
853+ for i in 0 ..=end_idx. min ( self . buffer . len ( ) - 1 ) {
854+ if let Some ( cell) = self . buffer . get_mut ( i) {
855+ * cell = None ;
856+ }
857+ }
858+ self . redraw ( ) ;
859+ }
860+ _ => { }
861+ }
862+ }
776863}
777864
778865impl Write for TtfConsole < ' _ > {
@@ -845,6 +932,29 @@ impl<'a> crate::output::console::Console for TtfConsole<'a> {
845932 }
846933 }
847934 }
935+ '\x08' => {
936+ if self . cursor_x > 0 {
937+ self . cursor_x -= 1 ;
938+ // Clear the character in the buffer
939+ let buf_y = ( self . cursor_y + self . scroll_offset_y as u32 ) as usize ;
940+ let idx = buf_y * self . width_chars as usize + self . cursor_x as usize ;
941+
942+ if let Some ( cell) = self . buffer . get_mut ( idx) {
943+ * cell = None ;
944+ }
945+
946+ // Clear visually
947+ self . renderer . fill_rect (
948+ Pixel :: new (
949+ ( self . cursor_x * self . font_width ) as u64 ,
950+ ( self . cursor_y * self . font_height ) as u64 ,
951+ ) ,
952+ self . font_width as u64 ,
953+ self . font_height as u64 ,
954+ self . current_bg_color ,
955+ ) ;
956+ }
957+ }
848958 _ => {
849959 self . put_char_impl ( ch) ;
850960 self . cursor_x += 1 ;
0 commit comments