mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 05:12:40 +03:00
use Range for scroll region
This commit is contained in:
parent
904f8fc059
commit
78c2df34fc
117
term/src/lib.rs
117
term/src/lib.rs
@ -11,7 +11,7 @@ extern crate unicode_segmentation;
|
||||
extern crate vte;
|
||||
|
||||
use failure::Error;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
|
||||
#[macro_use]
|
||||
mod debug;
|
||||
@ -33,6 +33,11 @@ pub type PhysRowIndex = usize;
|
||||
/// iterator Skip trait that is currently only in unstable rust.
|
||||
pub type VisibleRowIndex = i64;
|
||||
|
||||
/// range.contains(), but that is unstable
|
||||
fn in_range<T: PartialOrd>(value: T, range: &Range<T>) -> bool {
|
||||
value >= range.start && value < range.end
|
||||
}
|
||||
|
||||
/// Position allows referring to an absolute visible row number
|
||||
/// or a position relative to some existing row number (typically
|
||||
/// where the cursor is located). Both of the cases are represented
|
||||
@ -434,11 +439,21 @@ impl Screen {
|
||||
}
|
||||
}
|
||||
|
||||
/// Translate a VisibleRowIndex into a PhysRowIndex. The resultant index
|
||||
/// will be invalidated by inserting or removing rows!
|
||||
#[inline]
|
||||
fn phys_row(&self, row: VisibleRowIndex) -> PhysRowIndex {
|
||||
assert!(row >= 0);
|
||||
(self.lines.len() - self.physical_rows) + row as usize
|
||||
}
|
||||
|
||||
/// Translate a range of VisibleRowIndex to a range of PhysRowIndex.
|
||||
/// The resultant range will be invalidated by inserting or removing rows!
|
||||
#[inline]
|
||||
fn phys_range(&self, range: &Range<VisibleRowIndex>) -> Range<PhysRowIndex> {
|
||||
self.phys_row(range.start)..self.phys_row(range.end)
|
||||
}
|
||||
|
||||
/// ---------
|
||||
/// |
|
||||
/// |--- top
|
||||
@ -451,25 +466,19 @@ impl Screen {
|
||||
/// at bottom.
|
||||
/// If the top of the region is the top of the visible display, rather than
|
||||
/// removing the lines we let them go into the scrollback.
|
||||
fn scroll_up(
|
||||
&mut self,
|
||||
scroll_top: VisibleRowIndex,
|
||||
scroll_bottom: VisibleRowIndex,
|
||||
num_rows: usize,
|
||||
) {
|
||||
let top_idx = self.phys_row(scroll_top);
|
||||
let bot_idx = self.phys_row(scroll_bottom);
|
||||
assert!(num_rows <= bot_idx - top_idx);
|
||||
fn scroll_up(&mut self, scroll_region: &Range<VisibleRowIndex>, num_rows: usize) {
|
||||
let phys_scroll = self.phys_range(&scroll_region);
|
||||
assert!(num_rows <= phys_scroll.end - phys_scroll.start);
|
||||
|
||||
// Invalidate the lines that will move before they move so that
|
||||
// the indices of the lines are stable (we may remove lines below)
|
||||
for y in top_idx..bot_idx + 1 {
|
||||
for y in phys_scroll.clone() {
|
||||
self.line_mut(y).set_dirty();
|
||||
}
|
||||
|
||||
// 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_top > 0 {
|
||||
let lines_removed = if scroll_region.start > 0 {
|
||||
// No scrollback available for these;
|
||||
// Remove the scrolled lines
|
||||
num_rows
|
||||
@ -484,20 +493,20 @@ impl Screen {
|
||||
|
||||
// Perform the removal
|
||||
for _ in 0..lines_removed {
|
||||
self.lines.remove(top_idx);
|
||||
self.lines.remove(phys_scroll.start);
|
||||
}
|
||||
|
||||
if scroll_top == 0 {
|
||||
if scroll_region.start == 0 {
|
||||
// All of the lines above the top are now effectively dirty because
|
||||
// they were moved into scrollback by the scroll operation.
|
||||
for y in 0..top_idx {
|
||||
for y in 0..phys_scroll.start {
|
||||
self.line_mut(y).set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..num_rows {
|
||||
self.lines.insert(
|
||||
bot_idx + 1 - lines_removed,
|
||||
phys_scroll.end - lines_removed,
|
||||
Line::new(self.physical_cols),
|
||||
);
|
||||
}
|
||||
@ -513,20 +522,14 @@ impl Screen {
|
||||
/// beyond the bottom get removed from the screen.
|
||||
/// In other words, we remove (bottom-num_rows..bottom) and then insert num_rows
|
||||
/// at scroll_top.
|
||||
fn scroll_down(
|
||||
&mut self,
|
||||
scroll_top: VisibleRowIndex,
|
||||
scroll_bottom: VisibleRowIndex,
|
||||
num_rows: usize,
|
||||
) {
|
||||
let top_idx = self.phys_row(scroll_top);
|
||||
let bot_idx = self.phys_row(scroll_bottom);
|
||||
assert!(num_rows <= bot_idx - top_idx);
|
||||
fn scroll_down(&mut self, scroll_region: &Range<VisibleRowIndex>, num_rows: usize) {
|
||||
let phys_scroll = self.phys_range(&scroll_region);
|
||||
assert!(num_rows <= phys_scroll.end - phys_scroll.start);
|
||||
|
||||
let middle = (bot_idx + 1) - num_rows;
|
||||
let middle = phys_scroll.end - num_rows;
|
||||
|
||||
// dirty the rows in the region
|
||||
for y in top_idx..middle {
|
||||
for y in phys_scroll.start..middle {
|
||||
self.line_mut(y).set_dirty();
|
||||
}
|
||||
|
||||
@ -535,7 +538,10 @@ impl Screen {
|
||||
}
|
||||
|
||||
for _ in 0..num_rows {
|
||||
self.lines.insert(top_idx, Line::new(self.physical_cols));
|
||||
self.lines.insert(
|
||||
phys_scroll.start,
|
||||
Line::new(self.physical_cols),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -566,8 +572,7 @@ pub struct TerminalState {
|
||||
answerback: Vec<AnswerBack>,
|
||||
|
||||
/// The scroll region
|
||||
scroll_top: VisibleRowIndex,
|
||||
scroll_bottom: VisibleRowIndex,
|
||||
scroll_region: Range<VisibleRowIndex>,
|
||||
|
||||
/// When set, modifies the sequence of bytes sent for keys
|
||||
/// designated as cursor keys. This includes various navigation
|
||||
@ -600,8 +605,7 @@ impl TerminalState {
|
||||
cursor: CursorPosition::default(),
|
||||
saved_cursor: CursorPosition::default(),
|
||||
answerback: Vec::new(),
|
||||
scroll_top: 0,
|
||||
scroll_bottom: physical_rows as i64 - 1,
|
||||
scroll_region: 0..physical_rows as VisibleRowIndex,
|
||||
wrap_next: false,
|
||||
application_cursor_keys: false,
|
||||
application_keypad: false,
|
||||
@ -780,15 +784,13 @@ impl TerminalState {
|
||||
}
|
||||
|
||||
fn scroll_up(&mut self, num_rows: usize) {
|
||||
let top = self.scroll_top;
|
||||
let bottom = self.scroll_bottom;
|
||||
self.screen_mut().scroll_up(top, bottom, num_rows)
|
||||
let scroll_region = self.scroll_region.clone();
|
||||
self.screen_mut().scroll_up(&scroll_region, num_rows)
|
||||
}
|
||||
|
||||
fn scroll_down(&mut self, num_rows: usize) {
|
||||
let top = self.scroll_top;
|
||||
let bottom = self.scroll_bottom;
|
||||
self.screen_mut().scroll_down(top, bottom, num_rows)
|
||||
let scroll_region = self.scroll_region.clone();
|
||||
self.screen_mut().scroll_down(&scroll_region, num_rows)
|
||||
}
|
||||
|
||||
fn new_line(&mut self, move_to_first_column: bool) {
|
||||
@ -798,7 +800,7 @@ impl TerminalState {
|
||||
self.cursor.x
|
||||
};
|
||||
let y = self.cursor.y;
|
||||
let y = if y == self.scroll_bottom {
|
||||
let y = if y == self.scroll_region.end - 1 {
|
||||
self.scroll_up(1);
|
||||
y
|
||||
} else {
|
||||
@ -815,7 +817,7 @@ impl TerminalState {
|
||||
/// scroll the region down.
|
||||
fn reverse_index(&mut self) {
|
||||
let y = self.cursor.y;
|
||||
let y = if y == self.scroll_top {
|
||||
let y = if y == self.scroll_region.start {
|
||||
self.scroll_down(1);
|
||||
y
|
||||
} else {
|
||||
@ -1036,39 +1038,26 @@ impl vte::Perform for TerminalState {
|
||||
}
|
||||
CSIAction::SetScrollingRegion { top, bottom } => {
|
||||
let rows = self.screen().physical_rows;
|
||||
self.scroll_top = top.min(rows as i64 - 1);
|
||||
self.scroll_bottom = bottom.min(rows as i64 - 1);
|
||||
if self.scroll_top > self.scroll_bottom {
|
||||
std::mem::swap(&mut self.scroll_top, &mut self.scroll_bottom);
|
||||
let mut top = top.min(rows as i64 - 1);
|
||||
let mut bottom = bottom.min(rows as i64 - 1);
|
||||
if top > bottom {
|
||||
std::mem::swap(&mut top, &mut bottom);
|
||||
}
|
||||
self.scroll_region = top..bottom + 1;
|
||||
}
|
||||
CSIAction::RequestDeviceAttributes => {
|
||||
self.push_answerback(DEVICE_IDENT);
|
||||
}
|
||||
CSIAction::DeleteLines(n) => {
|
||||
let top = self.cursor.y;
|
||||
let bottom = self.scroll_bottom;
|
||||
if top >= self.scroll_top && top <= bottom {
|
||||
debug!(
|
||||
"execute delete {} lines with scroll up {} {}",
|
||||
n,
|
||||
top,
|
||||
top + n
|
||||
);
|
||||
self.screen_mut().scroll_up(top, bottom, n as usize);
|
||||
if in_range(self.cursor.y, &self.scroll_region) {
|
||||
let scroll_region = self.cursor.y..self.scroll_region.end;
|
||||
self.screen_mut().scroll_up(&scroll_region, n as usize);
|
||||
}
|
||||
}
|
||||
CSIAction::InsertLines(n) => {
|
||||
let top = self.cursor.y;
|
||||
let bottom = self.scroll_bottom;
|
||||
if top >= self.scroll_top && top <= bottom {
|
||||
debug!(
|
||||
"execute insert {} lines with scroll down {} {}",
|
||||
n,
|
||||
top,
|
||||
top + n
|
||||
);
|
||||
self.screen_mut().scroll_down(top, bottom, n as usize);
|
||||
if in_range(self.cursor.y, &self.scroll_region) {
|
||||
let scroll_region = self.cursor.y..self.scroll_region.end;
|
||||
self.screen_mut().scroll_down(&scroll_region, n as usize);
|
||||
}
|
||||
}
|
||||
CSIAction::SaveCursor => {
|
||||
|
Loading…
Reference in New Issue
Block a user