aboutsummaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/grid/resize.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src/grid/resize.rs')
-rw-r--r--alacritty_terminal/src/grid/resize.rs134
1 files changed, 68 insertions, 66 deletions
diff --git a/alacritty_terminal/src/grid/resize.rs b/alacritty_terminal/src/grid/resize.rs
index 40492c3a..eb8bef0c 100644
--- a/alacritty_terminal/src/grid/resize.rs
+++ b/alacritty_terminal/src/grid/resize.rs
@@ -1,9 +1,9 @@
//! Grid resize and reflow.
-use std::cmp::{min, Ordering};
+use std::cmp::{max, min, Ordering};
use std::mem;
-use crate::index::{Column, Line};
+use crate::index::{Boundary, Column, Line};
use crate::term::cell::{Flags, ResetDiscriminant};
use crate::grid::row::Row;
@@ -11,7 +11,7 @@ use crate::grid::{Dimensions, Grid, GridCell};
impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
/// Resize the grid's width and/or height.
- pub fn resize<D>(&mut self, reflow: bool, lines: Line, cols: Column)
+ pub fn resize<D>(&mut self, reflow: bool, lines: usize, columns: usize)
where
T: ResetDiscriminant<D>,
D: PartialEq,
@@ -25,9 +25,9 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
Ordering::Equal => (),
}
- match self.cols.cmp(&cols) {
- Ordering::Less => self.grow_cols(reflow, cols),
- Ordering::Greater => self.shrink_cols(reflow, cols),
+ match self.columns.cmp(&columns) {
+ Ordering::Less => self.grow_columns(reflow, columns),
+ Ordering::Greater => self.shrink_columns(reflow, columns),
Ordering::Equal => (),
}
@@ -40,32 +40,32 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
/// Alacritty keeps the cursor at the bottom of the terminal as long as there
/// is scrollback available. Once scrollback is exhausted, new lines are
/// simply added to the bottom of the screen.
- fn grow_lines<D>(&mut self, new_line_count: Line)
+ fn grow_lines<D>(&mut self, target: usize)
where
T: ResetDiscriminant<D>,
D: PartialEq,
{
- let lines_added = new_line_count - self.lines;
+ let lines_added = target - self.lines;
// Need to resize before updating buffer.
- self.raw.grow_visible_lines(new_line_count);
- self.lines = new_line_count;
+ self.raw.grow_visible_lines(target);
+ self.lines = target;
let history_size = self.history_size();
- let from_history = min(history_size, lines_added.0);
+ let from_history = min(history_size, lines_added);
// Move existing lines up for every line that couldn't be pulled from history.
- if from_history != lines_added.0 {
+ if from_history != lines_added {
let delta = lines_added - from_history;
- self.scroll_up(&(Line(0)..new_line_count), delta);
+ self.scroll_up(&(Line(0)..Line(target as i32)), delta);
}
// Move cursor down for every line pulled from history.
self.saved_cursor.point.line += from_history;
self.cursor.point.line += from_history;
- self.display_offset = self.display_offset.saturating_sub(*lines_added);
- self.decrease_scroll_limit(*lines_added);
+ self.display_offset = self.display_offset.saturating_sub(lines_added);
+ self.decrease_scroll_limit(lines_added);
}
/// Remove lines from the visible area.
@@ -75,37 +75,37 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
/// of the terminal window.
///
/// Alacritty takes the same approach.
- fn shrink_lines<D>(&mut self, target: Line)
+ fn shrink_lines<D>(&mut self, target: usize)
where
T: ResetDiscriminant<D>,
D: PartialEq,
{
// Scroll up to keep content inside the window.
- let required_scrolling = (self.cursor.point.line + 1).saturating_sub(target.0);
+ let required_scrolling = (self.cursor.point.line.0 as usize + 1).saturating_sub(target);
if required_scrolling > 0 {
- self.scroll_up(&(Line(0)..self.lines), Line(required_scrolling));
+ self.scroll_up(&(Line(0)..Line(self.lines as i32)), required_scrolling);
// Clamp cursors to the new viewport size.
- self.cursor.point.line = min(self.cursor.point.line, target - 1);
+ self.cursor.point.line = min(self.cursor.point.line, Line(target as i32 - 1));
}
// Clamp saved cursor, since only primary cursor is scrolled into viewport.
- self.saved_cursor.point.line = min(self.saved_cursor.point.line, target - 1);
+ self.saved_cursor.point.line = min(self.saved_cursor.point.line, Line(target as i32 - 1));
- self.raw.rotate((self.lines - target).0 as isize);
+ self.raw.rotate((self.lines - target) as isize);
self.raw.shrink_visible_lines(target);
self.lines = target;
}
/// Grow number of columns in each row, reflowing if necessary.
- fn grow_cols(&mut self, reflow: bool, cols: Column) {
+ fn grow_columns(&mut self, reflow: bool, columns: usize) {
// Check if a row needs to be wrapped.
let should_reflow = |row: &Row<T>| -> bool {
let len = Column(row.len());
- reflow && len.0 > 0 && len < cols && row[len - 1].flags().contains(Flags::WRAPLINE)
+ reflow && len.0 > 0 && len < columns && row[len - 1].flags().contains(Flags::WRAPLINE)
};
- self.cols = cols;
+ self.columns = columns;
let mut reversed: Vec<Row<T>> = Vec::with_capacity(self.raw.len());
let mut cursor_line_delta = 0;
@@ -138,12 +138,12 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
if last_len >= 1
&& last_row[Column(last_len - 1)].flags().contains(Flags::LEADING_WIDE_CHAR_SPACER)
{
- last_row.shrink(Column(last_len - 1));
+ last_row.shrink(last_len - 1);
last_len -= 1;
}
// Don't try to pull more cells from the next line than available.
- let mut num_wrapped = cols.0 - last_len;
+ let mut num_wrapped = columns - last_len;
let len = min(row.len(), num_wrapped);
// Insert leading spacer when there's not enough room for reflowing wide char.
@@ -164,30 +164,30 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
// Add removed cells to previous row and reflow content.
last_row.append(&mut cells);
- let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
+ let cursor_buffer_line = self.lines - self.cursor.point.line.0 as usize - 1;
if i == cursor_buffer_line && reflow {
// Resize cursor's line and reflow the cursor if necessary.
- let mut target = self.cursor.point.sub(cols, num_wrapped);
+ let mut target = self.cursor.point.sub(self, Boundary::Cursor, num_wrapped);
// Clamp to the last column, if no content was reflown with the cursor.
if target.column.0 == 0 && row.is_clear() {
self.cursor.input_needs_wrap = true;
- target = target.sub(cols, 1);
+ target = target.sub(self, Boundary::Cursor, 1);
}
self.cursor.point.column = target.column;
- // Get required cursor line changes. Since `num_wrapped` is smaller than `cols`
+ // Get required cursor line changes. Since `num_wrapped` is smaller than `columns`
// this will always be either `0` or `1`.
- let line_delta = (self.cursor.point.line - target.line).0;
+ let line_delta = self.cursor.point.line - target.line;
if line_delta != 0 && row.is_clear() {
continue;
}
- cursor_line_delta += line_delta;
+ cursor_line_delta += line_delta.0 as usize;
} else if row.is_clear() {
- if i + reversed.len() >= self.lines.0 {
+ if i + reversed.len() >= self.lines {
// Since we removed a line, rotate down the viewport.
self.display_offset = self.display_offset.saturating_sub(1);
}
@@ -210,27 +210,27 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
}
// Make sure we have at least the viewport filled.
- if reversed.len() < self.lines.0 {
- let delta = self.lines.0 - reversed.len();
- self.cursor.point.line.0 = self.cursor.point.line.saturating_sub(delta);
- reversed.resize_with(self.lines.0, || Row::new(cols));
+ if reversed.len() < self.lines {
+ let delta = (self.lines - reversed.len()) as i32;
+ self.cursor.point.line = max(self.cursor.point.line - delta, Line(0));
+ reversed.resize_with(self.lines, || Row::new(columns));
}
// Pull content down to put cursor in correct position, or move cursor up if there's no
// more lines to delete below the cursor.
if cursor_line_delta != 0 {
- let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
- let available = min(cursor_buffer_line, reversed.len() - self.lines.0);
+ let cursor_buffer_line = self.lines - self.cursor.point.line.0 as usize - 1;
+ let available = min(cursor_buffer_line, reversed.len() - self.lines);
let overflow = cursor_line_delta.saturating_sub(available);
reversed.truncate(reversed.len() + overflow - cursor_line_delta);
- self.cursor.point.line.0 = self.cursor.point.line.saturating_sub(overflow);
+ self.cursor.point.line = max(self.cursor.point.line - overflow, Line(0));
}
// Reverse iterator and fill all rows that are still too short.
let mut new_raw = Vec::with_capacity(reversed.len());
for mut row in reversed.drain(..).rev() {
- if row.len() < cols.0 {
- row.grow(cols);
+ if row.len() < columns {
+ row.grow(columns);
}
new_raw.push(row);
}
@@ -242,8 +242,8 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
}
/// Shrink number of columns in each row, reflowing if necessary.
- fn shrink_cols(&mut self, reflow: bool, cols: Column) {
- self.cols = cols;
+ fn shrink_columns(&mut self, reflow: bool, columns: usize) {
+ self.columns = columns;
// Remove the linewrap special case, by moving the cursor outside of the grid.
if self.cursor.input_needs_wrap && reflow {
@@ -260,7 +260,7 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
if let Some(buffered) = buffered.take() {
// Add a column for every cell added before the cursor, if it goes beyond the new
// width it is then later reflown.
- let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
+ let cursor_buffer_line = self.lines - self.cursor.point.line.0 as usize - 1;
if i == cursor_buffer_line {
self.cursor.point.column += buffered.len();
}
@@ -270,11 +270,11 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
loop {
// Remove all cells which require reflowing.
- let mut wrapped = match row.shrink(cols) {
+ let mut wrapped = match row.shrink(columns) {
Some(wrapped) if reflow => wrapped,
_ => {
- let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
- if reflow && i == cursor_buffer_line && self.cursor.point.column > cols {
+ let cursor_buffer_line = self.lines - self.cursor.point.line.0 as usize - 1;
+ if reflow && i == cursor_buffer_line && self.cursor.point.column > columns {
// If there are empty cells before the cursor, we assume it is explicit
// whitespace and need to wrap it like normal content.
Vec::new()
@@ -287,11 +287,13 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
};
// Insert spacer if a wide char would be wrapped into the last column.
- if row.len() >= cols.0 && row[cols - 1].flags().contains(Flags::WIDE_CHAR) {
+ if row.len() >= columns
+ && row[Column(columns - 1)].flags().contains(Flags::WIDE_CHAR)
+ {
let mut spacer = T::default();
spacer.flags_mut().insert(Flags::LEADING_WIDE_CHAR_SPACER);
- let wide_char = mem::replace(&mut row[cols - 1], spacer);
+ let wide_char = mem::replace(&mut row[Column(columns - 1)], spacer);
wrapped.insert(0, wide_char);
}
@@ -299,7 +301,7 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
let len = wrapped.len();
if len > 0 && wrapped[len - 1].flags().contains(Flags::LEADING_WIDE_CHAR_SPACER) {
if len == 1 {
- row[cols - 1].flags_mut().insert(Flags::WRAPLINE);
+ row[Column(columns - 1)].flags_mut().insert(Flags::WRAPLINE);
new_raw.push(row);
break;
} else {
@@ -320,7 +322,7 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
.last()
.map(|c| c.flags().contains(Flags::WRAPLINE) && i >= 1)
.unwrap_or(false)
- && wrapped.len() < cols.0
+ && wrapped.len() < columns
{
// Make sure previous wrap flag doesn't linger around.
if let Some(cell) = wrapped.last_mut() {
@@ -332,24 +334,24 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
break;
} else {
// Reflow cursor if a line below it is deleted.
- let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
- if (i == cursor_buffer_line && self.cursor.point.column < cols)
+ let cursor_buffer_line = self.lines - self.cursor.point.line.0 as usize - 1;
+ if (i == cursor_buffer_line && self.cursor.point.column < columns)
|| i < cursor_buffer_line
{
- self.cursor.point.line.0 = self.cursor.point.line.saturating_sub(1);
+ self.cursor.point.line = max(self.cursor.point.line - 1, Line(0));
}
// Reflow the cursor if it is on this line beyond the width.
- if i == cursor_buffer_line && self.cursor.point.column >= cols {
- // Since only a single new line is created, we subtract only `cols`
+ if i == cursor_buffer_line && self.cursor.point.column >= columns {
+ // Since only a single new line is created, we subtract only `columns`
// from the cursor instead of reflowing it completely.
- self.cursor.point.column -= cols;
+ self.cursor.point.column -= columns;
}
// Make sure new row is at least as long as new width.
let occ = wrapped.len();
- if occ < cols.0 {
- wrapped.resize_with(cols.0, T::default);
+ if occ < columns {
+ wrapped.resize_with(columns, T::default);
}
row = Row::from_vec(wrapped, occ);
}
@@ -358,22 +360,22 @@ impl<T: GridCell + Default + PartialEq + Clone> Grid<T> {
// Reverse iterator and use it as the new grid storage.
let mut reversed: Vec<Row<T>> = new_raw.drain(..).rev().collect();
- reversed.truncate(self.max_scroll_limit + self.lines.0);
+ reversed.truncate(self.max_scroll_limit + self.lines);
self.raw.replace_inner(reversed);
// Reflow the primary cursor, or clamp it if reflow is disabled.
if !reflow {
- self.cursor.point.column = min(self.cursor.point.column, cols - 1);
- } else if self.cursor.point.column == cols
- && !self[self.cursor.point.line][cols - 1].flags().contains(Flags::WRAPLINE)
+ self.cursor.point.column = min(self.cursor.point.column, Column(columns - 1));
+ } else if self.cursor.point.column == columns
+ && !self[self.cursor.point.line][Column(columns - 1)].flags().contains(Flags::WRAPLINE)
{
self.cursor.input_needs_wrap = true;
self.cursor.point.column -= 1;
} else {
- self.cursor.point = self.cursor.point.add(cols, 0);
+ self.cursor.point = self.cursor.point.grid_clamp(self, Boundary::Cursor);
}
// Clamp the saved cursor to the grid.
- self.saved_cursor.point.column = min(self.saved_cursor.point.column, cols - 1);
+ self.saved_cursor.point.column = min(self.saved_cursor.point.column, Column(columns - 1));
}
}