@@ -34,31 +34,40 @@ impl VgaConsole {
3434 self . row += 1 ;
3535 }
3636
37+ fn reset_cursor ( & mut self ) {
38+ self . row = 0 ;
39+ self . col = 0 ;
40+ }
41+
3742 fn scroll_as_required ( & mut self ) {
38- if self . col == self . width {
43+ assert ! ( self . row <= self . height) ;
44+ if self . col >= self . width {
3945 self . col = 0 ;
4046 self . row += 1 ;
4147 }
4248 if self . row == self . height {
43- self . row = self . height - 1 ;
49+ self . row -= 1 ;
4450 self . scroll_page ( ) ;
4551 }
4652 }
4753
4854 pub fn clear ( & mut self ) {
4955 for row in 0 ..self . height {
5056 for col in 0 ..self . width {
51- self . row = row;
52- self . col = col;
53- self . write ( b' ' , Some ( Self :: DEFAULT_ATTR ) ) ;
57+ self . write_at ( row, col, b' ' , Some ( Self :: DEFAULT_ATTR ) ) ;
5458 }
5559 }
56- self . row = 0 ;
57- self . col = 0 ;
60+ self . reset_cursor ( ) ;
5861 }
5962
6063 fn write ( & mut self , glyph : u8 , attr : Option < u8 > ) {
61- let offset = ( ( self . row * self . width ) + self . col ) * 2 ;
64+ self . write_at ( self . row , self . col , glyph, attr) ;
65+ }
66+
67+ fn write_at ( & mut self , row : isize , col : isize , glyph : u8 , attr : Option < u8 > ) {
68+ assert ! ( row < self . height, "{} >= {}?" , row, self . height) ;
69+ assert ! ( col < self . width, "{} => {}?" , col, self . width) ;
70+ let offset = ( ( row * self . width ) + col) * 2 ;
6271 unsafe { core:: ptr:: write_volatile ( self . addr . offset ( offset) , glyph) } ;
6372 if let Some ( a) = attr {
6473 unsafe { core:: ptr:: write_volatile ( self . addr . offset ( offset + 1 ) , a) } ;
@@ -68,17 +77,16 @@ impl VgaConsole {
6877 fn scroll_page ( & mut self ) {
6978 let row_len_bytes = self . width * 2 ;
7079 unsafe {
80+ // Scroll rows[1..=height-1] to become rows[0..=height-2].
7181 core:: ptr:: copy (
7282 self . addr . offset ( row_len_bytes) ,
7383 self . addr ,
7484 ( row_len_bytes * ( self . height - 1 ) ) as usize ,
7585 ) ;
76- // Blank bottom line
86+ // Blank the bottom line of the screen (rows[height-1]).
7787 for col in 0 ..self . width {
78- self . col = col;
79- self . write ( b' ' , Some ( Self :: DEFAULT_ATTR ) ) ;
88+ self . write_at ( self . height - 1 , col, b' ' , Some ( Self :: DEFAULT_ATTR ) ) ;
8089 }
81- self . col = 0 ;
8290 }
8391 }
8492
@@ -228,8 +236,12 @@ impl VgaConsole {
228236impl core:: fmt:: Write for VgaConsole {
229237 fn write_str ( & mut self , data : & str ) -> core:: fmt:: Result {
230238 for ch in data. chars ( ) {
239+ self . scroll_as_required ( ) ;
231240 match ch {
232241 '\u{0008}' => {
242+ // This is a backspace, so we go back one character (if we
243+ // can). We expect the caller to provide "\u{0008} \u{0008}"
244+ // to actually erase the char then move the cursor over it.
233245 if self . col > 0 {
234246 self . col -= 1 ;
235247 }
@@ -242,7 +254,6 @@ impl core::fmt::Write for VgaConsole {
242254 self . move_char_down ( ) ;
243255 }
244256 _ => {
245- self . scroll_as_required ( ) ;
246257 self . write ( Self :: map_char_to_glyph ( ch) , None ) ;
247258 self . move_char_right ( ) ;
248259 }
0 commit comments