mirror of
https://github.com/wez/wezterm.git
synced 2024-12-26 23:04:49 +03:00
cell attributes to bitfield, add screen container
This commit is contained in:
parent
7e41bb27d4
commit
342efa810b
@ -1,5 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate unicode_width;
|
||||
extern crate unicode_segmentation;
|
||||
extern crate harfbuzz_sys;
|
||||
|
142
src/term/mod.rs
142
src/term/mod.rs
@ -7,34 +7,74 @@ pub mod color;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CellAttributes {
|
||||
pub bold: bool,
|
||||
pub underline: bool,
|
||||
pub italic: bool,
|
||||
pub blink: bool,
|
||||
pub reverse: bool,
|
||||
pub strikethrough: bool,
|
||||
pub font: u8,
|
||||
attributes: u16,
|
||||
pub foreground: color::ColorAttribute,
|
||||
pub background: color::ColorAttribute,
|
||||
}
|
||||
|
||||
/// Define getter and setter for the attributes bitfield.
|
||||
/// The first form is for a simple boolean value stored in
|
||||
/// a single bit. The $bitnum parameter specifies which bit.
|
||||
/// The second form is for an integer value that occupies a range
|
||||
/// of bits. The $bitmask and $bitshift parameters define how
|
||||
/// to transform from the stored bit value to the consumable
|
||||
/// value.
|
||||
macro_rules! bitfield {
|
||||
($getter:ident, $setter:ident, $bitnum:expr) => {
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn $getter(&self) -> bool {
|
||||
(self.attributes & (1 << $bitnum)) == (1 << $bitnum)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn $setter(&mut self, value: bool) {
|
||||
let attr_value = if value { 1 << $bitnum } else { 0 };
|
||||
self.attributes = (self.attributes & !(1 << $bitnum)) | attr_value;
|
||||
}
|
||||
};
|
||||
|
||||
($getter:ident, $setter:ident, $bitmask:expr, $bitshift:expr) => {
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn $getter(&self) -> u16 {
|
||||
(self.attributes >> $bitshift) & $bitmask
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(dead_code)]
|
||||
pub fn $setter(&mut self, value: u16) {
|
||||
let clear = !($bitmask << $bitshift);
|
||||
let attr_value = (value & $bitmask) << $bitshift;
|
||||
self.attributes = (self.attributes & clear) | attr_value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
impl CellAttributes {
|
||||
bitfield!(bold, set_bold, 0);
|
||||
bitfield!(underline, set_underline, 1);
|
||||
bitfield!(italic, set_italic, 2);
|
||||
bitfield!(blink, set_blink, 3);
|
||||
bitfield!(reverse, set_reverse, 4);
|
||||
bitfield!(strikethrough, set_strikethrough, 5);
|
||||
// Allow up to 8 different font values
|
||||
bitfield!(font, set_font, 0b111000000, 6);
|
||||
}
|
||||
|
||||
impl Default for CellAttributes {
|
||||
fn default() -> CellAttributes {
|
||||
CellAttributes {
|
||||
bold: false,
|
||||
underline: false,
|
||||
italic: false,
|
||||
blink: false,
|
||||
reverse: false,
|
||||
strikethrough: false,
|
||||
font: 0,
|
||||
attributes: 0,
|
||||
foreground: color::ColorAttribute::Foreground,
|
||||
background: color::ColorAttribute::Background,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Cell {
|
||||
chars: [u8; 8],
|
||||
pub attrs: CellAttributes,
|
||||
@ -51,12 +91,20 @@ impl Cell {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Line {
|
||||
pub cells: Vec<Cell>,
|
||||
}
|
||||
|
||||
impl Line {
|
||||
/// Create a new line with the specified number of columns.
|
||||
/// Each cell has the default attributes.
|
||||
pub fn new(cols: usize) -> Line {
|
||||
let mut cells = Vec::with_capacity(cols);
|
||||
cells.resize(cols, Default::default());
|
||||
Line { cells }
|
||||
}
|
||||
|
||||
/// Recompose line into the corresponding utf8 string.
|
||||
/// In the future, we'll want to decompose into clusters of Cells that share
|
||||
/// the same render attributes
|
||||
@ -85,3 +133,65 @@ impl Line {
|
||||
Line { cells }
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds the model of a screen. This can either be the primary screen
|
||||
/// which includes lines of scrollback text, or the alternate screen
|
||||
/// which holds no scrollback. The intent is to have one instance of
|
||||
/// Screen for each of these things.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Screen {
|
||||
/// Holds the line data that comprises the screen contents.
|
||||
/// This is allocated with capacity for the entire scrollback.
|
||||
/// The last N lines are the visible lines, with those prior being
|
||||
/// the lines that have scrolled off the top of the screen.
|
||||
/// Index 0 is the topmost line of the screen/scrollback (depending
|
||||
/// on the current window size) and will be the first line to be
|
||||
/// popped off the front of the screen when a new line is added that
|
||||
/// would otherwise have exceeded the line capacity
|
||||
pub lines: Vec<Line>,
|
||||
|
||||
/// Maximum number of lines of scrollback
|
||||
scrollback_size: usize,
|
||||
|
||||
/// Physical, visible height of the screen (not including scrollback)
|
||||
physical_rows: usize,
|
||||
/// Physical, visible width of the screen
|
||||
physical_cols: usize,
|
||||
}
|
||||
|
||||
impl Screen {
|
||||
/// Create a new Screen with the specified dimensions.
|
||||
/// The Cells in the viewable portion of the screen are set to the
|
||||
/// default cell attributes.
|
||||
pub fn new(physical_rows: usize, physical_cols: usize, scrollback_size: usize) -> Screen {
|
||||
let mut lines = Vec::with_capacity(physical_rows + scrollback_size);
|
||||
for i in 0..physical_rows {
|
||||
lines.push(Line::new(physical_cols));
|
||||
}
|
||||
|
||||
Screen {
|
||||
lines,
|
||||
scrollback_size,
|
||||
physical_rows,
|
||||
physical_cols,
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize the physical, viewable portion of the screen
|
||||
pub fn resize(&mut self, physical_rows: usize, physical_cols: usize) {
|
||||
let capacity = physical_rows + self.scrollback_size;
|
||||
let current_capacity = self.lines.capacity();
|
||||
if capacity > current_capacity {
|
||||
self.lines.reserve(capacity - current_capacity);
|
||||
}
|
||||
|
||||
if physical_rows > self.physical_rows {
|
||||
// Enlarging the viewable portion? Add more lines at the bottom
|
||||
for _ in self.physical_rows..physical_rows {
|
||||
self.lines.push(Line::new(physical_cols));
|
||||
}
|
||||
}
|
||||
self.physical_rows = physical_rows;
|
||||
self.physical_cols = physical_cols;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user