aboutsummaryrefslogtreecommitdiffstats
path: root/src/cell.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cell.rs')
-rw-r--r--src/cell.rs78
1 files changed, 60 insertions, 18 deletions
diff --git a/src/cell.rs b/src/cell.rs
index d0d6f0c..61a3cd3 100644
--- a/src/cell.rs
+++ b/src/cell.rs
@@ -1,33 +1,73 @@
use unicode_normalization::UnicodeNormalization as _;
use unicode_width::UnicodeWidthChar as _;
+const CODEPOINTS_IN_CELL: usize = 6;
+
/// Represents a single terminal cell.
-#[derive(Clone, Debug, Default, Eq, PartialEq)]
+#[derive(Clone, Debug, Default, Eq)]
pub struct Cell {
- contents: String,
+ contents: [char; CODEPOINTS_IN_CELL],
+ len: u8,
attrs: crate::attrs::Attrs,
}
+impl PartialEq<Cell> for Cell {
+ fn eq(&self, other: &Self) -> bool {
+ if self.attrs != other.attrs {
+ return false;
+ }
+ if self.len != other.len {
+ return false;
+ }
+ let len = self.len as usize;
+ self.contents[..len] == other.contents[..len]
+ }
+}
+
impl Cell {
pub(crate) fn set(&mut self, c: char, a: crate::attrs::Attrs) {
- let mut buf = vec![0; 4];
- c.encode_utf8(&mut buf);
- self.contents = unsafe { String::from_utf8_unchecked(buf) };
+ self.contents[0] = c;
+ self.len = 1;
self.attrs = a;
}
pub(crate) fn append(&mut self, c: char) {
- self.contents.push(c);
+ if self.len as usize >= CODEPOINTS_IN_CELL {
+ return;
+ }
+
+ self.contents[self.len as usize] = c;
+ self.len += 1;
+
// some fonts have combined characters but can't render combining
// characters correctly, so try to prefer precombined characters when
// possible
- if !unicode_normalization::is_nfc(&self.contents) {
- self.contents = self.contents.nfc().collect();
+ if unicode_normalization::is_nfc_quick(
+ self.contents.iter().copied().take(CODEPOINTS_IN_CELL),
+ ) == unicode_normalization::IsNormalized::Yes
+ {
+ return;
}
+
+ let mut new_contents = ['\x00'; CODEPOINTS_IN_CELL];
+ let mut new_len = 0;
+ for c in self
+ .contents
+ .iter()
+ .copied()
+ .take(self.len as usize)
+ .nfc()
+ .take(CODEPOINTS_IN_CELL)
+ {
+ new_contents[new_len as usize] = c;
+ new_len += 1;
+ }
+ self.contents = new_contents;
+ self.len = new_len;
}
pub(crate) fn clear(&mut self, bgcolor: crate::attrs::Color) {
- self.contents.clear();
+ self.len = 0;
self.attrs.clear();
self.attrs.bgcolor = bgcolor;
}
@@ -37,13 +77,16 @@ impl Cell {
/// Can include multiple unicode characters if combining characters are
/// used, but will contain at most one character with a non-zero character
/// width.
- pub fn contents(&self) -> &str {
- &self.contents
+ pub fn contents(&self) -> String {
+ self.contents
+ .iter()
+ .take(self.len as usize)
+ .collect::<String>()
}
/// Returns whether the cell contains any text data.
pub fn has_contents(&self) -> bool {
- self.contents != ""
+ self.len > 0
}
/// Returns whether the text data in the cell represents a wide character.
@@ -51,12 +94,11 @@ impl Cell {
// strings in this context should always be an arbitrary character
// followed by zero or more zero-width characters, so we should only
// have to look at the first character
- let width = self
- .contents
- .chars()
- .next()
- .map_or(0, |c| c.width().unwrap_or(0));
- width > 1
+ if self.len == 0 {
+ false
+ } else {
+ self.contents[0].width().unwrap_or(0) > 1
+ }
}
pub(crate) fn attrs(&self) -> &crate::attrs::Attrs {