diff --git a/src/grid/mod.rs b/src/grid/mod.rs index 7f648f46..a52c27c5 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -148,13 +148,17 @@ impl Grid { pub fn buffer_to_visible(&self, point: Point) -> Point { Point { - line: self.buffer_line_to_visible(point.line), + line: self.buffer_line_to_visible(point.line).expect("Line not visible"), col: point.col } } - pub fn buffer_line_to_visible(&self, line: usize) -> Line { - self.offset_to_line(line - self.display_offset) + pub fn buffer_line_to_visible(&self, line: usize) -> Option { + if line >= self.display_offset { + self.offset_to_line(line - self.display_offset) + } else { + None + } } pub fn visible_line_to_buffer(&self, line: Line) -> usize { @@ -267,10 +271,12 @@ impl Grid { *(self.num_lines() - line - 1) } - pub fn offset_to_line(&self, offset: usize) -> Line { - assert!(offset < *self.num_lines()); - - self.lines - offset - 1 + pub fn offset_to_line(&self, offset: usize) -> Option { + if offset < *self.num_lines() { + Some(self.lines - offset - 1) + } else { + None + } } #[inline] diff --git a/src/term/mod.rs b/src/term/mod.rs index c3c3a300..54c8a7e2 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -122,29 +122,49 @@ impl<'a> RenderableCellsIter<'a> { let cursor_offset = grid.line_to_offset(cursor.line); let inner = grid.display_iter(); - let selection = selection.map(|loc| { - // start and end *lines* are swapped as we switch from buffer to - // Line coordinates. - let mut end = Point { - line: grid.buffer_line_to_visible(loc.start.line), - col: loc.start.col - }; - let mut start = Point { - line: grid.buffer_line_to_visible(loc.end.line), - col: loc.end.col + let mut selection_range = None; + selection.map(|loc| { + // Get on-screen lines of the selection's locations + let start_line = grid.buffer_line_to_visible(loc.start.line); + let end_line = grid.buffer_line_to_visible(loc.end.line); + + // Get start/end locations based on what part of selection is on screen + let locations = match (start_line, end_line) { + (Some(start_line), Some(end_line)) => { + Some((start_line, loc.start.col, end_line, loc.end.col)) + }, + (Some(start_line), None) => { + Some((start_line, loc.start.col, Line(0), grid.num_cols())) + }, + (None, Some(end_line)) => { + Some((grid.num_lines(), Column(0), end_line, loc.end.col)) + }, + (None, None) => None, }; - if start > end { - ::std::mem::swap(&mut start, &mut end); + if let Some((start_line, start_col, end_line, end_col)) = locations { + // start and end *lines* are swapped as we switch from buffer to + // Line coordinates. + let mut end = Point { + line: start_line, + col: start_col, + }; + let mut start = Point { + line: end_line, + col: end_col, + }; + + if start > end { + ::std::mem::swap(&mut start, &mut end); + } + + let cols = grid.num_cols(); + let start = Linear(start.line.0 * cols.0 + start.col.0); + let end = Linear(end.line.0 * cols.0 + end.col.0); + + // Update the selection + selection_range = Some(RangeInclusive::new(start, end)); } - - println!("start={:?}, end={:?}", start, end); - - let cols = grid.num_cols(); - let start = Linear(start.line.0 * cols.0 + start.col.0); - let end = Linear(end.line.0 * cols.0 + end.col.0); - - RangeInclusive::new(start, end) }); RenderableCellsIter { @@ -153,7 +173,7 @@ impl<'a> RenderableCellsIter<'a> { grid: grid, inner: inner, mode: mode, - selection: selection, + selection: selection_range, config: config, colors: colors, cursor_cells: ArrayDeque::new(),