aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2018-02-15 18:35:49 -0800
committerJoe Wilm <joe@jwilm.com>2018-03-07 09:47:21 -0800
commitcfc4ebfd6a2fb39ae98ba37c215a4a9141865e01 (patch)
tree604b757b2d0f2754359a73b2bf682e6e5d0650ed
parent6d1d41f8c77968547b43603db51a5efeac21a400 (diff)
downloadalacritty-cfc4ebfd6a2fb39ae98ba37c215a4a9141865e01.tar.gz
alacritty-cfc4ebfd6a2fb39ae98ba37c215a4a9141865e01.zip
checkpoint: very basic scrolling works
Things that do not work - Limiting how far back in the buffer it's possible to scroll - Selections (need to transform to buffer offsets)
-rw-r--r--src/event.rs4
-rw-r--r--src/grid/mod.rs200
-rw-r--r--src/grid/row.rs18
-rw-r--r--src/grid/storage.rs40
-rw-r--r--src/input.rs28
-rw-r--r--src/term/mod.rs187
6 files changed, 309 insertions, 168 deletions
diff --git a/src/event.rs b/src/event.rs
index 8c4107ca..d0d9a8da 100644
--- a/src/event.rs
+++ b/src/event.rs
@@ -55,6 +55,10 @@ impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
*self.size_info
}
+ fn scroll(&mut self, count: isize) {
+ self.terminal.scroll_display(count);
+ }
+
fn copy_selection(&self, buffer: ::copypasta::Buffer) {
if let Some(ref selection) = *self.selection {
selection.to_span(self.terminal)
diff --git a/src/grid/mod.rs b/src/grid/mod.rs
index f0bd2f6f..820cd9e2 100644
--- a/src/grid/mod.rs
+++ b/src/grid/mod.rs
@@ -12,17 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//! A generic 2d grid implementation optimized for use in a terminal.
-//!
-//! The current implementation uses a vector of vectors to store cell data.
-//! Reimplementing the store as a single contiguous vector may be desirable in
-//! the future. Rotation and indexing would need to be reconsidered at that
-//! time; rotation currently reorganize Vecs in the lines Vec, and indexing with
-//! ranges is currently supported.
-
-use std::cmp::Ordering;
-use std::iter::IntoIterator;
-use std::ops::{Deref, Range, RangeTo, RangeFrom, RangeFull, Index, IndexMut};
+//! A specialized 2d grid implementation optimized for use in a terminal.
+
+use std::cmp::{max, Ordering};
+use std::ops::{Deref, Range, Index, IndexMut, RangeTo, RangeFrom, RangeFull};
use index::{self, Point, Line, Column, IndexRange, RangeInclusive};
@@ -36,7 +29,7 @@ mod storage;
use self::storage::Storage;
/// Lines to keep in scrollback buffer
-const SCROLLBACK_LINES: usize = 100_000;
+const SCROLLBACK_LINES: usize = 10_000;
/// Convert a type to a linear index range.
pub trait ToRange {
@@ -105,8 +98,12 @@ pub struct GridIterator<'a, T: 'a> {
}
impl<T: Copy + Clone> Grid<T> {
+ pub fn scroll_display(&mut self, count: isize) {
+ self.display_offset = max((self.display_offset as isize) + count, 0isize) as usize;
+ }
+
pub fn new(lines: index::Line, cols: index::Column, template: T) -> Grid<T> {
- let mut raw = Storage::with_capacity(*lines + SCROLLBACK_LINES);
+ let mut raw = Storage::with_capacity(*lines + SCROLLBACK_LINES, lines);
let template_row = Row::new(cols, &template);
// Allocate all lines in the buffer, including scrollback history
@@ -125,6 +122,7 @@ impl<T: Copy + Clone> Grid<T> {
template_row,
template,
temp: Vec::new(),
+ display_offset: 0,
}
}
@@ -147,12 +145,23 @@ impl<T: Copy + Clone> Grid<T> {
}
}
- fn grow_lines(&mut self, lines: index::Line) {
- for _ in IndexRange(self.num_lines()..lines) {
- self.raw.push(self.template_row.clone());
- }
+ /// Add lines to the visible area
+ ///
+ /// The behavior in Terminal.app and iTerm.app is to keep the cursor at the
+ /// bottom of the screen as long as there is scrollback available. Once
+ /// scrollback is exhausted, new lines are simply added to the bottom of the
+ /// screen.
+ ///
+ /// Alacritty takes a different approach. Rather than trying to move with
+ /// the scrollback, we simply pull additional lines from the back of the
+ /// buffer in order to populate the new area.
+ fn grow_lines(&mut self, target: index::Line) {
+ let delta = target - self.lines;
- self.lines = lines;
+ self.raw.set_visible_lines(target);
+ self.lines = target;
+
+ self.scroll_up(&(Line(0)..target), delta);
}
fn grow_cols(&mut self, cols: index::Column) {
@@ -167,6 +176,37 @@ impl<T: Copy + Clone> Grid<T> {
self.template_row.grow(cols, &self.template);
}
+ /// 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: index::Line) {
+ // TODO handle disabled scrollback
+ // while index::Line(self.raw.len()) != lines {
+ // self.raw.pop();
+ // }
+
+ let prev = self.lines;
+
+ self.raw.rotate(*prev as isize - *target as isize);
+ self.raw.set_visible_lines(target);
+ self.lines = target;
+ }
+
+ /// Convert a Line index (active region) to a buffer offset
+ ///
+ /// # Panics
+ ///
+ /// This method will panic if `Line` is larger than the grid dimensions
+ pub fn line_to_offset(&self, line: index::Line) -> usize {
+ assert!(line < self.num_lines());
+
+ *(self.num_lines() - line - 1)
+ }
+
#[inline]
pub fn scroll_down(&mut self, region: &Range<index::Line>, positions: index::Line) {
// Whether or not there is a scrolling region active, as long as it
@@ -177,12 +217,12 @@ impl<T: Copy + Clone> Grid<T> {
if region.start == Line(0) {
// 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.raw.rotate_up(*positions);
// Now, restore any scroll region lines
for i in IndexRange(region.end .. self.num_lines()) {
// First do the swap
- self.raw.swap(*i, *i + *positions);
+ self.raw.swap_lines(i, i + positions);
}
// Finally, reset recycled lines
@@ -192,7 +232,7 @@ impl<T: Copy + Clone> Grid<T> {
} else {
// Subregion rotation
for line in IndexRange((region.start + positions)..region.end).rev() {
- self.swap_lines(line, line - positions);
+ self.raw.swap_lines(line, line - positions);
}
for line in IndexRange(region.start .. (region.start + positions)) {
@@ -214,29 +254,29 @@ impl<T: Copy + Clone> 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.raw.rotate(-(*positions as isize));
// Now, restore any lines outside the scroll region
for idx in (*region.end .. *self.num_lines()).rev() {
// First do the swap
- self.raw.swap(idx, idx - *positions);
+ self.raw.swap_lines(Line(idx), Line(idx) - positions);
}
// Finally, reset recycled lines
//
// Recycled lines are just above the end of the scrolling region.
for i in 0..*positions {
- self.raw[*region.end - i - 1].reset(&self.template_row);
+ self.raw[region.end - i - 1].reset(&self.template_row);
}
} else {
// Subregion rotation
for line in IndexRange(region.start..(region.end - positions)) {
- self.swap_lines(line, line + positions);
+ self.raw.swap_lines(line, line + positions);
}
// Clear reused lines
for line in IndexRange((region.end - positions) .. region.end) {
- self.raw[*line].reset(&self.template_row);
+ self.raw[line].reset(&self.template_row);
}
}
}
@@ -248,6 +288,10 @@ impl<T> Grid<T> {
self.lines
}
+ pub fn display_iter(&self) -> DisplayIter<T> {
+ DisplayIter::new(self)
+ }
+
#[inline]
pub fn num_cols(&self) -> index::Column {
self.cols
@@ -265,22 +309,14 @@ impl<T> Grid<T> {
self.lines > point.line && self.cols > point.col
}
- /// Swap two lines in the grid
- ///
- /// This could have used slice::swap internally, but we are able to have
- /// better error messages by doing the bounds checking ourselves.
- #[inline]
- pub fn swap_lines(&mut self, src: index::Line, dst: index::Line) {
- self.raw.swap(*src, *dst);
- }
-
- fn shrink_lines(&mut self, lines: index::Line) {
- while index::Line(self.raw.len()) != lines {
- self.raw.pop();
- }
-
- self.lines = lines;
- }
+ // /// Swap two lines in the grid
+ // ///
+ // /// This could have used slice::swap internally, but we are able to have
+ // /// better error messages by doing the bounds checking ourselves.
+ // #[inline]
+ // pub fn swap_lines(&mut self, src: index::Line, dst: index::Line) {
+ // self.raw.swap(*src, *dst);
+ // }
fn shrink_cols(&mut self, cols: index::Column) {
for row in self.raw.iter_mut() {
@@ -335,12 +371,22 @@ impl<'a, T> BidirectionalIterator for GridIterator<'a, T> {
}
}
+/// Index active region by line
impl<T> Index<index::Line> for Grid<T> {
type Output = Row<T>;
#[inline]
fn index(&self, index: index::Line) -> &Row<T> {
- let index = self.lines.0 - index.0;
+ &self.raw[index]
+ }
+}
+
+/// Index with buffer offset
+impl<T> Index<usize> for Grid<T> {
+ type Output = Row<T>;
+
+ #[inline]
+ fn index(&self, index: usize) -> &Row<T> {
&self.raw[index]
}
}
@@ -348,7 +394,6 @@ impl<T> Index<index::Line> for Grid<T> {
impl<T> IndexMut<index::Line> for Grid<T> {
#[inline]
fn index_mut(&mut self, index: index::Line) -> &mut Row<T> {
- let index = self.lines.0 - index.0;
&mut self.raw[index]
}
}
@@ -369,9 +414,9 @@ impl<'point, T> IndexMut<&'point Point> for Grid<T> {
}
}
-// =================================================================================================
-// Regions =========================================================================================
-// =================================================================================================
+// -------------------------------------------------------------------------------------------------
+// REGIONS
+// -------------------------------------------------------------------------------------------------
/// A subset of lines in the grid
///
@@ -533,7 +578,7 @@ impl<'a, T> Iterator for RegionIter<'a, T> {
if self.cur < self.end {
let index = self.cur;
self.cur += 1;
- Some(&self.raw[*index])
+ Some(&self.raw[index])
} else {
None
}
@@ -547,10 +592,67 @@ impl<'a, T> Iterator for RegionIterMut<'a, T> {
let index = self.cur;
self.cur += 1;
unsafe {
- Some(&mut *(&mut self.raw[index.0] as *mut _))
+ Some(&mut *(&mut self.raw[index] as *mut _))
}
} else {
None
}
}
}
+
+// -------------------------------------------------------------------------------------------------
+// DISPLAY ITERATOR
+// -------------------------------------------------------------------------------------------------
+
+/// Iterates over the visible area accounting for buffer transform
+pub struct DisplayIter<'a, T: 'a> {
+ grid: &'a Grid<T>,
+ offset: usize,
+ limit: usize,
+ col: Column,
+}
+
+impl<'a, T: 'a> DisplayIter<'a, T> {
+ pub fn new(grid: &'a Grid<T>) -> DisplayIter<'a, T> {
+ let offset = grid.display_offset + *grid.num_lines() - 1;
+ let limit = grid.display_offset;
+ let col = Column(0);
+
+ DisplayIter { grid, offset, col, limit }
+ }
+
+ pub fn offset(&self) -> usize {
+ self.offset
+ }
+
+ pub fn column(&self) -> Column {
+ self.col
+ }
+}
+
+impl<'a, T: Copy + 'a> Iterator for DisplayIter<'a, T> {
+ type Item = Indexed<T>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ // Make sure indices are valid. Return None if we've reached the end.
+ if self.col == self.grid.num_cols() {
+ if self.offset == self.limit {
+ return None;
+ }
+
+ self.col = Column(0);
+ self.offset -= 1;
+ }
+
+ // Return the next item.
+ let item = Some(Indexed {
+ inner: self.grid.raw[self.offset][self.col],
+ line: Line( *self.grid.lines - 1 - (self.offset - self.limit)),
+ column: self.col
+ });
+
+ self.col += 1;
+ item
+ }
+}
diff --git a/src/grid/row.rs b/src/grid/row.rs
index 1c83d45d..6b6af7c8 100644
--- a/src/grid/row.rs
+++ b/src/grid/row.rs
@@ -22,10 +22,7 @@ use index::Column;
/// A row in the grid
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
-pub struct Row<T> {
- data: Vec<T>,
- id: u64
-}
+pub struct Row<T>(Vec<T>);
impl<T: Copy + Clone> Row<T> {
pub fn new(columns: Column, template: &T) -> Row<T> {
@@ -40,9 +37,8 @@ impl<T: Copy + Clone> Row<T> {
/// Resets contents to the contents of `other`
#[inline]
- pub fn reset(&mut self, other: &Row<T>, id: u64) {
+ pub fn reset(&mut self, other: &Row<T>) {
self.copy_from_slice(&**other);
- self.id = id;
}
}
@@ -52,16 +48,6 @@ impl<T> Row<T> {
self.pop();
}
}
-
- #[inline]
- pub fn cells(&self) -> slice::Iter<T> {
- self.0.iter()
- }
-
- #[inline]
- pub fn cells_mut(&mut self) -> slice::IterMut<T> {
- self.0.iter_mut()
- }
}
diff --git a/src/grid/storage.rs b/src/grid/storage.rs
index 3c64f700..b4228687 100644
--- a/src/grid/storage.rs
+++ b/src/grid/storage.rs
@@ -13,22 +13,35 @@
/// done so manually.
use std::ops::{Index, IndexMut};
+use index::Line;
+
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
pub struct Storage<T> {
inner: Vec<T>,
zero: usize,
+ visible_lines: Line,
}
impl<T> Storage<T> {
#[inline]
- pub fn with_capacity(cap: usize) -> Storage<T> {
+ pub fn with_capacity(cap: usize, lines: Line) -> Storage<T> {
Storage {
inner: Vec::with_capacity(cap),
- zero: 0
+ zero: 0,
+ visible_lines: lines - 1,
}
}
#[inline]
+ pub fn capacity(&self) -> usize {
+ self.inner.capacity()
+ }
+
+ pub fn set_visible_lines(&mut self, next: Line) {
+ self.visible_lines = next - 1;
+ }
+
+ #[inline]
pub fn push(&mut self, item: T) {
self.inner.push(item)
}
@@ -55,6 +68,12 @@ impl<T> Storage<T> {
self.inner.swap(a, b);
}
+ pub fn swap_lines(&mut self, a: Line, b: Line) {
+ let a = self.visible_lines - a;
+ let b = self.visible_lines - b;
+ self.swap(*a, *b);
+ }
+
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut { storage: self, index: 0 }
}
@@ -88,6 +107,23 @@ impl<T> IndexMut<usize> for Storage<T> {
}
}
+impl<T> Index<Line> for Storage<T> {
+ type Output = T;
+ #[inline]
+ fn index(&self, index: Line) -> &T {
+ let index = self.visible_lines - index;
+ &self[*index]
+ }
+}
+
+impl<T> IndexMut<Line> for Storage<T> {
+ #[inline]
+ fn index_mut(&mut self, index: Line) -> &mut T {
+ let index = self.visible_lines - index;
+ &mut self[*index]
+ }
+}
+
pub struct IterMut<'a, T: 'a> {
storage: &'a mut Storage<T>,
index: usize,
diff --git a/src/input.rs b/src/input.rs
index ff1eb796..6ffdd507 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -64,6 +64,7 @@ pub trait ActionContext {
fn last_modifiers(&mut self) -> &mut ModifiersState;
fn change_font_size(&mut self, delta: i8);
fn reset_font_size(&mut self);
+ fn scroll(&mut self, count: isize) {}
}
/// Describes a state and action to take in that state
@@ -386,10 +387,6 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
pub fn on_mouse_wheel(&mut self, delta: MouseScrollDelta, phase: TouchPhase) {
let mouse_modes = mode::TermMode::MOUSE_REPORT_CLICK | mode::TermMode::MOUSE_MOTION | mode::TermMode::SGR_MOUSE;
- if !self.ctx.terminal_mode().intersects(mouse_modes | mode::TermMode::ALT_SCREEN) {
- return;
- }
-
match delta {
MouseScrollDelta::LineDelta(_columns, lines) => {
let to_scroll = self.ctx.mouse_mut().lines_scrolled + lines;
@@ -439,16 +436,19 @@ impl<'a, A: ActionContext + 'a> Processor<'a, A> {
let faux_scrollback_lines = self.mouse_config.faux_scrollback_lines;
if self.ctx.terminal_mode().intersects(mouse_modes) {
self.mouse_report(code, ElementState::Pressed);
- } else if faux_scrollback_lines > 0 {
- // Faux scrolling
- let cmd = code + 1; // 64 + 1 = A, 65 + 1 = B
- let mut content = Vec::with_capacity(faux_scrollback_lines * 3);
- for _ in 0..faux_scrollback_lines {
- content.push(0x1b);
- content.push(b'O');
- content.push(cmd);
- }
- self.ctx.write_to_pty(content);
+ // } else if faux_scrollback_lines > 0 {
+ // // Faux scrolling
+ // let cmd = code + 1; // 64 + 1 = A, 65 + 1 = B
+ // let mut content = Vec::with_capacity(faux_scrollback_lines * 3);
+ // for _ in 0..faux_scrollback_lines {
+ // content.push(0x1b);
+ // content.push(b'O');
+ // content.push(cmd);
+ // }
+ // self.ctx.write_to_pty(content);
+ // }
+ } else {
+ self.ctx.scroll(-((code as isize) * 2 - 129));
}
}
diff --git a/src/term/mod.rs b/src/term/mod.rs
index d501d1c1..73b0850f 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -24,8 +24,8 @@ use unicode_width::UnicodeWidthChar;
use font::{self, Size};
use ansi::{self, Color, NamedColor, Attr, Handler, CharsetIndex, StandardCharset, CursorStyle};
-use grid::{BidirectionalIterator, Grid, ToRange, Indexed, IndexRegion};
-use index::{self, Point, Column, Line, Linear, IndexRange, Contains, RangeInclusive};
+use grid::{BidirectionalIterator, Grid, ToRange, Indexed, IndexRegion, DisplayIter};
+use index::{self, Point, Column, Line, IndexRange, Contains, RangeInclusive};
use selection::{self, Span, Selection};
use config::{Config, VisualBellAnimation};
use {MouseCursor, Rgb};
@@ -94,12 +94,11 @@ impl selection::Dimensions for Term {
/// This manages the cursor during a render. The cursor location is inverted to
/// draw it, and reverted after drawing to maintain state.
pub struct RenderableCellsIter<'a> {
+ inner: DisplayIter<'a, Cell>,
grid: &'a Grid<Cell>,
cursor: &'a Point,
- cursor_index: index::Linear,
+ cursor_offset: usize,
mode: TermMode,
- line: Line,
- column: Column,
config: &'a Config,
colors: &'a color::List,
selection: Option<RangeInclusive<index::Linear>>,
@@ -120,18 +119,18 @@ impl<'a> RenderableCellsIter<'a> {
selection: Option<RangeInclusive<index::Linear>>,
cursor_style: CursorStyle,
) -> RenderableCellsIter<'b> {
- let cursor_index = Linear(cursor.line.0 * grid.num_cols().0 + cursor.col.0);
+ let cursor_offset = grid.line_to_offset(cursor.line);
+ let inner = grid.display_iter();
RenderableCellsIter {
- grid,
- cursor,
- cursor_index,
- mode,
- line: Line(0),
- column: Column(0),
- selection,
- config,
- colors,
+ cursor: cursor,
+ cursor_offset: cursor_offset,
+ grid: grid,
+ inner: inner,
+ mode: mode,
+ selection: selection,
+ config: config,
+ colors: colors,
cursor_cells: ArrayDeque::new(),
}.initialize(cursor_style)
}
@@ -318,6 +317,7 @@ impl<'a> RenderableCellsIter<'a> {
}
pub struct RenderableCell {
+ /// A _Display_ line (not necessarily an _Active_ line)
pub line: Line,
pub column: Column,
pub c: char,
@@ -336,64 +336,55 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
/// (eg. invert fg and bg colors).
#[inline]
fn next(&mut self) -> Option<Self::Item> {
- while self.line < self.grid.num_lines() {
- while self.column < self.grid.num_cols() {
- // Grab current state for this iteration
- let line = self.line;
- let mut column = self.column;
- let cell = &self.grid[line][column];
-
- let index = Linear(line.0 * self.grid.num_cols().0 + column.0);
-
- let (cell, selected) = if index == self.cursor_index {
- // Cursor cell
- let cell = self.cursor_cells.pop_front().unwrap();
- column = cell.column;
-
- // Since there may be multiple cursor cells (for a wide
- // char), only update iteration position after all cursor
- // cells have been drawn.
- if self.cursor_cells.is_empty() {
- self.line = cell.line;
- self.column = cell.column + 1;
- }
- (cell.inner, false)
- } else {
- // Normal cell
- self.column += 1;
+ loop {
+ // Handle cursor
+ let (cell, selected) = if self.cursor_offset == self.inner.offset() &&
+ self.inner.column() == self.cursor.col
+ {
+ // Cursor cell
+ let cell = self.cursor_cells.pop_front().unwrap();
+
+ // Since there may be multiple cursor cells (for a wide
+ // char), only update iteration position after all cursor
+ // cells have been drawn.
+ if self.cursor_cells.is_empty() {
+ self.inner.next();
+ }
+ (cell, false)
+ } else {
+ let cell = self.inner.next()?;
+
+ // XXX (jwilm) selection temp disabled
+ //
+ // let selected = self.selection.as_ref()
+ // .map(|range| range.contains_(index))
+ // .unwrap_or(false);
+ let selected = false;
+
+ // Skip empty cells
+ if cell.is_empty() && !selected {
+ continue;
+ }
+ (cell, selected)
+ };
- let selected = self.selection.as_ref()
- .map(|range| range.contains_(index))
- .unwrap_or(false);
+ // Apply inversion and lookup RGB values
+ let mut bg_alpha = 1.0;
+ let fg_rgb;
+ let bg_rgb;
- // Skip empty cells
- if cell.is_empty() && !selected {
- continue;
- }
- (*cell, selected)
- };
+ let invert = selected ^ cell.inverse();
- // Apply inversion and lookup RGB values
- let mut bg_alpha = 1.0;
- let fg_rgb;
- let bg_rgb;
-
- let invert = selected ^ cell.inverse();
-
- if invert {
- if cell.fg == cell.bg {
- bg_rgb = self.colors[NamedColor::Foreground];
- fg_rgb = self.colors[NamedColor::Background];
- bg_alpha = 1.0
- } else {
- bg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
- fg_rgb = self.compute_bg_rgb(&cell.bg);
- }
+ if invert {
+ if cell.fg == cell.bg {
+ bg_rgb = self.colors[NamedColor::Foreground];
+ fg_rgb = self.colors[NamedColor::Background];
+ bg_alpha = 1.0
} else {
- fg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
- bg_rgb = self.compute_bg_rgb(&cell.bg);
- bg_alpha = self.compute_bg_alpha(&cell.bg);
+ bg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
+ fg_rgb = self.compute_bg_rgb(&cell.bg);
}
+<<<<<<< HEAD
return Some(RenderableCell {
line,
@@ -404,13 +395,35 @@ impl<'a> Iterator for RenderableCellsIter<'a> {
bg: bg_rgb,
bg_alpha,
})
+||||||| merged common ancestors
+
+ return Some(RenderableCell {
+ line: line,
+ column: column,
+ flags: cell.flags,
+ c: cell.c,
+ fg: fg_rgb,
+ bg: bg_rgb,
+ bg_alpha: bg_alpha,
+ })
+=======
+ } else {
+ fg_rgb = self.compute_fg_rgb(&cell.fg, &cell);
+ bg_rgb = self.compute_bg_rgb(&cell.bg);
+ bg_alpha = self.compute_bg_alpha(&cell.bg);
+>>>>>>> checkpoint: very basic scrolling works
}
- self.column = Column(0);
- self.line += 1;
+ return Some(RenderableCell {
+ line: cell.line,
+ column: cell.column,
+ flags: cell.flags,
+ c: cell.c,
+ fg: fg_rgb,
+ bg: bg_rgb,
+ bg_alpha: bg_alpha,
+ })
}
-
- None
}
}
@@ -788,6 +801,11 @@ impl Term {
self.next_title.take()
}
+ pub fn scroll_display(&mut self, count: isize) {
+ self.grid.scroll_display(count);
+ self.dirty = true;
+ }
+
#[inline]
pub fn get_next_mouse_cursor(&mut self) -> Option<MouseCursor> {
self.next_mouse_cursor.take()
@@ -1045,10 +1063,6 @@ impl Term {
num_lines = Line(2);
}
- // Scroll up to keep cursor and as much context as possible in grid.
- // This only runs when the lines decreases.
- self.scroll_region = Line(0)..self.grid.num_lines();
-
// Scroll up to keep cursor in terminal
if self.cursor.point.line >= num_lines {
let lines = self.cursor.point.line - num_lines + 1;
@@ -1060,7 +1074,6 @@ impl Term {
let lines = self.cursor_save_alt.point.line - num_lines + 1;
self.alt_grid.scroll_up(&(Line(0)..old_lines), lines);
}
-
debug!("num_cols, num_lines = {}, {}", num_cols, num_lines);
// Resize grids to new size
@@ -1083,16 +1096,16 @@ impl Term {
.map(|i| (*i as usize) % self.tabspaces == 0)
.collect::<Vec<bool>>();
- if num_lines > old_lines {
- // Make sure bottom of terminal is clear
- let template = self.cursor.template;
- self.grid
- .region_mut((self.cursor.point.line + 1)..)
- .each(|c| c.reset(&template));
- self.alt_grid
- .region_mut((self.cursor_save_alt.point.line + 1)..)
- .each(|c| c.reset(&template));
- }
+ // if num_lines > old_lines {
+ // // Make sure bottom of terminal is clear
+ // let template = self.cursor.template;
+ // self.grid
+ // .region_mut((self.cursor.point.line + 1)..)
+ // .each(|c| c.reset(&template));
+ // self.alt_grid
+ // .region_mut((self.cursor_save_alt.point.line + 1)..)
+ // .each(|c| c.reset(&template));
+ // }
}