vt100/
attrs.rs

1use crate::term::BufWrite as _;
2
3/// Represents a foreground or background color for cells.
4#[derive(Eq, PartialEq, Debug, Copy, Clone)]
5pub enum Color {
6    /// The default terminal color.
7    Default,
8
9    /// An indexed terminal color.
10    Idx(u8),
11
12    /// An RGB terminal color. The parameters are (red, green, blue).
13    Rgb(u8, u8, u8),
14}
15
16impl Default for Color {
17    fn default() -> Self {
18        Self::Default
19    }
20}
21
22const TEXT_MODE_BOLD: u8 = 0b0000_0001;
23const TEXT_MODE_ITALIC: u8 = 0b0000_0010;
24const TEXT_MODE_UNDERLINE: u8 = 0b0000_0100;
25const TEXT_MODE_INVERSE: u8 = 0b0000_1000;
26
27#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
28pub struct Attrs {
29    pub fgcolor: Color,
30    pub bgcolor: Color,
31    pub mode: u8,
32}
33
34impl Attrs {
35    pub fn bold(&self) -> bool {
36        self.mode & TEXT_MODE_BOLD != 0
37    }
38
39    pub fn set_bold(&mut self, bold: bool) {
40        if bold {
41            self.mode |= TEXT_MODE_BOLD;
42        } else {
43            self.mode &= !TEXT_MODE_BOLD;
44        }
45    }
46
47    pub fn italic(&self) -> bool {
48        self.mode & TEXT_MODE_ITALIC != 0
49    }
50
51    pub fn set_italic(&mut self, italic: bool) {
52        if italic {
53            self.mode |= TEXT_MODE_ITALIC;
54        } else {
55            self.mode &= !TEXT_MODE_ITALIC;
56        }
57    }
58
59    pub fn underline(&self) -> bool {
60        self.mode & TEXT_MODE_UNDERLINE != 0
61    }
62
63    pub fn set_underline(&mut self, underline: bool) {
64        if underline {
65            self.mode |= TEXT_MODE_UNDERLINE;
66        } else {
67            self.mode &= !TEXT_MODE_UNDERLINE;
68        }
69    }
70
71    pub fn inverse(&self) -> bool {
72        self.mode & TEXT_MODE_INVERSE != 0
73    }
74
75    pub fn set_inverse(&mut self, inverse: bool) {
76        if inverse {
77            self.mode |= TEXT_MODE_INVERSE;
78        } else {
79            self.mode &= !TEXT_MODE_INVERSE;
80        }
81    }
82
83    pub fn write_escape_code_diff(
84        &self,
85        contents: &mut Vec<u8>,
86        other: &Self,
87    ) {
88        if self != other && self == &Self::default() {
89            crate::term::ClearAttrs::default().write_buf(contents);
90            return;
91        }
92
93        let attrs = crate::term::Attrs::default();
94
95        let attrs = if self.fgcolor == other.fgcolor {
96            attrs
97        } else {
98            attrs.fgcolor(self.fgcolor)
99        };
100        let attrs = if self.bgcolor == other.bgcolor {
101            attrs
102        } else {
103            attrs.bgcolor(self.bgcolor)
104        };
105        let attrs = if self.bold() == other.bold() {
106            attrs
107        } else {
108            attrs.bold(self.bold())
109        };
110        let attrs = if self.italic() == other.italic() {
111            attrs
112        } else {
113            attrs.italic(self.italic())
114        };
115        let attrs = if self.underline() == other.underline() {
116            attrs
117        } else {
118            attrs.underline(self.underline())
119        };
120        let attrs = if self.inverse() == other.inverse() {
121            attrs
122        } else {
123            attrs.inverse(self.inverse())
124        };
125
126        attrs.write_buf(contents);
127    }
128}