Skip to main content

rmux_core/screen/
selection.rs

1use crate::grid::GridCellFlags;
2use crate::input::GridAttr;
3use crate::style::{style_parse, Style, StyleCell};
4
5use super::Screen;
6
7impl Screen {
8    /// Marks one visible row range as selected.
9    pub fn mark_selected_row_range(&mut self, row: u32, start_x: u32, end_x: u32) {
10        let line_width = self.grid.sx();
11        if row >= self.grid.sy() || line_width == 0 {
12            return;
13        }
14
15        let Some(line) = self.grid.visible_line_mut(row) else {
16            return;
17        };
18        let start_x = start_x.min(line_width.saturating_sub(1));
19        let end_x = end_x.min(line_width.saturating_sub(1));
20        if start_x > end_x {
21            return;
22        }
23
24        let start_x = line.owning_cell_x(start_x).unwrap_or(start_x);
25        let end_x = line.owning_cell_x(end_x).unwrap_or(end_x);
26        let mut x = start_x;
27        while x <= end_x {
28            let owner_x = line.owning_cell_x(x).unwrap_or(x);
29            let width = line
30                .cell(owner_x)
31                .map(|cell| u32::from(cell.width().max(1)))
32                .unwrap_or(1);
33
34            for offset in 0..width {
35                let cell_x = owner_x.saturating_add(offset);
36                if let Some(cell) = line.cell_mut(cell_x) {
37                    let mut flags = cell.flags();
38                    flags.insert(GridCellFlags::SELECTED);
39                    cell.set_flags(flags);
40                }
41            }
42
43            x = owner_x.saturating_add(width.max(1));
44        }
45    }
46
47    /// Overlays `style_input` onto all selected visible cells.
48    pub fn overlay_style_on_selected(&mut self, style_input: &str) {
49        if style_input.is_empty() {
50            return;
51        }
52
53        let width = self.grid.sx();
54        for row in 0..self.grid.sy() {
55            let Some(line) = self.grid.visible_line_mut(row) else {
56                continue;
57            };
58            for x in 0..width {
59                let Some(cell) = line.cell_mut(x) else {
60                    continue;
61                };
62                if !cell.flags().contains(GridCellFlags::SELECTED) || cell.is_padding() {
63                    continue;
64                }
65
66                let base = StyleCell {
67                    fg: cell.fg(),
68                    bg: cell.bg(),
69                    us: cell.us(),
70                    attr: cell.attr(),
71                };
72                let mut style = Style::with_cell(base);
73                if style_parse(&mut style, &base, style_input).is_err() {
74                    return;
75                }
76
77                let attr = if style.cell.attr & GridAttr::NOATTR != 0 {
78                    style.cell.attr & !GridAttr::NOATTR
79                } else {
80                    style.cell.attr
81                };
82                cell.set_attr(attr);
83                cell.set_fg(style.cell.fg);
84                cell.set_bg(style.cell.bg);
85                cell.set_us(style.cell.us);
86            }
87        }
88    }
89}