use crate::ffi::util::{cstr_to_string, slice_from, state_mut, style_from_rgba};
use crate::terminal::{
AxisInfo, CanvasShape, DatasetInfo, PendingCanvas, PendingChart, PendingStyledParagraph,
SpanInfo, WidgetCommand,
};
use std::ffi::c_void;
use std::os::raw::c_char;
#[no_mangle]
pub extern "C" fn ratatui_styled_para_begin(
handle: *mut c_void,
area_id: u32,
alignment: u8,
wrap: u8,
) {
let Some(state) = state_mut(handle) else { return; };
state.pending_styled_para = Some(PendingStyledParagraph {
area_id,
alignment,
wrap: wrap != 0,
lines: vec![vec![]],
});
}
#[no_mangle]
pub extern "C" fn ratatui_styled_para_span(
handle: *mut c_void,
text: *const c_char,
fg_r: u8, fg_g: u8, fg_b: u8, use_default_fg: u8,
bg_r: u8, bg_g: u8, bg_b: u8, use_default_bg: u8,
modifiers: u8,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut pending) = state.pending_styled_para {
let style = style_from_rgba(
fg_r, fg_g, fg_b, use_default_fg,
bg_r, bg_g, bg_b, use_default_bg,
modifiers,
);
let span = SpanInfo { text: cstr_to_string(text), style };
if let Some(last_line) = pending.lines.last_mut() {
last_line.push(span);
}
}
}
#[no_mangle]
pub extern "C" fn ratatui_styled_para_newline(handle: *mut c_void) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut pending) = state.pending_styled_para {
pending.lines.push(vec![]);
}
}
#[no_mangle]
pub extern "C" fn ratatui_styled_para_end(handle: *mut c_void) {
let Some(state) = state_mut(handle) else { return; };
if let Some(pending) = state.pending_styled_para.take() {
state.commands.push(WidgetCommand::StyledParagraph {
area_id: pending.area_id,
alignment: pending.alignment,
wrap: pending.wrap,
lines: pending.lines,
});
}
}
#[no_mangle]
pub extern "C" fn ratatui_chart_begin(handle: *mut c_void, area_id: u32) {
let Some(state) = state_mut(handle) else { return; };
state.pending_chart = Some(PendingChart {
area_id,
x_axis: None,
y_axis: None,
datasets: Vec::new(),
});
}
#[no_mangle]
pub extern "C" fn ratatui_chart_x_axis(
handle: *mut c_void,
title: *const c_char,
min: f64,
max: f64,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut pending) = state.pending_chart {
pending.x_axis = Some(AxisInfo { title: cstr_to_string(title), min, max });
}
}
#[no_mangle]
pub extern "C" fn ratatui_chart_y_axis(
handle: *mut c_void,
title: *const c_char,
min: f64,
max: f64,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut pending) = state.pending_chart {
pending.y_axis = Some(AxisInfo { title: cstr_to_string(title), min, max });
}
}
#[no_mangle]
pub extern "C" fn ratatui_chart_dataset(
handle: *mut c_void,
name: *const c_char,
marker: u8,
r: u8, g: u8, b: u8,
data: *const f64,
point_count: u32,
) {
if data.is_null() { return; }
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut pending) = state.pending_chart {
let raw = slice_from(data, point_count as usize * 2);
let points: Vec<(f64, f64)> = raw.chunks(2).map(|c| (c[0], c[1])).collect();
pending.datasets.push(DatasetInfo {
name: cstr_to_string(name),
marker,
r, g, b,
points,
});
}
}
#[no_mangle]
pub extern "C" fn ratatui_chart_end(handle: *mut c_void) {
let Some(state) = state_mut(handle) else { return; };
if let Some(pending) = state.pending_chart.take() {
state.commands.push(WidgetCommand::Chart {
area_id: pending.area_id,
x_axis: pending.x_axis,
y_axis: pending.y_axis,
datasets: pending.datasets,
});
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_begin(
handle: *mut c_void,
area_id: u32,
x_min: f64, x_max: f64,
y_min: f64, y_max: f64,
marker: u8,
) {
let Some(state) = state_mut(handle) else { return; };
state.pending_canvas = Some(PendingCanvas {
area_id,
x_min, x_max, y_min, y_max,
marker,
shapes: Vec::new(),
});
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_map(handle: *mut c_void, resolution: u8) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
p.shapes.push(CanvasShape::Map { resolution });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_layer(handle: *mut c_void) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas { p.shapes.push(CanvasShape::Layer); }
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_line(
handle: *mut c_void,
x1: f64, y1: f64, x2: f64, y2: f64,
r: u8, g: u8, b: u8,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
p.shapes.push(CanvasShape::Line { x1, y1, x2, y2, r, g, b });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_circle(
handle: *mut c_void,
x: f64, y: f64, radius: f64,
r: u8, g: u8, b: u8,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
p.shapes.push(CanvasShape::Circle { x, y, radius, r, g, b });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_rectangle(
handle: *mut c_void,
x: f64, y: f64, w: f64, h: f64,
r: u8, g: u8, b: u8,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
p.shapes.push(CanvasShape::Rectangle { x, y, w, h, r, g, b });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_text(
handle: *mut c_void,
x: f64, y: f64,
text: *const c_char,
r: u8, g: u8, b: u8,
) {
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
p.shapes.push(CanvasShape::Text { x, y, text: cstr_to_string(text), r, g, b });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_points(
handle: *mut c_void,
coords: *const f64,
count: u32,
r: u8, g: u8, b: u8,
) {
if coords.is_null() { return; }
let Some(state) = state_mut(handle) else { return; };
if let Some(ref mut p) = state.pending_canvas {
let raw = slice_from(coords, count as usize * 2);
let pts: Vec<(f64, f64)> = raw.chunks(2).map(|c| (c[0], c[1])).collect();
p.shapes.push(CanvasShape::Points { coords: pts, r, g, b });
}
}
#[no_mangle]
pub extern "C" fn ratatui_canvas_end(handle: *mut c_void) {
let Some(state) = state_mut(handle) else { return; };
if let Some(pending) = state.pending_canvas.take() {
state.commands.push(WidgetCommand::Canvas {
area_id: pending.area_id,
x_min: pending.x_min,
x_max: pending.x_max,
y_min: pending.y_min,
y_max: pending.y_max,
marker: pending.marker,
shapes: pending.shapes,
});
}
}