summaryrefslogtreecommitdiff
path: root/alacritty_terminal/src/term/cell.rs
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2022-03-16 19:27:55 +0300
committerGitHub <noreply@github.com>2022-03-16 19:27:55 +0300
commitf4bdf5fb36fdf3b329be8253da39050abe7238a5 (patch)
tree9b49a78b15fdd73850a7bfc279e3986af2b59683 /alacritty_terminal/src/term/cell.rs
parent589c1e9c6b8830625162af14a9a7aee32c7aade0 (diff)
downloadalacritty-f4bdf5fb36fdf3b329be8253da39050abe7238a5.tar.gz
alacritty-f4bdf5fb36fdf3b329be8253da39050abe7238a5.zip
Add colored underline support
This commit adds support for colored underline and refines the dynamic extra storage. The extra storage now is using `Arc` making cloning it way faster compared to `Box` approach which scales really well when it comes to cloning in `Term::write_at_cursor`, since cloning `Arc` is constant time. Fixes #4142.
Diffstat (limited to 'alacritty_terminal/src/term/cell.rs')
-rw-r--r--alacritty_terminal/src/term/cell.rs60
1 files changed, 43 insertions, 17 deletions
diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs
index 2af1fbac..716bcf9b 100644
--- a/alacritty_terminal/src/term/cell.rs
+++ b/alacritty_terminal/src/term/cell.rs
@@ -1,4 +1,4 @@
-use std::boxed::Box;
+use std::sync::Arc;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
@@ -57,19 +57,20 @@ impl ResetDiscriminant<Color> for Cell {
/// allocation required ahead of time for every cell, with some additional overhead when the extra
/// storage is actually required.
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
-struct CellExtra {
+pub struct CellExtra {
zerowidth: Vec<char>,
+
+ underline_color: Option<Color>,
}
/// Content and attributes of a single cell in the terminal grid.
-#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
+#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
pub struct Cell {
pub c: char,
pub fg: Color,
pub bg: Color,
pub flags: Flags,
- #[serde(default)]
- extra: Option<Box<CellExtra>>,
+ pub extra: Option<Arc<CellExtra>>,
}
impl Default for Cell {
@@ -94,25 +95,39 @@ impl Cell {
/// Write a new zerowidth character to this cell.
#[inline]
- pub fn push_zerowidth(&mut self, c: char) {
- self.extra.get_or_insert_with(Default::default).zerowidth.push(c);
- }
-
- /// Free all dynamically allocated cell storage.
- #[inline]
- pub fn drop_extra(&mut self) {
- if self.extra.is_some() {
- self.extra = None;
- }
+ pub fn push_zerowidth(&mut self, character: char) {
+ let extra = self.extra.get_or_insert(Default::default());
+ Arc::make_mut(extra).zerowidth.push(character);
}
/// Remove all wide char data from a cell.
#[inline(never)]
pub fn clear_wide(&mut self) {
self.flags.remove(Flags::WIDE_CHAR);
- self.drop_extra();
+ if let Some(extra) = self.extra.as_mut() {
+ Arc::make_mut(extra).zerowidth = Vec::new();
+ }
self.c = ' ';
}
+
+ /// Set underline color on the cell.
+ pub fn set_underline_color(&mut self, color: Option<Color>) {
+ // If we reset color and we don't have zerowidth we should drop extra storage.
+ if color.is_none() && self.extra.as_ref().map_or(true, |extra| !extra.zerowidth.is_empty())
+ {
+ self.extra = None;
+ return;
+ }
+
+ let extra = self.extra.get_or_insert(Default::default());
+ Arc::make_mut(extra).underline_color = color;
+ }
+
+ /// Underline color stored in this cell.
+ #[inline]
+ pub fn underline_color(&self) -> Option<Color> {
+ self.extra.as_ref()?.underline_color
+ }
}
impl GridCell for Cell {
@@ -184,12 +199,23 @@ impl LineLength for grid::Row<Cell> {
#[cfg(test)]
mod tests {
- use super::{Cell, LineLength};
+ use super::*;
+
+ use std::mem;
use crate::grid::Row;
use crate::index::Column;
#[test]
+ fn cell_size_is_below_cap() {
+ // Expected cell size on 64-bit architectures.
+ const EXPECTED_CELL_SIZE: usize = 24;
+
+ // Ensure that cell size isn't growning by accident.
+ assert!(mem::size_of::<Cell>() <= EXPECTED_CELL_SIZE);
+ }
+
+ #[test]
fn line_length_works() {
let mut row = Row::<Cell>::new(10);
row[Column(5)].c = 'a';