diff --git a/src/grid.rs b/src/grid.rs index a9ecfff..c61857a 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -122,7 +122,14 @@ impl Grid { self.scrollback .iter() .skip(scrollback_len - self.scrollback_offset) - .chain(self.rows.iter().take(rows_len - self.scrollback_offset)) + // when scrollback_offset > rows_len (e.g. rows = 3, + // scrollback_len = 10, offset = 9) the skip(10 - 9) + // will take 9 rows instead of 3. we need to set + // the upper bound to rows_len (e.g. 3) + .take(rows_len) + // same for rows_len - scrollback_offset (e.g. 3 - 9). + // it'll panic with overflow. we have to saturate the subtraction. + .chain(self.rows.iter().take(rows_len.saturating_sub(self.scrollback_offset))) } pub fn drawing_rows(&self) -> impl Iterator { diff --git a/tests/scroll.rs b/tests/scroll.rs index 16bd42c..5395812 100644 --- a/tests/scroll.rs +++ b/tests/scroll.rs @@ -1,3 +1,5 @@ +use std::ops::RangeInclusive; + mod helpers; #[test] @@ -110,3 +112,25 @@ fn edge_of_screen() { b"\x1b[24;75H\x1b[31mfoobar\x1b[24;80H" ); } + +#[test] +fn scrollback_larger_than_rows() { + let mut parser = vt100::Parser::new(3, 20, 10); + + parser.process(&gen_nums(1..=10, "\r\n").as_bytes()); + + // 1. Extra rows returned + parser.screen_mut().set_scrollback(4); + assert_eq!(parser.screen().contents(), gen_nums(4..=6, "\n")); + + // 2. Subtraction overflow + parser.screen_mut().set_scrollback(10); + assert_eq!(parser.screen().contents(), gen_nums(1..=4, "\n")); +} + +#[cfg(test)] +fn gen_nums(range: RangeInclusive, join: &str) -> String { + range.map(|num| num.to_string()) + .collect::>() + .join(join) +}