diff --git a/term/src/screen.rs b/term/src/screen.rs index 10a06077abc..13580aff390 100644 --- a/term/src/screen.rs +++ b/term/src/screen.rs @@ -649,6 +649,8 @@ impl Screen { ) { let phys_scroll = self.phys_range(scroll_region); let num_rows = num_rows.min(phys_scroll.end - phys_scroll.start); + let scrollback_ok = scroll_region.start == 0 && self.allow_scrollback; + let insert_at_end = scroll_region.end as usize == self.physical_rows; debug!( "scroll_up {:?} num_rows={} phys_scroll={:?}", @@ -660,7 +662,7 @@ impl Screen { // changed by the scroll operation. For normal newline at the bottom // of the screen based scrolling, the StableRowIndex does not change, // so we use the scroll region bounds to gate the invalidation. - if scroll_region.start != 0 || scroll_region.end as usize != self.physical_rows { + if !scrollback_ok { for y in phys_scroll.clone() { self.line_mut(y).update_last_change_seqno(seqno); } @@ -668,7 +670,7 @@ impl Screen { // if we're going to remove lines due to lack of scrollback capacity, // remember how many so that we can adjust our insertion point later. - let lines_removed = if scroll_region.start > 0 { + let lines_removed = if !scrollback_ok { // No scrollback available for these; // Remove the scrolled lines num_rows @@ -708,7 +710,7 @@ impl Screen { line.update_last_change_seqno(seqno); line }; - if scroll_region.end as usize == self.physical_rows { + if insert_at_end { self.lines.push_back(line); } else { self.lines.insert(phys_scroll.end - 1, line); @@ -724,12 +726,10 @@ impl Screen { self.lines.remove(remove_idx); } - if remove_idx == 0 && self.allow_scrollback { + if remove_idx == 0 && scrollback_ok { self.stable_row_index_offset += lines_removed; } - // It's cheaper to push() than it is insert() at the end - let push = scroll_region.end as usize == self.physical_rows; for _ in 0..to_add { let mut line = if default_blank == blank_attr { Line::new(seqno) @@ -741,12 +741,19 @@ impl Screen { ) }; bidi_mode.apply_to_line(&mut line, seqno); - if push { + if insert_at_end { self.lines.push_back(line); } else { self.lines.insert(phys_scroll.end, line); } } + + // If we have invalidated the StableRowIndex, mark all subsequent lines as dirty + if to_remove > 0 || (to_add > 0 && !insert_at_end) { + for y in self.phys_range(&(scroll_region.end..self.physical_rows as VisibleRowIndex)) { + self.line_mut(y).update_last_change_seqno(seqno); + } + } } pub fn erase_scrollback(&mut self) {