2016-11-28 17:30:08 -05:00
|
|
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2016-12-04 14:14:27 -05:00
|
|
|
use ansi::{NamedColor, Color};
|
2016-12-26 22:52:37 -05:00
|
|
|
use grid;
|
|
|
|
use index::Column;
|
2016-11-28 17:30:08 -05:00
|
|
|
|
|
|
|
bitflags! {
|
|
|
|
#[derive(Serialize, Deserialize)]
|
2017-08-30 14:43:37 -04:00
|
|
|
pub struct Flags: u32 {
|
|
|
|
const INVERSE = 0b00000001;
|
|
|
|
const BOLD = 0b00000010;
|
|
|
|
const ITALIC = 0b00000100;
|
|
|
|
const UNDERLINE = 0b00001000;
|
|
|
|
const WRAPLINE = 0b00010000;
|
|
|
|
const WIDE_CHAR = 0b00100000;
|
|
|
|
const WIDE_CHAR_SPACER = 0b01000000;
|
|
|
|
const DIM = 0b10000000;
|
|
|
|
const DIM_BOLD = 0b10000010;
|
2016-11-28 17:30:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-29 21:51:17 -05:00
|
|
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
|
2016-11-28 17:30:08 -05:00
|
|
|
pub struct Cell {
|
|
|
|
pub c: char,
|
|
|
|
pub fg: Color,
|
|
|
|
pub bg: Color,
|
|
|
|
pub flags: Flags,
|
|
|
|
}
|
|
|
|
|
2016-12-29 21:43:55 -05:00
|
|
|
impl Default for Cell {
|
|
|
|
fn default() -> Cell {
|
|
|
|
Cell::new(
|
|
|
|
' ',
|
|
|
|
Color::Named(NamedColor::Foreground),
|
|
|
|
Color::Named(NamedColor::Background)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-12-26 22:52:37 -05:00
|
|
|
/// Get the length of occupied cells in a line
|
|
|
|
pub trait LineLength {
|
|
|
|
/// Calculate the occupied line length
|
|
|
|
fn line_length(&self) -> Column;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LineLength for grid::Row<Cell> {
|
|
|
|
fn line_length(&self) -> Column {
|
|
|
|
let mut length = Column(0);
|
|
|
|
|
2016-12-29 10:43:58 -05:00
|
|
|
if self[Column(self.len() - 1)].flags.contains(WRAPLINE) {
|
|
|
|
return Column(self.len());
|
|
|
|
}
|
|
|
|
|
2016-12-26 22:52:37 -05:00
|
|
|
for (index, cell) in self[..].iter().rev().enumerate() {
|
|
|
|
if cell.c != ' ' {
|
|
|
|
length = Column(self.len() - index);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
length
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-28 17:30:08 -05:00
|
|
|
impl Cell {
|
2017-06-23 13:01:53 -04:00
|
|
|
#[inline]
|
2016-11-28 17:30:08 -05:00
|
|
|
pub fn bold(&self) -> bool {
|
|
|
|
self.flags.contains(BOLD)
|
|
|
|
}
|
|
|
|
|
2017-06-23 13:01:53 -04:00
|
|
|
#[inline]
|
2017-06-18 20:04:16 -04:00
|
|
|
pub fn inverse(&self) -> bool {
|
|
|
|
self.flags.contains(INVERSE)
|
|
|
|
}
|
|
|
|
|
2017-06-23 13:01:53 -04:00
|
|
|
#[inline]
|
|
|
|
pub fn dim(&self) -> bool {
|
|
|
|
self.flags.contains(DIM)
|
|
|
|
}
|
|
|
|
|
2016-11-28 17:30:08 -05:00
|
|
|
pub fn new(c: char, fg: Color, bg: Color) -> Cell {
|
|
|
|
Cell {
|
|
|
|
c: c.into(),
|
|
|
|
bg: bg,
|
|
|
|
fg: fg,
|
|
|
|
flags: Flags::empty(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.c == ' ' &&
|
2016-12-04 14:14:27 -05:00
|
|
|
self.bg == Color::Named(NamedColor::Background) &&
|
2017-02-01 16:17:55 -05:00
|
|
|
!self.flags.intersects(INVERSE | UNDERLINE)
|
2016-11-28 17:30:08 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn reset(&mut self, template: &Cell) {
|
|
|
|
// memcpy template to self
|
2017-01-06 23:44:51 -05:00
|
|
|
*self = *template;
|
2016-11-28 17:30:08 -05:00
|
|
|
}
|
|
|
|
}
|
2016-12-26 22:52:37 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::{Cell, LineLength};
|
|
|
|
|
|
|
|
use grid::Row;
|
|
|
|
use index::Column;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn line_length_works() {
|
2016-12-29 21:43:55 -05:00
|
|
|
let template = Cell::default();
|
2016-12-26 22:52:37 -05:00
|
|
|
let mut row = Row::new(Column(10), &template);
|
|
|
|
row[Column(5)].c = 'a';
|
|
|
|
|
|
|
|
assert_eq!(row.line_length(), Column(6));
|
|
|
|
}
|
2016-12-29 10:43:58 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn line_length_works_with_wrapline() {
|
2016-12-29 21:43:55 -05:00
|
|
|
let template = Cell::default();
|
2016-12-29 10:43:58 -05:00
|
|
|
let mut row = Row::new(Column(10), &template);
|
|
|
|
row[Column(9)].flags.insert(super::WRAPLINE);
|
|
|
|
|
|
|
|
assert_eq!(row.line_length(), Column(10));
|
|
|
|
}
|
2016-12-26 22:52:37 -05:00
|
|
|
}
|
2016-12-29 21:51:17 -05:00
|
|
|
|
2017-02-02 23:50:48 -05:00
|
|
|
#[cfg(all(test, feature = "bench"))]
|
2016-12-29 21:51:17 -05:00
|
|
|
mod benches {
|
|
|
|
extern crate test;
|
|
|
|
use super::Cell;
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn cell_reset(b: &mut test::Bencher) {
|
|
|
|
b.iter(|| {
|
|
|
|
let mut cell = Cell::default();
|
|
|
|
|
|
|
|
for _ in 0..100 {
|
|
|
|
cell.reset(test::black_box(&Cell::default()));
|
|
|
|
}
|
|
|
|
|
|
|
|
test::black_box(cell);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|