diff options
Diffstat (limited to 'alacritty_terminal/src/selection.rs')
-rw-r--r-- | alacritty_terminal/src/selection.rs | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/alacritty_terminal/src/selection.rs b/alacritty_terminal/src/selection.rs index 9c3fa598..9402fc21 100644 --- a/alacritty_terminal/src/selection.rs +++ b/alacritty_terminal/src/selection.rs @@ -9,8 +9,10 @@ use std::convert::TryFrom; use std::mem; use std::ops::{Bound, Range, RangeBounds}; -use crate::grid::Dimensions; +use crate::ansi::CursorShape; +use crate::grid::{Dimensions, Grid, GridCell}; use crate::index::{Column, Line, Point, Side}; +use crate::term::cell::Flags; use crate::term::Term; /// A Point and side within that point. @@ -42,14 +44,67 @@ impl<L> SelectionRange<L> { Self { start, end, is_block } } - pub fn contains(&self, col: Column, line: L) -> bool + /// Check if a point lies within the selection. + pub fn contains(&self, point: Point<L>) -> bool where L: PartialEq + PartialOrd, { - self.start.line <= line - && self.end.line >= line - && (self.start.col <= col || (self.start.line != line && !self.is_block)) - && (self.end.col >= col || (self.end.line != line && !self.is_block)) + self.start.line <= point.line + && self.end.line >= point.line + && (self.start.col <= point.col || (self.start.line != point.line && !self.is_block)) + && (self.end.col >= point.col || (self.end.line != point.line && !self.is_block)) + } +} + +impl SelectionRange<Line> { + /// Check if the cell at a point is part of the selection. + pub fn contains_cell<T>( + &self, + grid: &Grid<T>, + point: Point, + cursor_point: Point, + cursor_shape: CursorShape, + ) -> bool + where + T: GridCell, + { + // Do not invert block cursor at selection boundaries. + if cursor_shape == CursorShape::Block + && cursor_point == point + && (self.start == point + || self.end == point + || (self.is_block + && ((self.start.line == point.line && self.end.col == point.col) + || (self.end.line == point.line && self.start.col == point.col)))) + { + return false; + } + + // Point itself is selected. + if self.contains(point) { + return true; + } + + let num_cols = grid.cols(); + + // Convert to absolute coordinates to adjust for the display offset. + let buffer_point = grid.visible_to_buffer(point); + let cell = &grid[buffer_point]; + + // Check if wide char's spacers are selected. + if cell.flags().contains(Flags::WIDE_CHAR) { + let prev = point.sub(num_cols, 1); + let buffer_prev = grid.visible_to_buffer(prev); + let next = point.add(num_cols, 1); + + // Check trailing spacer. + self.contains(next) + // Check line-wrapping, leading spacer. + || (grid[buffer_prev].flags().contains(Flags::LEADING_WIDE_CHAR_SPACER) + && self.contains(prev)) + } else { + false + } } } |