aboutsummaryrefslogtreecommitdiff
path: root/src/grid
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2018-03-06 20:57:40 -0800
committerJoe Wilm <joe@jwilm.com>2018-03-07 09:51:51 -0800
commit143c28953cca8f2a1190c94f6e6944dad391dac7 (patch)
tree0eaa7794088041a37ef1e7c564926407c5c7eb56 /src/grid
parent2cfdd595f11377fbd91536a428e87d949ed9a05e (diff)
downloadalacritty-143c28953cca8f2a1190c94f6e6944dad391dac7.tar.gz
alacritty-143c28953cca8f2a1190c94f6e6944dad391dac7.zip
Support selections with scrolling buffer
Selections now *mostly* work. They move as the buffer scrolls, copying works as it should, and it looks like the different selection modes behave properly as well. The new Selection implementation uses buffer coordinates instead of screen coordinates. This leads to doing a transform from mouse input to update the selection, and back to screen coordinates when displaying the selection. Scrolling the selection is fast because the grid is already operating in buffer coordinates. There are several bugs to address: * A _partially_ visible selection will lead to a crash since the drawing routine converts selection coordinates to screen coordinates. The solution will be to clip the coordinates at draw time. * A selection scrolling off the buffer in either direction leads to indexing out-of-bounds. The solution again is to clip, but this needs to be done within Selection::rotate by passing a max limit. It may also need a return type to indicate that the selection is no longer visible and should be discarded. * A selection scrolling out of a logical scrolling region is not clipped. A temporary and robust workaround is to simply discard the selection in the case of scrolling in a region. wip selections fix issue with line selection selection mostly working need to support selection not being on the screen at draw time Fix selection_to_string Uncomment tests
Diffstat (limited to 'src/grid')
-rw-r--r--src/grid/mod.rs68
1 files changed, 53 insertions, 15 deletions
diff --git a/src/grid/mod.rs b/src/grid/mod.rs
index cf66a420..7f648f46 100644
--- a/src/grid/mod.rs
+++ b/src/grid/mod.rs
@@ -17,7 +17,7 @@
use std::cmp::{min, max, Ordering};
use std::ops::{Deref, Range, Index, IndexMut, RangeTo, RangeFrom, RangeFull};
-use index::{self, Point, Line, Column, IndexRange, RangeInclusive};
+use index::{self, Point, Line, Column, IndexRange};
use selection::Selection;
mod row;
@@ -29,11 +29,6 @@ mod tests;
mod storage;
use self::storage::Storage;
-/// Convert a type to a linear index range.
-pub trait ToRange {
- fn to_range(&self) -> RangeInclusive<index::Linear>;
-}
-
/// Bidirection iterator
pub trait BidirectionalIterator: Iterator {
fn prev(&mut self) -> Option<Self::Item>;
@@ -105,8 +100,17 @@ pub struct Grid<T> {
}
pub struct GridIterator<'a, T: 'a> {
+ /// Immutable grid reference
grid: &'a Grid<T>,
- pub cur: Point,
+
+ /// Current position of the iterator within the grid.
+ pub cur: Point<usize>,
+
+ /// Bottom of screen (buffer)
+ bot: usize,
+
+ /// Top of screen (buffer)
+ top: usize,
}
impl<T: Copy + Clone> Grid<T> {
@@ -135,6 +139,28 @@ impl<T: Copy + Clone> Grid<T> {
}
}
+ pub fn visible_to_buffer(&self, point: Point) -> Point<usize> {
+ Point {
+ line: self.visible_line_to_buffer(point.line),
+ col: point.col
+ }
+ }
+
+ pub fn buffer_to_visible(&self, point: Point<usize>) -> Point {
+ Point {
+ line: self.buffer_line_to_visible(point.line),
+ col: point.col
+ }
+ }
+
+ pub fn buffer_line_to_visible(&self, line: usize) -> Line {
+ self.offset_to_line(line - self.display_offset)
+ }
+
+ pub fn visible_line_to_buffer(&self, line: Line) -> usize {
+ self.line_to_offset(line) + self.display_offset
+ }
+
pub fn scroll_display(&mut self, count: isize) {
self.display_offset = min(
max((self.display_offset as isize) + count, 0isize) as usize,
@@ -224,6 +250,7 @@ impl<T: Copy + Clone> Grid<T> {
let prev = self.lines;
+ self.selection = None;
self.raw.rotate(*prev as isize - *target as isize);
self.raw.set_visible_lines(target);
self.lines = target;
@@ -240,6 +267,12 @@ impl<T: Copy + Clone> Grid<T> {
*(self.num_lines() - line - 1)
}
+ pub fn offset_to_line(&self, offset: usize) -> Line {
+ assert!(offset < *self.num_lines());
+
+ self.lines - offset - 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
@@ -251,6 +284,9 @@ 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);
+ if let Some(ref mut selection) = self.selection {
+ selection.rotate(-(*positions as isize));
+ }
self.decrease_scroll_limit(*positions);
@@ -292,6 +328,9 @@ 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(-(*positions as isize));
+ if let Some(ref mut selection) = self.selection {
+ selection.rotate(*positions as isize);
+ }
// Now, restore any lines outside the scroll region
for idx in (*region.end .. *self.num_lines()).rev() {
@@ -334,10 +373,12 @@ impl<T> Grid<T> {
self.cols
}
- pub fn iter_from(&self, point: Point) -> GridIterator<T> {
+ pub fn iter_from(&self, point: Point<usize>) -> GridIterator<T> {
GridIterator {
grid: self,
cur: point,
+ bot: self.display_offset,
+ top: self.display_offset + *self.num_lines() - 1,
}
}
@@ -369,15 +410,12 @@ impl<'a, T> Iterator for GridIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
- let last_line = self.grid.num_lines() - Line(1);
let last_col = self.grid.num_cols() - Column(1);
match self.cur {
- Point { line, col } if
- (line == last_line) &&
- (col == last_col) => None,
+ Point { line, col } if (line == self.bot) && (col == last_col) => None,
Point { col, .. } if
(col == last_col) => {
- self.cur.line += Line(1);
+ self.cur.line -= 1;
self.cur.col = Column(0);
Some(&self.grid[self.cur.line][self.cur.col])
},
@@ -394,9 +432,9 @@ impl<'a, T> BidirectionalIterator for GridIterator<'a, T> {
let num_cols = self.grid.num_cols();
match self.cur {
- Point { line: Line(0), col: Column(0) } => None,
+ Point { line, col: Column(0) } if line == self.top => None,
Point { col: Column(0), .. } => {
- self.cur.line -= Line(1);
+ self.cur.line += 1;
self.cur.col = num_cols - Column(1);
Some(&self.grid[self.cur.line][self.cur.col])
},