Skip to main content

rmux_core/screen/
style_overlay.rs

1use crate::input::{GridAttr, COLOUR_DEFAULT, COLOUR_NONE, COLOUR_TERMINAL};
2use crate::style::{style_parse, Style, StyleCell};
3
4use super::Screen;
5
6impl Screen {
7    /// Applies `style_input` only where the application left cell styling unset.
8    pub fn overlay_style_on_default_cells(&mut self, style_input: &str) {
9        let Some(style) = default_cell_overlay(style_input) else {
10            return;
11        };
12        self.overlay_default_style(&style);
13    }
14
15    /// Applies `style` only where the application left cell styling unset.
16    pub fn overlay_default_style(&mut self, style: &Style) {
17        let background = effective_background(style);
18        let width = self.grid.sx();
19        for row in 0..self.grid.sy() {
20            let Some(line) = self.grid.visible_line_mut(row) else {
21                continue;
22            };
23            for x in 0..width {
24                let Some(cell) = line.cell_mut(x) else {
25                    continue;
26                };
27                if cell.is_padding() {
28                    continue;
29                }
30
31                if is_set(style.cell.fg) && is_unset(cell.fg()) {
32                    cell.set_fg(style.cell.fg);
33                }
34                if is_set(background) && is_unset(cell.bg()) {
35                    cell.set_bg(background);
36                }
37                if is_set(style.cell.us) && is_unset(cell.us()) {
38                    cell.set_us(style.cell.us);
39                }
40                if style.cell.attr != 0 && cell.attr() == 0 {
41                    cell.set_attr(style.cell.attr & !GridAttr::NOATTR);
42                }
43            }
44        }
45    }
46}
47
48fn default_cell_overlay(style_input: &str) -> Option<Style> {
49    if style_input.is_empty() {
50        return None;
51    }
52
53    let base = StyleCell::default();
54    let mut style = Style::default();
55    style_parse(&mut style, &base, style_input).ok()?;
56    (is_set(style.cell.fg)
57        || is_set(style.cell.bg)
58        || is_set(style.cell.us)
59        || is_set(style.fill)
60        || style.cell.attr != 0)
61        .then_some(style)
62}
63
64fn effective_background(style: &Style) -> i32 {
65    if is_set(style.cell.bg) {
66        style.cell.bg
67    } else {
68        style.fill
69    }
70}
71
72fn is_set(colour: i32) -> bool {
73    !is_unset(colour)
74}
75
76fn is_unset(colour: i32) -> bool {
77    matches!(colour, COLOUR_DEFAULT | COLOUR_TERMINAL | COLOUR_NONE)
78}