use rdom_core::{Dom, NodeId};
use crate::ext::TuiExt;
use crate::render::inline::inline_flow_container;
use crate::render::{Buffer, Rect, Style};
use crate::style::Modifier;
pub(in crate::render::paint_pass) fn paint_caret_if_editable(
dom: &Dom<TuiExt>,
buf: &mut Buffer,
id: NodeId,
clip: Rect,
) {
use crate::layout::{CaretColor, CaretTextColor};
let sel = match dom.selection() {
Some(s) if s.is_collapsed() => s,
_ => return,
};
let Some(focused) = dom.focused() else {
return;
};
let Some(host) = crate::node::nearest_editable_ancestor(dom, focused) else {
return;
};
if dom.node(host).ext().is_some_and(|e| e.caret_blink_off) {
return;
}
let caret_ifc = inline_flow_container(dom, sel.focus.node);
if caret_ifc != Some(id) {
return;
}
let computed = match dom.node(focused).ext().and_then(|e| e.computed.as_ref()) {
Some(c) => c,
None => return,
};
if matches!(computed.caret_color, CaretColor::Transparent) {
return;
}
let Some((x, y)) = crate::render::inline::cell_of_position(dom, sel.focus) else {
return;
};
if x < clip.x || x >= clip.right() || y < clip.y || y >= clip.bottom() {
return;
}
let resolve_reset_fg = |c: crate::Color| match c {
crate::Color::Reset => crate::Color::Rgb(0xFF, 0xFF, 0xFF),
other => other,
};
let resolve_reset_bg = |c: crate::Color| match c {
crate::Color::Reset => crate::Color::Rgb(0x00, 0x00, 0x00),
other => other,
};
let cascaded_fg = resolve_reset_fg(computed.fg);
let cascaded_bg = resolve_reset_bg(computed.bg);
let under_mod = buf.cell(x, y).map(|c| c.modifier).unwrap_or_default();
let caret_bg = match &computed.caret_color {
CaretColor::Auto => cascaded_fg,
CaretColor::Transparent => return, CaretColor::Color(tc) => match tc {
crate::TuiColor::Literal(c) => *c,
crate::TuiColor::Var { .. } => cascaded_fg,
},
};
let caret_fg = match &computed.caret_text_color {
CaretTextColor::Auto => cascaded_bg,
CaretTextColor::Color(tc) => match tc {
crate::TuiColor::Literal(c) => *c,
crate::TuiColor::Var { .. } => cascaded_bg,
},
};
let mut new_style = Style::new().fg(caret_fg).bg(caret_bg);
for m in [
Modifier::BOLD,
Modifier::ITALIC,
Modifier::UNDERLINED,
Modifier::SLOW_BLINK,
Modifier::RAPID_BLINK,
Modifier::HIDDEN,
Modifier::CROSSED_OUT,
] {
if under_mod.contains(m) {
new_style = new_style.add_modifier(m);
}
}
buf.set_style(x, y, new_style);
}