summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/selection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'alacritty_terminal/src/selection.rs')
-rw-r--r--alacritty_terminal/src/selection.rs67
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
+ }
}
}