1use unicode_width::UnicodeWidthChar as _;
2
3const CODEPOINTS_IN_CELL: usize = 6;
4
5#[derive(Clone, Debug, Default, Eq)]
7pub struct Cell {
8 contents: [char; CODEPOINTS_IN_CELL],
9 len: u8,
10 attrs: crate::attrs::Attrs,
11}
12
13impl PartialEq<Self> for Cell {
14 fn eq(&self, other: &Self) -> bool {
15 if self.len != other.len {
16 return false;
17 }
18 if self.attrs != other.attrs {
19 return false;
20 }
21 let len = self.len();
22 self.contents[..len] == other.contents[..len]
24 }
25}
26
27impl Cell {
28 #[inline]
29 fn len(&self) -> usize {
30 usize::from(self.len & 0x0f)
31 }
32
33 pub(crate) fn set(&mut self, c: char, a: crate::attrs::Attrs) {
34 self.contents[0] = c;
35 self.len = 1;
36 self.set_wide(c.width().unwrap_or(1) > 1);
40 self.attrs = a;
41 }
42
43 pub(crate) fn append(&mut self, c: char) {
44 let len = self.len();
45 if len >= CODEPOINTS_IN_CELL {
46 return;
47 }
48 if len == 0 {
49 self.contents[0] = ' ';
51 self.len += 1;
52 }
53
54 let len = self.len();
55 self.contents[len] = c;
57 self.len += 1;
58 }
59
60 pub(crate) fn clear(&mut self, attrs: crate::attrs::Attrs) {
61 self.len = 0;
62 self.attrs = attrs;
63 }
64
65 #[must_use]
71 pub fn contents(&self) -> String {
72 let mut s = String::with_capacity(CODEPOINTS_IN_CELL * 4);
73 for c in self.contents.iter().take(self.len()) {
74 s.push(*c);
75 }
76 s
77 }
78
79 #[must_use]
81 pub fn has_contents(&self) -> bool {
82 self.len > 0
83 }
84
85 #[must_use]
87 pub fn is_wide(&self) -> bool {
88 self.len & 0x80 == 0x80
89 }
90
91 #[must_use]
95 pub fn is_wide_continuation(&self) -> bool {
96 self.len & 0x40 == 0x40
97 }
98
99 fn set_wide(&mut self, wide: bool) {
100 if wide {
101 self.len |= 0x80;
102 } else {
103 self.len &= 0x7f;
104 }
105 }
106
107 pub(crate) fn set_wide_continuation(&mut self, wide: bool) {
108 if wide {
109 self.len |= 0x40;
110 } else {
111 self.len &= 0xbf;
112 }
113 }
114
115 pub(crate) fn attrs(&self) -> &crate::attrs::Attrs {
116 &self.attrs
117 }
118
119 #[must_use]
121 pub fn fgcolor(&self) -> crate::attrs::Color {
122 self.attrs.fgcolor
123 }
124
125 #[must_use]
127 pub fn bgcolor(&self) -> crate::attrs::Color {
128 self.attrs.bgcolor
129 }
130
131 #[must_use]
134 pub fn bold(&self) -> bool {
135 self.attrs.bold()
136 }
137
138 #[must_use]
141 pub fn italic(&self) -> bool {
142 self.attrs.italic()
143 }
144
145 #[must_use]
148 pub fn underline(&self) -> bool {
149 self.attrs.underline()
150 }
151
152 #[must_use]
155 pub fn inverse(&self) -> bool {
156 self.attrs.inverse()
157 }
158}