1use crate::ffi::util::{cstr_to_string, slice_from, state_mut, style_from_rgba};
4use crate::terminal::{
5 AxisInfo, CanvasShape, DatasetInfo, PendingCanvas, PendingChart, PendingStyledParagraph,
6 SpanInfo, WidgetCommand,
7};
8use std::ffi::c_void;
9use std::os::raw::c_char;
10
11#[no_mangle]
29pub extern "C" fn ratatui_styled_para_begin(
30 handle: *mut c_void,
31 area_id: u32,
32 alignment: u8,
33 wrap: u8,
34) {
35 let Some(state) = state_mut(handle) else { return; };
36 state.pending_styled_para = Some(PendingStyledParagraph {
37 area_id,
38 alignment,
39 wrap: wrap != 0,
40 lines: vec![vec![]],
41 });
42}
43
44#[no_mangle]
50pub extern "C" fn ratatui_styled_para_span(
51 handle: *mut c_void,
52 text: *const c_char,
53 fg_r: u8, fg_g: u8, fg_b: u8, use_default_fg: u8,
54 bg_r: u8, bg_g: u8, bg_b: u8, use_default_bg: u8,
55 modifiers: u8,
56) {
57 let Some(state) = state_mut(handle) else { return; };
58 if let Some(ref mut pending) = state.pending_styled_para {
59 let style = style_from_rgba(
60 fg_r, fg_g, fg_b, use_default_fg,
61 bg_r, bg_g, bg_b, use_default_bg,
62 modifiers,
63 );
64 let span = SpanInfo { text: cstr_to_string(text), style };
65 if let Some(last_line) = pending.lines.last_mut() {
66 last_line.push(span);
67 }
68 }
69}
70
71#[no_mangle]
75pub extern "C" fn ratatui_styled_para_newline(handle: *mut c_void) {
76 let Some(state) = state_mut(handle) else { return; };
77 if let Some(ref mut pending) = state.pending_styled_para {
78 pending.lines.push(vec![]);
79 }
80}
81
82#[no_mangle]
86pub extern "C" fn ratatui_styled_para_end(handle: *mut c_void) {
87 let Some(state) = state_mut(handle) else { return; };
88 if let Some(pending) = state.pending_styled_para.take() {
89 state.commands.push(WidgetCommand::StyledParagraph {
90 area_id: pending.area_id,
91 alignment: pending.alignment,
92 wrap: pending.wrap,
93 lines: pending.lines,
94 });
95 }
96}
97
98#[no_mangle]
111pub extern "C" fn ratatui_chart_begin(handle: *mut c_void, area_id: u32) {
112 let Some(state) = state_mut(handle) else { return; };
113 state.pending_chart = Some(PendingChart {
114 area_id,
115 x_axis: None,
116 y_axis: None,
117 datasets: Vec::new(),
118 });
119}
120
121#[no_mangle]
125pub extern "C" fn ratatui_chart_x_axis(
126 handle: *mut c_void,
127 title: *const c_char,
128 min: f64,
129 max: f64,
130) {
131 let Some(state) = state_mut(handle) else { return; };
132 if let Some(ref mut pending) = state.pending_chart {
133 pending.x_axis = Some(AxisInfo { title: cstr_to_string(title), min, max });
134 }
135}
136
137#[no_mangle]
141pub extern "C" fn ratatui_chart_y_axis(
142 handle: *mut c_void,
143 title: *const c_char,
144 min: f64,
145 max: f64,
146) {
147 let Some(state) = state_mut(handle) else { return; };
148 if let Some(ref mut pending) = state.pending_chart {
149 pending.y_axis = Some(AxisInfo { title: cstr_to_string(title), min, max });
150 }
151}
152
153#[no_mangle]
165pub extern "C" fn ratatui_chart_dataset(
166 handle: *mut c_void,
167 name: *const c_char,
168 marker: u8,
169 r: u8, g: u8, b: u8,
170 data: *const f64,
171 point_count: u32,
172) {
173 if data.is_null() { return; }
174 let Some(state) = state_mut(handle) else { return; };
175 if let Some(ref mut pending) = state.pending_chart {
176 let raw = slice_from(data, point_count as usize * 2);
178 let points: Vec<(f64, f64)> = raw.chunks(2).map(|c| (c[0], c[1])).collect();
179 pending.datasets.push(DatasetInfo {
180 name: cstr_to_string(name),
181 marker,
182 r, g, b,
183 points,
184 });
185 }
186}
187
188#[no_mangle]
192pub extern "C" fn ratatui_chart_end(handle: *mut c_void) {
193 let Some(state) = state_mut(handle) else { return; };
194 if let Some(pending) = state.pending_chart.take() {
195 state.commands.push(WidgetCommand::Chart {
196 area_id: pending.area_id,
197 x_axis: pending.x_axis,
198 y_axis: pending.y_axis,
199 datasets: pending.datasets,
200 });
201 }
202}
203
204#[no_mangle]
224pub extern "C" fn ratatui_canvas_begin(
225 handle: *mut c_void,
226 area_id: u32,
227 x_min: f64, x_max: f64,
228 y_min: f64, y_max: f64,
229 marker: u8,
230) {
231 let Some(state) = state_mut(handle) else { return; };
232 state.pending_canvas = Some(PendingCanvas {
233 area_id,
234 x_min, x_max, y_min, y_max,
235 marker,
236 shapes: Vec::new(),
237 });
238}
239
240#[no_mangle]
247pub extern "C" fn ratatui_canvas_map(handle: *mut c_void, resolution: u8) {
248 let Some(state) = state_mut(handle) else { return; };
249 if let Some(ref mut p) = state.pending_canvas {
250 p.shapes.push(CanvasShape::Map { resolution });
251 }
252}
253
254#[no_mangle]
259pub extern "C" fn ratatui_canvas_layer(handle: *mut c_void) {
260 let Some(state) = state_mut(handle) else { return; };
261 if let Some(ref mut p) = state.pending_canvas { p.shapes.push(CanvasShape::Layer); }
262}
263
264#[no_mangle]
268pub extern "C" fn ratatui_canvas_line(
269 handle: *mut c_void,
270 x1: f64, y1: f64, x2: f64, y2: f64,
271 r: u8, g: u8, b: u8,
272) {
273 let Some(state) = state_mut(handle) else { return; };
274 if let Some(ref mut p) = state.pending_canvas {
275 p.shapes.push(CanvasShape::Line { x1, y1, x2, y2, r, g, b });
276 }
277}
278
279#[no_mangle]
283pub extern "C" fn ratatui_canvas_circle(
284 handle: *mut c_void,
285 x: f64, y: f64, radius: f64,
286 r: u8, g: u8, b: u8,
287) {
288 let Some(state) = state_mut(handle) else { return; };
289 if let Some(ref mut p) = state.pending_canvas {
290 p.shapes.push(CanvasShape::Circle { x, y, radius, r, g, b });
291 }
292}
293
294#[no_mangle]
298pub extern "C" fn ratatui_canvas_rectangle(
299 handle: *mut c_void,
300 x: f64, y: f64, w: f64, h: f64,
301 r: u8, g: u8, b: u8,
302) {
303 let Some(state) = state_mut(handle) else { return; };
304 if let Some(ref mut p) = state.pending_canvas {
305 p.shapes.push(CanvasShape::Rectangle { x, y, w, h, r, g, b });
306 }
307}
308
309#[no_mangle]
313pub extern "C" fn ratatui_canvas_text(
314 handle: *mut c_void,
315 x: f64, y: f64,
316 text: *const c_char,
317 r: u8, g: u8, b: u8,
318) {
319 let Some(state) = state_mut(handle) else { return; };
320 if let Some(ref mut p) = state.pending_canvas {
321 p.shapes.push(CanvasShape::Text { x, y, text: cstr_to_string(text), r, g, b });
322 }
323}
324
325#[no_mangle]
335pub extern "C" fn ratatui_canvas_points(
336 handle: *mut c_void,
337 coords: *const f64,
338 count: u32,
339 r: u8, g: u8, b: u8,
340) {
341 if coords.is_null() { return; }
342 let Some(state) = state_mut(handle) else { return; };
343 if let Some(ref mut p) = state.pending_canvas {
344 let raw = slice_from(coords, count as usize * 2);
346 let pts: Vec<(f64, f64)> = raw.chunks(2).map(|c| (c[0], c[1])).collect();
347 p.shapes.push(CanvasShape::Points { coords: pts, r, g, b });
348 }
349}
350
351#[no_mangle]
355pub extern "C" fn ratatui_canvas_end(handle: *mut c_void) {
356 let Some(state) = state_mut(handle) else { return; };
357 if let Some(pending) = state.pending_canvas.take() {
358 state.commands.push(WidgetCommand::Canvas {
359 area_id: pending.area_id,
360 x_min: pending.x_min,
361 x_max: pending.x_max,
362 y_min: pending.y_min,
363 y_max: pending.y_max,
364 marker: pending.marker,
365 shapes: pending.shapes,
366 });
367 }
368}