use alacritty_terminal::term::TermMode;
use alacritty_terminal::vte::ansi::CursorShape;
use serde::Serialize;
#[derive(Serialize)]
pub struct CellFrame {
pub t: &'static str,
pub session_id: String,
pub width: u16,
pub height: u16,
pub full: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub cursor: Option<CursorState>,
pub overlay: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub row_indices: Option<Vec<usize>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub viewport: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub alt_screen: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bracketed_paste: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mouse_mode: Option<&'static str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mouse_encoding: Option<&'static str>,
pub history_size: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub seq: Option<u64>,
pub rows: Vec<RowData>,
}
#[derive(Serialize)]
pub struct RowData {
pub runs: Vec<String>,
}
#[derive(Serialize)]
pub struct CursorState {
pub row: i32,
pub col: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub shape: Option<u8>,
pub visible: bool,
}
#[derive(Default)]
pub struct DiffEngine {
prev: Vec<Option<u64>>,
}
impl DiffEngine {
pub fn with_rows(rows: usize) -> Self {
Self { prev: vec![None; rows] }
}
pub fn invalidate(&mut self) {
self.prev.fill(None);
}
pub fn is_untracked(&self) -> bool {
self.prev.is_empty() || self.prev.iter().all(|h| h.is_none())
}
pub fn resize(&mut self, new_rows: usize) {
if new_rows > self.prev.len() {
self.prev.resize(new_rows, None);
} else {
self.prev.truncate(new_rows);
}
}
pub fn changed_rows_from(&mut self, hashes: &[u64]) -> Vec<usize> {
let mut changed = Vec::new();
for (i, &h) in hashes.iter().enumerate() {
if let Some(entry) = self.prev.get(i) {
if *entry != Some(h) {
changed.push(i);
if let Some(slot) = self.prev.get_mut(i) {
*slot = Some(h);
}
}
} else {
changed.push(i);
if i < self.prev.len() {
self.prev[i] = Some(h);
}
}
}
changed
}
}
#[inline]
pub fn decscusr_code(shape: CursorShape) -> u8 {
match shape {
CursorShape::Block => 0,
CursorShape::Underline => 3,
CursorShape::Beam => 5,
CursorShape::Hidden => 0,
CursorShape::HollowBlock => 0,
}
}
pub fn mouse_mode_str(mode: TermMode) -> &'static str {
if mode.contains(TermMode::MOUSE_MOTION) {
"motion"
} else if mode.contains(TermMode::MOUSE_DRAG) {
"drag"
} else if mode.contains(TermMode::MOUSE_REPORT_CLICK) {
"press"
} else {
"none"
}
}
pub fn mouse_encoding_str(mode: TermMode) -> &'static str {
if mode.contains(TermMode::SGR_MOUSE) {
"sgr"
} else if mode.contains(TermMode::UTF8_MOUSE) {
"utf8"
} else {
"default"
}
}