summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/grid
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src/grid')
-rw-r--r--alacritty_terminal/src/grid/mod.rs377
-rw-r--r--alacritty_terminal/src/grid/resize.rs274
-rw-r--r--alacritty_terminal/src/grid/row.rs12
-rw-r--r--alacritty_terminal/src/grid/storage.rs225
-rw-r--r--alacritty_terminal/src/grid/tests.rs22
5 files changed, 482 insertions, 428 deletions
diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs
index 71545dca..a136b1b5 100644
--- a/alacritty_terminal/src/grid/mod.rs
+++ b/alacritty_terminal/src/grid/mod.rs
@@ -14,22 +14,22 @@
//! A specialized 2D grid implementation optimized for use in a terminal.
-use std::cmp::{max, min, Ordering};
+use std::cmp::{max, min};
use std::ops::{Deref, Index, IndexMut, Range, RangeFrom, RangeFull, RangeTo};
use serde::{Deserialize, Serialize};
+use crate::ansi::{CharsetIndex, StandardCharset};
use crate::index::{Column, IndexRange, Line, Point};
-use crate::selection::Selection;
-use crate::term::cell::Flags;
+use crate::term::cell::{Cell, Flags};
+pub mod resize;
mod row;
-pub use self::row::Row;
-
+mod storage;
#[cfg(test)]
mod tests;
-mod storage;
+pub use self::row::Row;
use self::storage::Storage;
/// Bidirectional iterator.
@@ -60,7 +60,6 @@ impl<T: PartialEq> ::std::cmp::PartialEq for Grid<T> {
&& self.cols.eq(&other.cols)
&& self.lines.eq(&other.lines)
&& self.display_offset.eq(&other.display_offset)
- && self.selection.eq(&other.selection)
}
}
@@ -76,7 +75,36 @@ pub trait GridCell {
fn fast_eq(&self, other: Self) -> bool;
}
-/// Represents the terminal display contents.
+#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
+pub struct Cursor {
+ /// The location of this cursor.
+ pub point: Point,
+
+ /// Template cell when using this cursor.
+ pub template: Cell,
+
+ /// Currently configured graphic character sets.
+ pub charsets: Charsets,
+}
+
+#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
+pub struct Charsets([StandardCharset; 4]);
+
+impl Index<CharsetIndex> for Charsets {
+ type Output = StandardCharset;
+
+ fn index(&self, index: CharsetIndex) -> &StandardCharset {
+ &self.0[index as usize]
+ }
+}
+
+impl IndexMut<CharsetIndex> for Charsets {
+ fn index_mut(&mut self, index: CharsetIndex) -> &mut StandardCharset {
+ &mut self.0[index as usize]
+ }
+}
+
+/// Grid based terminal content storage.
///
/// ```notrust
/// ┌─────────────────────────┐ <-- max_scroll_limit + lines
@@ -105,6 +133,14 @@ pub trait GridCell {
/// ```
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Grid<T> {
+ /// Current cursor for writing data.
+ #[serde(skip)]
+ pub cursor: Cursor,
+
+ /// Last saved cursor.
+ #[serde(skip)]
+ pub saved_cursor: Cursor,
+
/// Lines in the grid. Each row holds a list of cells corresponding to the
/// columns in that row.
raw: Storage<T>,
@@ -122,10 +158,6 @@ pub struct Grid<T> {
/// updates this offset accordingly.
display_offset: usize,
- /// Selected region.
- #[serde(skip)]
- pub selection: Option<Selection>,
-
/// Maximum number of lines in history.
max_scroll_limit: usize,
}
@@ -139,10 +171,17 @@ pub enum Scroll {
Bottom,
}
-impl<T: GridCell + PartialEq + Copy> Grid<T> {
- pub fn new(lines: Line, cols: Column, scrollback: usize, template: T) -> Grid<T> {
- let raw = Storage::with_capacity(lines, Row::new(cols, &template));
- Grid { raw, cols, lines, display_offset: 0, selection: None, max_scroll_limit: scrollback }
+impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
+ pub fn new(lines: Line, cols: Column, max_scroll_limit: usize, template: T) -> Grid<T> {
+ Grid {
+ raw: Storage::with_capacity(lines, Row::new(cols, template)),
+ max_scroll_limit,
+ display_offset: 0,
+ saved_cursor: Cursor::default(),
+ cursor: Cursor::default(),
+ lines,
+ cols,
+ }
}
/// Clamp a buffer point to the visible region.
@@ -191,33 +230,7 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
}
}
- pub fn resize(
- &mut self,
- reflow: bool,
- lines: Line,
- cols: Column,
- cursor_pos: &mut Point,
- template: &T,
- ) {
- // Check that there's actually work to do and return early if not.
- if lines == self.lines && cols == self.cols {
- return;
- }
-
- match self.lines.cmp(&lines) {
- Ordering::Less => self.grow_lines(lines, cursor_pos, template),
- Ordering::Greater => self.shrink_lines(lines, cursor_pos, template),
- Ordering::Equal => (),
- }
-
- match self.cols.cmp(&cols) {
- Ordering::Less => self.grow_cols(reflow, cols, cursor_pos, template),
- Ordering::Greater => self.shrink_cols(reflow, cols, template),
- Ordering::Equal => (),
- }
- }
-
- fn increase_scroll_limit(&mut self, count: usize, template: &T) {
+ fn increase_scroll_limit(&mut self, count: usize, template: T) {
let count = min(count, self.max_scroll_limit - self.history_size());
if count != 0 {
self.raw.initialize(count, template, self.cols);
@@ -228,238 +241,12 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
let count = min(count, self.history_size());
if count != 0 {
self.raw.shrink_lines(min(count, self.history_size()));
+ self.display_offset = min(self.display_offset, self.history_size());
}
}
- /// Add lines to the visible area.
- ///
- /// 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(&mut self, new_line_count: Line, cursor_pos: &mut Point, template: &T) {
- let lines_added = new_line_count - self.lines;
-
- // Need to "resize" before updating buffer.
- self.raw.grow_visible_lines(new_line_count, Row::new(self.cols, template));
- self.lines = new_line_count;
-
- let history_size = self.history_size();
- let from_history = min(history_size, lines_added.0);
-
- // Move cursor down for all lines pulled from history.
- cursor_pos.line += from_history;
-
- if from_history != lines_added.0 {
- // Move existing lines up for every line that couldn't be pulled from history.
- self.scroll_up(&(Line(0)..new_line_count), lines_added - from_history, template);
- }
-
- self.decrease_scroll_limit(*lines_added);
- self.display_offset = self.display_offset.saturating_sub(*lines_added);
- }
-
- /// Grow number of columns in each row, reflowing if necessary.
- fn grow_cols(&mut self, reflow: bool, cols: Column, cursor_pos: &mut Point, template: &T) {
- // Check if a row needs to be wrapped.
- let should_reflow = |row: &Row<T>| -> bool {
- let len = Column(row.len());
- reflow && len < cols && row[len - 1].flags().contains(Flags::WRAPLINE)
- };
-
- let mut new_empty_lines = 0;
- let mut reversed: Vec<Row<T>> = Vec::with_capacity(self.raw.len());
- for (i, mut row) in self.raw.drain().enumerate().rev() {
- // Check if reflowing should be performed.
- let last_row = match reversed.last_mut() {
- Some(last_row) if should_reflow(last_row) => last_row,
- _ => {
- reversed.push(row);
- continue;
- },
- };
-
- // Remove wrap flag before appending additional cells.
- if let Some(cell) = last_row.last_mut() {
- cell.flags_mut().remove(Flags::WRAPLINE);
- }
-
- // Remove leading spacers when reflowing wide char to the previous line.
- let last_len = last_row.len();
- if last_len >= 2
- && !last_row[Column(last_len - 2)].flags().contains(Flags::WIDE_CHAR)
- && last_row[Column(last_len - 1)].flags().contains(Flags::WIDE_CHAR_SPACER)
- {
- last_row.shrink(Column(last_len - 1));
- }
-
- // Append as many cells from the next line as possible.
- let len = min(row.len(), cols.0 - last_row.len());
-
- // Insert leading spacer when there's not enough room for reflowing wide char.
- let mut cells = if row[Column(len - 1)].flags().contains(Flags::WIDE_CHAR) {
- let mut cells = row.front_split_off(len - 1);
-
- let mut spacer = *template;
- spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
- cells.push(spacer);
-
- cells
- } else {
- row.front_split_off(len)
- };
-
- last_row.append(&mut cells);
-
- if row.is_empty() {
- if i + reversed.len() < self.lines.0 {
- // Add new line and move lines up if we can't pull from history.
- cursor_pos.line = Line(cursor_pos.line.saturating_sub(1));
- new_empty_lines += 1;
- } else if i < self.display_offset {
- // Keep viewport in place if line is outside of the visible area.
- self.display_offset = self.display_offset.saturating_sub(1);
- }
-
- // Don't push line into the new buffer.
- continue;
- } else if let Some(cell) = last_row.last_mut() {
- // Set wrap flag if next line still has cells.
- cell.flags_mut().insert(Flags::WRAPLINE);
- }
-
- reversed.push(row);
- }
-
- // Add padding lines.
- reversed.append(&mut vec![Row::new(cols, template); new_empty_lines]);
-
- // Fill remaining cells and reverse iterator.
- let mut new_raw = Vec::with_capacity(reversed.len());
- for mut row in reversed.drain(..).rev() {
- if row.len() < cols.0 {
- row.grow(cols, template);
- }
- new_raw.push(row);
- }
-
- self.raw.replace_inner(new_raw);
-
- self.display_offset = min(self.display_offset, self.history_size());
- self.cols = cols;
- }
-
- /// Shrink number of columns in each row, reflowing if necessary.
- fn shrink_cols(&mut self, reflow: bool, cols: Column, template: &T) {
- let mut new_raw = Vec::with_capacity(self.raw.len());
- let mut buffered = None;
- for (i, mut row) in self.raw.drain().enumerate().rev() {
- // Append lines left over from previous row.
- if let Some(buffered) = buffered.take() {
- row.append_front(buffered);
- }
-
- loop {
- // Check if reflowing should be performed.
- let mut wrapped = match row.shrink(cols) {
- Some(wrapped) if reflow => wrapped,
- _ => {
- new_raw.push(row);
- break;
- },
- };
-
- // 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) {
- wrapped.insert(0, row[cols - 1]);
-
- let mut spacer = *template;
- spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
- row[cols - 1] = spacer;
- }
-
- // Remove wide char spacer before shrinking.
- let len = wrapped.len();
- if (len == 1 || (len >= 2 && !wrapped[len - 2].flags().contains(Flags::WIDE_CHAR)))
- && wrapped[len - 1].flags().contains(Flags::WIDE_CHAR_SPACER)
- {
- if len == 1 {
- row[cols - 1].flags_mut().insert(Flags::WRAPLINE);
- new_raw.push(row);
- break;
- } else {
- wrapped[len - 2].flags_mut().insert(Flags::WRAPLINE);
- wrapped.truncate(len - 1);
- }
- }
-
- new_raw.push(row);
-
- // Set line as wrapped if cells got removed.
- if let Some(cell) = new_raw.last_mut().and_then(|r| r.last_mut()) {
- cell.flags_mut().insert(Flags::WRAPLINE);
- }
-
- if wrapped
- .last()
- .map(|c| c.flags().contains(Flags::WRAPLINE) && i >= 1)
- .unwrap_or(false)
- && wrapped.len() < cols.0
- {
- // Make sure previous wrap flag doesn't linger around.
- if let Some(cell) = wrapped.last_mut() {
- cell.flags_mut().remove(Flags::WRAPLINE);
- }
-
- // Add removed cells to start of next row.
- buffered = Some(wrapped);
- break;
- } else {
- // Make sure viewport doesn't move if line is outside of the visible area.
- if i < self.display_offset {
- self.display_offset = min(self.display_offset + 1, self.max_scroll_limit);
- }
-
- // Make sure new row is at least as long as new width.
- let occ = wrapped.len();
- if occ < cols.0 {
- wrapped.append(&mut vec![*template; cols.0 - occ]);
- }
- row = Row::from_vec(wrapped, occ);
- }
- }
- }
-
- let mut reversed: Vec<Row<T>> = new_raw.drain(..).rev().collect();
- reversed.truncate(self.max_scroll_limit + self.lines.0);
- self.raw.replace_inner(reversed);
- self.cols = cols;
- }
-
- /// Remove lines from the visible area.
- ///
- /// The behavior in Terminal.app and iTerm.app is to keep the cursor at the
- /// bottom of the screen. This is achieved by pushing history "out the top"
- /// of the terminal window.
- ///
- /// Alacritty takes the same approach.
- fn shrink_lines(&mut self, target: Line, cursor_pos: &mut Point, template: &T) {
- // Scroll up to keep cursor inside the window.
- let required_scrolling = (cursor_pos.line + 1).saturating_sub(target.0);
- if required_scrolling > 0 {
- self.scroll_up(&(Line(0)..self.lines), Line(required_scrolling), template);
- }
-
- self.selection = None;
- self.raw.rotate((self.lines - target).0 as isize);
- self.raw.shrink_visible_lines(target);
- self.lines = target;
- }
-
#[inline]
- pub fn scroll_down(&mut self, region: &Range<Line>, positions: Line, template: &T) {
- let num_lines = self.num_lines().0;
- let num_cols = self.num_cols().0;
-
+ pub fn scroll_down(&mut self, region: &Range<Line>, positions: Line, template: T) {
// Whether or not there is a scrolling region active, as long as it
// starts at the top, we can do a full rotation which just involves
// changing the start index.
@@ -469,10 +256,6 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
// Rotate the entire line buffer. If there's a scrolling region
// active, the bottom lines are restored in the next step.
self.raw.rotate_up(*positions);
- self.selection = self
- .selection
- .take()
- .and_then(|s| s.rotate(num_lines, num_cols, region, -(*positions as isize)));
self.decrease_scroll_limit(*positions);
@@ -484,22 +267,16 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
// Finally, reset recycled lines.
for i in IndexRange(Line(0)..positions) {
- self.raw[i].reset(&template);
+ self.raw[i].reset(template);
}
} else {
- // Rotate selection to track content.
- self.selection = self
- .selection
- .take()
- .and_then(|s| s.rotate(num_lines, num_cols, region, -(*positions as isize)));
-
// Subregion rotation.
for line in IndexRange((region.start + positions)..region.end).rev() {
self.raw.swap_lines(line, line - positions);
}
for line in IndexRange(region.start..(region.start + positions)) {
- self.raw[line].reset(&template);
+ self.raw[line].reset(template);
}
}
}
@@ -507,9 +284,8 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
/// Move lines at the bottom towards the top.
///
/// This is the performance-sensitive part of scrolling.
- pub fn scroll_up(&mut self, region: &Range<Line>, positions: Line, template: &T) {
+ pub fn scroll_up(&mut self, region: &Range<Line>, positions: Line, template: T) {
let num_lines = self.num_lines().0;
- let num_cols = self.num_cols().0;
if region.start == Line(0) {
// Update display offset when not pinned to active area.
@@ -522,10 +298,6 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
// Rotate the entire line buffer. If there's a scrolling region
// active, the bottom lines are restored in the next step.
self.raw.rotate(-(*positions as isize));
- self.selection = self
- .selection
- .take()
- .and_then(|s| s.rotate(num_lines, num_cols, region, *positions as isize));
// This next loop swaps "fixed" lines outside of a scroll region
// back into place after the rotation. The work is done in buffer-
@@ -541,15 +313,9 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
//
// Recycled lines are just above the end of the scrolling region.
for i in 0..*positions {
- self.raw[i + fixed_lines].reset(&template);
+ self.raw[i + fixed_lines].reset(template);
}
} else {
- // Rotate selection to track content.
- self.selection = self
- .selection
- .take()
- .and_then(|s| s.rotate(num_lines, num_cols, region, *positions as isize));
-
// Subregion rotation.
for line in IndexRange(region.start..(region.end - positions)) {
self.raw.swap_lines(line, line + positions);
@@ -557,12 +323,12 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
// Clear reused lines.
for line in IndexRange((region.end - positions)..region.end) {
- self.raw[line].reset(&template);
+ self.raw[line].reset(template);
}
}
}
- pub fn clear_viewport(&mut self, template: &T) {
+ pub fn clear_viewport(&mut self, template: T) {
// Determine how many lines to scroll up by.
let end = Point { line: 0, col: self.num_cols() };
let mut iter = self.iter_from(end);
@@ -583,12 +349,12 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
// Reset rotated lines.
for i in positions.0..self.lines.0 {
- self.raw[i].reset(&template);
+ self.raw[i].reset(template);
}
}
/// Completely reset the grid state.
- pub fn reset(&mut self, template: &T) {
+ pub fn reset(&mut self, template: T) {
self.clear_history();
// Reset all visible lines.
@@ -596,8 +362,9 @@ impl<T: GridCell + PartialEq + Copy> Grid<T> {
self.raw[row].reset(template);
}
+ self.saved_cursor = Cursor::default();
+ self.cursor = Cursor::default();
self.display_offset = 0;
- self.selection = None;
}
}
@@ -637,7 +404,7 @@ impl<T> Grid<T> {
/// This is used only for initializing after loading ref-tests.
#[inline]
- pub fn initialize_all(&mut self, template: &T)
+ pub fn initialize_all(&mut self, template: T)
where
T: Copy + GridCell,
{
@@ -663,6 +430,12 @@ impl<T> Grid<T> {
pub fn display_offset(&self) -> usize {
self.display_offset
}
+
+ #[inline]
+ pub fn cursor_cell(&mut self) -> &mut T {
+ let point = self.cursor.point;
+ &mut self[&point]
+ }
}
pub struct GridIterator<'a, T> {
diff --git a/alacritty_terminal/src/grid/resize.rs b/alacritty_terminal/src/grid/resize.rs
new file mode 100644
index 00000000..796c5859
--- /dev/null
+++ b/alacritty_terminal/src/grid/resize.rs
@@ -0,0 +1,274 @@
+//! Grid resize and reflow.
+
+use std::cmp::{min, Ordering};
+
+use crate::index::{Column, Line};
+use crate::term::cell::Flags;
+
+use crate::grid::row::Row;
+use crate::grid::{Grid, GridCell};
+
+impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
+ /// Resize the grid's width and/or height.
+ pub fn resize(&mut self, reflow: bool, lines: Line, cols: Column) {
+ match self.lines.cmp(&lines) {
+ Ordering::Less => self.grow_lines(lines),
+ Ordering::Greater => self.shrink_lines(lines),
+ Ordering::Equal => (),
+ }
+
+ match self.cols.cmp(&cols) {
+ Ordering::Less => self.grow_cols(cols, reflow),
+ Ordering::Greater => self.shrink_cols(cols, reflow),
+ Ordering::Equal => (),
+ }
+ }
+
+ /// Add lines to the visible area.
+ ///
+ /// 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(&mut self, new_line_count: Line) {
+ let lines_added = new_line_count - self.lines;
+
+ // Need to resize before updating buffer.
+ self.raw.grow_visible_lines(new_line_count, Row::new(self.cols, T::default()));
+ self.lines = new_line_count;
+
+ let history_size = self.history_size();
+ let from_history = min(history_size, lines_added.0);
+
+ // Move existing lines up for every line that couldn't be pulled from history.
+ if from_history != lines_added.0 {
+ let delta = lines_added - from_history;
+ self.scroll_up(&(Line(0)..new_line_count), delta, T::default());
+ }
+
+ // 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);
+ }
+
+ /// Remove lines from the visible area.
+ ///
+ /// The behavior in Terminal.app and iTerm.app is to keep the cursor at the
+ /// bottom of the screen. This is achieved by pushing history "out the top"
+ /// of the terminal window.
+ ///
+ /// Alacritty takes the same approach.
+ fn shrink_lines(&mut self, target: Line) {
+ // Scroll up to keep content inside the window.
+ let required_scrolling = (self.cursor.point.line + 1).saturating_sub(target.0);
+ if required_scrolling > 0 {
+ self.scroll_up(&(Line(0)..self.lines), Line(required_scrolling), T::default());
+
+ // Clamp cursors to the new viewport size.
+ self.saved_cursor.point.line = min(self.saved_cursor.point.line, target - 1);
+ self.cursor.point.line = min(self.cursor.point.line, target - 1);
+ }
+
+ self.raw.rotate((self.lines - target).0 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, cols: Column, reflow: bool) {
+ // Check if a row needs to be wrapped.
+ let should_reflow = |row: &Row<T>| -> bool {
+ let len = Column(row.len());
+ reflow && len < cols && row[len - 1].flags().contains(Flags::WRAPLINE)
+ };
+
+ self.cols = cols;
+
+ let mut reversed: Vec<Row<T>> = Vec::with_capacity(self.raw.len());
+ let mut new_empty_lines = 0;
+
+ let mut rows = self.raw.take_all();
+
+ for (i, mut row) in rows.drain(..).enumerate().rev() {
+ // Check if reflowing should be performed.
+ let last_row = match reversed.last_mut() {
+ Some(last_row) if should_reflow(last_row) => last_row,
+ _ => {
+ reversed.push(row);
+ continue;
+ },
+ };
+
+ // Remove wrap flag before appending additional cells.
+ if let Some(cell) = last_row.last_mut() {
+ cell.flags_mut().remove(Flags::WRAPLINE);
+ }
+
+ // Remove leading spacers when reflowing wide char to the previous line.
+ let mut last_len = last_row.len();
+ if last_len >= 2
+ && !last_row[Column(last_len - 2)].flags().contains(Flags::WIDE_CHAR)
+ && last_row[Column(last_len - 1)].flags().contains(Flags::WIDE_CHAR_SPACER)
+ {
+ last_row.shrink(Column(last_len - 1));
+ last_len -= 1;
+ }
+
+ // Don't try to pull more cells from the next line than available.
+ let len = min(row.len(), cols.0 - last_len);
+
+ // Insert leading spacer when there's not enough room for reflowing wide char.
+ let mut cells = if row[Column(len - 1)].flags().contains(Flags::WIDE_CHAR) {
+ let mut cells = row.front_split_off(len - 1);
+
+ let mut spacer = T::default();
+ spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
+ cells.push(spacer);
+
+ cells
+ } else {
+ row.front_split_off(len)
+ };
+
+ // Reflow cells to previous row.
+ last_row.append(&mut cells);
+
+ if row.is_empty() {
+ if i + reversed.len() < self.lines.0 {
+ // Add new line and move everything up if we can't pull from history.
+ self.saved_cursor.point.line.0 = self.saved_cursor.point.line.saturating_sub(1);
+ self.cursor.point.line.0 = self.cursor.point.line.saturating_sub(1);
+ new_empty_lines += 1;
+ } else {
+ // Since we removed a line, rotate down the viewport.
+ self.display_offset = self.display_offset.saturating_sub(1);
+ }
+
+ // Don't push line into the new buffer.
+ continue;
+ } else if let Some(cell) = last_row.last_mut() {
+ // Set wrap flag if next line still has cells.
+ cell.flags_mut().insert(Flags::WRAPLINE);
+ }
+
+ reversed.push(row);
+ }
+
+ // Add all new empty lines in one go.
+ reversed.append(&mut vec![Row::new(cols, T::default()); new_empty_lines]);
+
+ // 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, T::default());
+ }
+ new_raw.push(row);
+ }
+
+ self.raw.replace_inner(new_raw);
+
+ // Clamp display offset in case lines above it got merged.
+ self.display_offset = min(self.display_offset, self.history_size());
+ }
+
+ /// Shrink number of columns in each row, reflowing if necessary.
+ fn shrink_cols(&mut self, cols: Column, reflow: bool) {
+ self.cols = cols;
+
+ let mut rows = self.raw.take_all();
+
+ let mut new_raw = Vec::with_capacity(self.raw.len());
+ let mut buffered: Option<Vec<T>> = None;
+
+ for (i, mut row) in rows.drain(..).enumerate().rev() {
+ // Append lines left over from the previous row.
+ if let Some(buffered) = buffered.take() {
+ row.append_front(buffered);
+ }
+
+ loop {
+ // Remove all cells which require reflowing.
+ let mut wrapped = match row.shrink(cols) {
+ Some(wrapped) if reflow => wrapped,
+ _ => {
+ new_raw.push(row);
+ break;
+ },
+ };
+
+ // 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) {
+ wrapped.insert(0, row[cols - 1]);
+
+ let mut spacer = T::default();
+ spacer.flags_mut().insert(Flags::WIDE_CHAR_SPACER);
+ row[cols - 1] = spacer;
+ }
+
+ // Remove wide char spacer before shrinking.
+ let len = wrapped.len();
+ if (len == 1 || (len >= 2 && !wrapped[len - 2].flags().contains(Flags::WIDE_CHAR)))
+ && wrapped[len - 1].flags().contains(Flags::WIDE_CHAR_SPACER)
+ {
+ if len == 1 {
+ // Delete the wrapped content if it contains only a leading spacer.
+ row[cols - 1].flags_mut().insert(Flags::WRAPLINE);
+ new_raw.push(row);
+ break;
+ } else {
+ // Remove the leading spacer from the end of the wrapped row.
+ wrapped[len - 2].flags_mut().insert(Flags::WRAPLINE);
+ wrapped.truncate(len - 1);
+ }
+ }
+
+ new_raw.push(row);
+
+ // Set line as wrapped if cells got removed.
+ if let Some(cell) = new_raw.last_mut().and_then(|r| r.last_mut()) {
+ cell.flags_mut().insert(Flags::WRAPLINE);
+ }
+
+ if wrapped
+ .last()
+ .map(|c| c.flags().contains(Flags::WRAPLINE) && i >= 1)
+ .unwrap_or(false)
+ && wrapped.len() < cols.0
+ {
+ // Make sure previous wrap flag doesn't linger around.
+ if let Some(cell) = wrapped.last_mut() {
+ cell.flags_mut().remove(Flags::WRAPLINE);
+ }
+
+ // Add removed cells to start of next row.
+ buffered = Some(wrapped);
+ break;
+ } else {
+ // Since we added a line, rotate up the viewport.
+ if i < self.display_offset {
+ self.display_offset = min(self.display_offset + 1, self.max_scroll_limit);
+ }
+
+ // Make sure new row is at least as long as new width.
+ let occ = wrapped.len();
+ if occ < cols.0 {
+ wrapped.append(&mut vec![T::default(); cols.0 - occ]);
+ }
+ row = Row::from_vec(wrapped, occ);
+ }
+ }
+ }
+
+ // 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);
+ self.raw.replace_inner(reversed);
+
+ // Wrap content going beyond new width if necessary.
+ self.saved_cursor.point.col = min(self.saved_cursor.point.col, self.cols - 1);
+ self.cursor.point.col = min(self.cursor.point.col, self.cols - 1);
+ }
+}
diff --git a/alacritty_terminal/src/grid/row.rs b/alacritty_terminal/src/grid/row.rs
index 22a10625..b5248ad7 100644
--- a/alacritty_terminal/src/grid/row.rs
+++ b/alacritty_terminal/src/grid/row.rs
@@ -43,20 +43,20 @@ impl<T: PartialEq> PartialEq for Row<T> {
}
impl<T: Copy> Row<T> {
- pub fn new(columns: Column, template: &T) -> Row<T>
+ pub fn new(columns: Column, template: T) -> Row<T>
where
T: GridCell,
{
let occ = if template.is_empty() { 0 } else { columns.0 };
- Row { inner: vec![*template; columns.0], occ }
+ Row { inner: vec![template; columns.0], occ }
}
- pub fn grow(&mut self, cols: Column, template: &T) {
+ pub fn grow(&mut self, cols: Column, template: T) {
if self.inner.len() >= cols.0 {
return;
}
- self.inner.append(&mut vec![*template; cols.0 - self.len()]);
+ self.inner.append(&mut vec![template; cols.0 - self.len()]);
}
pub fn shrink(&mut self, cols: Column) -> Option<Vec<T>>
@@ -83,14 +83,12 @@ impl<T: Copy> Row<T> {
/// Reset all cells in the row to the `template` cell.
#[inline]
- pub fn reset(&mut self, template: &T)
+ pub fn reset(&mut self, template: T)
where
T: GridCell + PartialEq,
{
debug_assert!(!self.inner.is_empty());
- let template = *template;
-
// Mark all cells as dirty if template cell changed.
let len = self.inner.len();
if !self.inner[len - 1].fast_eq(template) {
diff --git a/alacritty_terminal/src/grid/storage.rs b/alacritty_terminal/src/grid/storage.rs
index 4820036f..4b7ca41a 100644
--- a/alacritty_terminal/src/grid/storage.rs
+++ b/alacritty_terminal/src/grid/storage.rs
@@ -1,6 +1,6 @@
use std::cmp::{max, PartialEq};
+use std::mem;
use std::ops::{Index, IndexMut};
-use std::vec::Drain;
use serde::{Deserialize, Serialize};
@@ -142,7 +142,7 @@ impl<T> Storage<T> {
/// Dynamically grow the storage buffer at runtime.
#[inline]
- pub fn initialize(&mut self, additional_rows: usize, template: &T, cols: Column)
+ pub fn initialize(&mut self, additional_rows: usize, template: T, cols: Column)
where
T: GridCell + Copy,
{
@@ -238,18 +238,27 @@ impl<T> Storage<T> {
self.zero = (self.zero + count) % self.inner.len();
}
- /// Drain all rows in the grid.
- pub fn drain(&mut self) -> Drain<'_, Row<T>> {
- self.truncate();
- self.inner.drain(..)
- }
-
/// Update the raw storage buffer.
+ #[inline]
pub fn replace_inner(&mut self, vec: Vec<Row<T>>) {
self.len = vec.len();
self.inner = vec;
self.zero = 0;
}
+
+ /// Remove all rows from storage.
+ #[inline]
+ pub fn take_all(&mut self) -> Vec<Row<T>> {
+ self.truncate();
+
+ let mut buffer = Vec::new();
+
+ mem::swap(&mut buffer, &mut self.inner);
+ self.zero = 0;
+ self.len = 0;
+
+ buffer
+ }
}
impl<T> Index<usize> for Storage<T> {
@@ -315,7 +324,7 @@ mod tests {
#[test]
fn with_capacity() {
- let storage = Storage::with_capacity(Line(3), Row::new(Column(0), &' '));
+ let storage = Storage::with_capacity(Line(3), Row::new(Column(0), ' '));
assert_eq!(storage.inner.len(), 3);
assert_eq!(storage.len, 3);
@@ -325,33 +334,33 @@ mod tests {
#[test]
fn indexing() {
- let mut storage = Storage::with_capacity(Line(3), Row::new(Column(0), &' '));
+ let mut storage = Storage::with_capacity(Line(3), Row::new(Column(0), ' '));
- storage[0] = Row::new(Column(1), &'0');
- storage[1] = Row::new(Column(1), &'1');
- storage[2] = Row::new(Column(1), &'2');
+ storage[0] = Row::new(Column(1), '0');
+ storage[1] = Row::new(Column(1), '1');
+ storage[2] = Row::new(Column(1), '2');
- assert_eq!(storage[0], Row::new(Column(1), &'0'));
- assert_eq!(storage[1], Row::new(Column(1), &'1'));
- assert_eq!(storage[2], Row::new(Column(1), &'2'));
+ assert_eq!(storage[0], Row::new(Column(1), '0'));
+ assert_eq!(storage[1], Row::new(Column(1), '1'));
+ assert_eq!(storage[2], Row::new(Column(1), '2'));
storage.zero += 1;
- assert_eq!(storage[0], Row::new(Column(1), &'1'));
- assert_eq!(storage[1], Row::new(Column(1), &'2'));
- assert_eq!(storage[2], Row::new(Column(1), &'0'));
+ assert_eq!(storage[0], Row::new(Column(1), '1'));
+ assert_eq!(storage[1], Row::new(Column(1), '2'));
+ assert_eq!(storage[2], Row::new(Column(1), '0'));
}
#[test]
#[should_panic]
fn indexing_above_inner_len() {
- let storage = Storage::with_capacity(Line(1), Row::new(Column(0), &' '));
+ let storage = Storage::with_capacity(Line(1), Row::new(Column(0), ' '));
let _ = &storage[2];
}
#[test]
fn rotate() {
- let mut storage = Storage::with_capacity(Line(3), Row::new(Column(0), &' '));
+ let mut storage = Storage::with_capacity(Line(3), Row::new(Column(0), ' '));
storage.rotate(2);
assert_eq!(storage.zero, 2);
storage.shrink_lines(2);
@@ -376,9 +385,9 @@ mod tests {
// Setup storage area
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'-'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '-'),
],
zero: 0,
visible_lines: Line(3),
@@ -386,15 +395,15 @@ mod tests {
};
// Grow buffer
- storage.grow_visible_lines(Line(4), Row::new(Column(1), &'-'));
+ storage.grow_visible_lines(Line(4), Row::new(Column(1), '-'));
// Make sure the result is correct
let expected = Storage {
inner: vec![
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'-'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '-'),
],
zero: 1,
visible_lines: Line(4),
@@ -422,9 +431,9 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
],
zero: 1,
visible_lines: Line(3),
@@ -432,15 +441,15 @@ mod tests {
};
// Grow buffer.
- storage.grow_visible_lines(Line(4), Row::new(Column(1), &'-'));
+ storage.grow_visible_lines(Line(4), Row::new(Column(1), '-'));
// Make sure the result is correct.
let expected = Storage {
inner: vec![
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
],
zero: 2,
visible_lines: Line(4),
@@ -467,9 +476,9 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
],
zero: 1,
visible_lines: Line(3),
@@ -482,9 +491,9 @@ mod tests {
// Make sure the result is correct.
let expected = Storage {
inner: vec![
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
],
zero: 1,
visible_lines: Line(2),
@@ -511,9 +520,9 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
],
zero: 0,
visible_lines: Line(3),
@@ -526,9 +535,9 @@ mod tests {
// Make sure the result is correct.
let expected = Storage {
inner: vec![
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
],
zero: 0,
visible_lines: Line(2),
@@ -561,12 +570,12 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(6),
@@ -579,12 +588,12 @@ mod tests {
// Make sure the result is correct.
let expected = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(2),
@@ -613,12 +622,12 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(1),
@@ -630,7 +639,7 @@ mod tests {
// Make sure the result is correct.
let expected = Storage {
- inner: vec![Row::new(Column(1), &'0'), Row::new(Column(1), &'1')],
+ inner: vec![Row::new(Column(1), '0'), Row::new(Column(1), '1')],
zero: 0,
visible_lines: Line(1),
len: 2,
@@ -655,9 +664,9 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '0'),
],
zero: 2,
visible_lines: Line(1),
@@ -669,7 +678,7 @@ mod tests {
// Make sure the result is correct.
let expected = Storage {
- inner: vec![Row::new(Column(1), &'0'), Row::new(Column(1), &'1')],
+ inner: vec![Row::new(Column(1), '0'), Row::new(Column(1), '1')],
zero: 0,
visible_lines: Line(1),
len: 2,
@@ -709,12 +718,12 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(0),
@@ -727,12 +736,12 @@ mod tests {
// Make sure the result after shrinking is correct.
let shrinking_expected = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(0),
@@ -743,18 +752,18 @@ mod tests {
assert_eq!(storage.len, shrinking_expected.len);
// Grow buffer.
- storage.grow_lines(4, Row::new(Column(1), &'-'));
+ storage.grow_lines(4, Row::new(Column(1), '-'));
// Make sure the result after shrinking is correct.
let growing_expected = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 3,
visible_lines: Line(0),
@@ -770,12 +779,12 @@ mod tests {
// Setup storage area.
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'4'),
- Row::new(Column(1), &'5'),
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '4'),
+ Row::new(Column(1), '5'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
],
zero: 2,
visible_lines: Line(0),
@@ -784,18 +793,18 @@ mod tests {
// Initialize additional lines.
let init_size = 3;
- storage.initialize(init_size, &'-', Column(1));
+ storage.initialize(init_size, '-', Column(1));
// Make sure the lines are present and at the right location.
let expected_init_size = std::cmp::max(init_size, MAX_CACHE_SIZE);
- let mut expected_inner = vec![Row::new(Column(1), &'4'), Row::new(Column(1), &'5')];
- expected_inner.append(&mut vec![Row::new(Column(1), &'-'); expected_init_size]);
+ let mut expected_inner = vec![Row::new(Column(1), '4'), Row::new(Column(1), '5')];
+ expected_inner.append(&mut vec![Row::new(Column(1), '-'); expected_init_size]);
expected_inner.append(&mut vec![
- Row::new(Column(1), &'0'),
- Row::new(Column(1), &'1'),
- Row::new(Column(1), &'2'),
- Row::new(Column(1), &'3'),
+ Row::new(Column(1), '0'),
+ Row::new(Column(1), '1'),
+ Row::new(Column(1), '2'),
+ Row::new(Column(1), '3'),
]);
let expected_storage = Storage {
inner: expected_inner,
@@ -813,9 +822,9 @@ mod tests {
fn rotate_wrap_zero() {
let mut storage = Storage {
inner: vec![
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'-'),
- Row::new(Column(1), &'-'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '-'),
+ Row::new(Column(1), '-'),
],
zero: 2,
visible_lines: Line(0),
diff --git a/alacritty_terminal/src/grid/tests.rs b/alacritty_terminal/src/grid/tests.rs
index ef011d16..04400afc 100644
--- a/alacritty_terminal/src/grid/tests.rs
+++ b/alacritty_terminal/src/grid/tests.rs
@@ -79,7 +79,7 @@ fn scroll_up() {
grid[Line(i)][Column(0)] = i;
}
- grid.scroll_up(&(Line(0)..Line(10)), Line(2), &0);
+ grid.scroll_up(&(Line(0)..Line(10)), Line(2), 0);
assert_eq!(grid[Line(0)][Column(0)], 2);
assert_eq!(grid[Line(0)].occ, 1);
@@ -111,7 +111,7 @@ fn scroll_down() {
grid[Line(i)][Column(0)] = i;
}
- grid.scroll_down(&(Line(0)..Line(10)), Line(2), &0);
+ grid.scroll_down(&(Line(0)..Line(10)), Line(2), 0);
assert_eq!(grid[Line(0)][Column(0)], 0); // was 8.
assert_eq!(grid[Line(0)].occ, 0);
@@ -183,7 +183,7 @@ fn shrink_reflow() {
grid[Line(0)][Column(3)] = cell('4');
grid[Line(0)][Column(4)] = cell('5');
- grid.resize(true, Line(1), Column(2), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(1), Column(2));
assert_eq!(grid.len(), 3);
@@ -209,8 +209,8 @@ fn shrink_reflow_twice() {
grid[Line(0)][Column(3)] = cell('4');
grid[Line(0)][Column(4)] = cell('5');
- grid.resize(true, Line(1), Column(4), &mut Point::new(Line(0), Column(0)), &Cell::default());
- grid.resize(true, Line(1), Column(2), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(1), Column(4));
+ grid.resize(true, Line(1), Column(2));
assert_eq!(grid.len(), 3);
@@ -236,7 +236,7 @@ fn shrink_reflow_empty_cell_inside_line() {
grid[Line(0)][Column(3)] = cell('4');
grid[Line(0)][Column(4)] = Cell::default();
- grid.resize(true, Line(1), Column(2), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(1), Column(2));
assert_eq!(grid.len(), 2);
@@ -248,7 +248,7 @@ fn shrink_reflow_empty_cell_inside_line() {
assert_eq!(grid[0][Column(0)], cell('3'));
assert_eq!(grid[0][Column(1)], cell('4'));
- grid.resize(true, Line(1), Column(1), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(1), Column(1));
assert_eq!(grid.len(), 4);
@@ -273,7 +273,7 @@ fn grow_reflow() {
grid[Line(1)][Column(0)] = cell('3');
grid[Line(1)][Column(1)] = Cell::default();
- grid.resize(true, Line(2), Column(3), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(2), Column(3));
assert_eq!(grid.len(), 2);
@@ -299,7 +299,7 @@ fn grow_reflow_multiline() {
grid[Line(2)][Column(0)] = cell('5');
grid[Line(2)][Column(1)] = cell('6');
- grid.resize(true, Line(3), Column(6), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(true, Line(3), Column(6));
assert_eq!(grid.len(), 3);
@@ -330,7 +330,7 @@ fn grow_reflow_disabled() {
grid[Line(1)][Column(0)] = cell('3');
grid[Line(1)][Column(1)] = Cell::default();
- grid.resize(false, Line(2), Column(3), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(false, Line(2), Column(3));
assert_eq!(grid.len(), 2);
@@ -354,7 +354,7 @@ fn shrink_reflow_disabled() {
grid[Line(0)][Column(3)] = cell('4');
grid[Line(0)][Column(4)] = cell('5');
- grid.resize(false, Line(1), Column(2), &mut Point::new(Line(0), Column(0)), &Cell::default());
+ grid.resize(false, Line(1), Column(2));
assert_eq!(grid.len(), 1);