1use std::{marker::PhantomData, mem::MaybeUninit};
7
8use crate::{
9 error::{Error, Result, from_result, from_result_with_len},
10 ffi,
11 style::{self, PaletteIndex, RgbColor, Style},
12};
13
14#[derive(Clone, Debug)]
31pub struct GridRef<'t> {
32 pub(crate) inner: ffi::GhosttyGridRef,
33 pub(crate) _phan: PhantomData<&'t ffi::GhosttyTerminal>,
34}
35
36impl GridRef<'_> {
37 pub fn row(&self) -> Result<Row> {
39 let mut v = ffi::GhosttyRow::default();
40 let result = unsafe { ffi::ghostty_grid_ref_row(std::ptr::from_ref(&self.inner), &raw mut v) };
41 from_result(result)?;
42 Ok(Row(v))
43 }
44 pub fn cell(&self) -> Result<Cell> {
46 let mut v = ffi::GhosttyCell::default();
47 let result = unsafe { ffi::ghostty_grid_ref_cell(std::ptr::from_ref(&self.inner), &raw mut v) };
48 from_result(result)?;
49 Ok(Cell(v))
50 }
51 pub fn style(&self) -> Result<Style> {
53 let mut v = ffi::GhosttyStyle::default();
54 let result =
55 unsafe { ffi::ghostty_grid_ref_style(std::ptr::from_ref(&self.inner), &raw mut v) };
56 from_result(result)?;
57 Style::try_from(v)
58 }
59
60 pub fn graphemes(&self, buf: &mut [char]) -> Result<usize> {
72 let mut len = 0;
73 let result = unsafe {
74 ffi::ghostty_grid_ref_graphemes(
75 std::ptr::from_ref(&self.inner),
76 std::ptr::from_mut(buf).cast(),
77 buf.len(),
78 &raw mut len,
79 )
80 };
81 from_result_with_len(result, len)
82 }
83}
84
85#[derive(Clone, Copy, Debug, PartialEq, Eq)]
90pub struct Row(pub(crate) ffi::GhosttyRow);
91
92impl Row {
93 fn get<T>(&self, tag: ffi::GhosttyRowData) -> Result<T> {
94 let mut value = MaybeUninit::<T>::zeroed();
95 let result = unsafe { ffi::ghostty_row_get(self.0, tag, value.as_mut_ptr().cast()) };
96 from_result(result)?;
98 Ok(unsafe { value.assume_init() })
100 }
101
102 pub fn is_wrapped(self) -> Result<bool> {
104 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_WRAP)
105 }
106 pub fn is_wrap_continuation(self) -> Result<bool> {
108 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_WRAP_CONTINUATION)
109 }
110 pub fn has_grapheme_cluster(self) -> Result<bool> {
112 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_GRAPHEME)
113 }
114 pub fn is_styled(self) -> Result<bool> {
116 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_STYLED)
117 }
118 pub fn has_hyperlink(self) -> Result<bool> {
120 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_HYPERLINK)
121 }
122 pub fn semantic_prompt(self) -> Result<RowSemanticPrompt> {
124 self.get::<ffi::GhosttyRowSemanticPrompt>(
125 ffi::GhosttyRowData_GHOSTTY_ROW_DATA_SEMANTIC_PROMPT,
126 )
127 .and_then(|v| v.try_into().map_err(|_| Error::InvalidValue))
128 }
129 pub fn has_kitty_virtual_placeholder(self) -> Result<bool> {
131 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_KITTY_VIRTUAL_PLACEHOLDER)
132 }
133 pub fn is_dirty(self) -> Result<bool> {
135 self.get(ffi::GhosttyRowData_GHOSTTY_ROW_DATA_DIRTY)
136 }
137}
138
139#[derive(Clone, Copy, Debug, PartialEq, Eq)]
144pub struct Cell(pub(crate) ffi::GhosttyCell);
145
146impl Cell {
147 fn get<T>(&self, tag: ffi::GhosttyCellData) -> Result<T> {
148 let mut value = MaybeUninit::<T>::zeroed();
149 let result = unsafe { ffi::ghostty_cell_get(self.0, tag, value.as_mut_ptr().cast()) };
150 from_result(result)?;
152 Ok(unsafe { value.assume_init() })
154 }
155
156 pub fn codepoint(self) -> Result<u32> {
158 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_CODEPOINT)
159 }
160 pub fn content_tag(self) -> Result<CellContentTag> {
162 self.get::<ffi::GhosttyCellContentTag>(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_CONTENT_TAG)
163 .and_then(|v| v.try_into().map_err(|_| Error::InvalidValue))
164 }
165 pub fn wide(self) -> Result<CellWide> {
167 self.get::<ffi::GhosttyCellWide>(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_WIDE)
168 .and_then(|v| v.try_into().map_err(|_| Error::InvalidValue))
169 }
170 pub fn has_text(self) -> Result<bool> {
172 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_HAS_TEXT)
173 }
174 pub fn has_styling(self) -> Result<bool> {
176 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_HAS_STYLING)
177 }
178 pub fn style_id(self) -> Result<style::Id> {
180 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_STYLE_ID)
181 .map(style::Id)
182 }
183 pub fn has_hyperlink(self) -> Result<bool> {
185 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_HAS_HYPERLINK)
186 }
187 pub fn is_protected(self) -> Result<bool> {
189 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_PROTECTED)
190 }
191 pub fn semantic_content(self) -> Result<CellSemanticContent> {
193 self.get::<ffi::GhosttyCellSemanticContent>(
194 ffi::GhosttyCellData_GHOSTTY_CELL_DATA_SEMANTIC_CONTENT,
195 )
196 .and_then(|v| v.try_into().map_err(|_| Error::InvalidValue))
197 }
198
199 pub fn bg_color_palette(self) -> Result<PaletteIndex> {
203 self.get(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_COLOR_PALETTE)
204 .map(PaletteIndex)
205 }
206 pub fn bg_color_rgb(self) -> Result<RgbColor> {
210 Ok(self
211 .get::<ffi::GhosttyColorRgb>(ffi::GhosttyCellData_GHOSTTY_CELL_DATA_COLOR_RGB)?
212 .into())
213 }
214}
215
216#[repr(u32)]
220#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
221pub enum RowSemanticPrompt {
222 None = ffi::GhosttyRowSemanticPrompt_GHOSTTY_ROW_SEMANTIC_NONE,
224 Prompt = ffi::GhosttyRowSemanticPrompt_GHOSTTY_ROW_SEMANTIC_PROMPT,
226 Continuation = ffi::GhosttyRowSemanticPrompt_GHOSTTY_ROW_SEMANTIC_PROMPT_CONTINUATION,
228}
229
230#[repr(u32)]
234#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
235pub enum CellContentTag {
236 Codepoint = ffi::GhosttyCellContentTag_GHOSTTY_CELL_CONTENT_CODEPOINT,
238 CodepointGrapheme = ffi::GhosttyCellContentTag_GHOSTTY_CELL_CONTENT_CODEPOINT_GRAPHEME,
240 BgColorPalette = ffi::GhosttyCellContentTag_GHOSTTY_CELL_CONTENT_BG_COLOR_PALETTE,
242 BgColorRgb = ffi::GhosttyCellContentTag_GHOSTTY_CELL_CONTENT_BG_COLOR_RGB,
244}
245
246#[repr(u32)]
250#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
251pub enum CellWide {
252 Narrow = ffi::GhosttyCellWide_GHOSTTY_CELL_WIDE_NARROW,
254 Wide = ffi::GhosttyCellWide_GHOSTTY_CELL_WIDE_WIDE,
256 SpacerTail = ffi::GhosttyCellWide_GHOSTTY_CELL_WIDE_SPACER_TAIL,
258 SpacerHead = ffi::GhosttyCellWide_GHOSTTY_CELL_WIDE_SPACER_HEAD,
260}
261
262#[repr(u32)]
267#[derive(Clone, Copy, Debug, PartialEq, Eq, int_enum::IntEnum)]
268pub enum CellSemanticContent {
269 Output = ffi::GhosttyCellSemanticContent_GHOSTTY_CELL_SEMANTIC_OUTPUT,
271 Input = ffi::GhosttyCellSemanticContent_GHOSTTY_CELL_SEMANTIC_INPUT,
273 Prompt = ffi::GhosttyCellSemanticContent_GHOSTTY_CELL_SEMANTIC_PROMPT,
275}