mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-06 07:38:21 +00:00
vt: add GhosttyRenderStateRowCells opaque type
Add a new opaque RowCells type that wraps per-row cell data (raw cells, graphemes, styles) for the C API. The caller allocates a RowCells handle via row_cells_new, then populates it by passing it to row_get with the new .cells data kind. This queries the current row from the iterator and slices the underlying MultiArrayList into the RowCellsWrapper fields. The new type and functions are wired through main.zig, lib_vt.zig, and the render.h C header.
This commit is contained in:
@@ -79,6 +79,13 @@ typedef struct GhosttyRenderState* GhosttyRenderState;
|
||||
*/
|
||||
typedef struct GhosttyRenderStateRowIterator* GhosttyRenderStateRowIterator;
|
||||
|
||||
/**
|
||||
* Opaque handle to render-state row cells.
|
||||
*
|
||||
* @ingroup render
|
||||
*/
|
||||
typedef struct GhosttyRenderStateRowCells* GhosttyRenderStateRowCells;
|
||||
|
||||
/**
|
||||
* Dirty state of a render state after update.
|
||||
*
|
||||
@@ -138,6 +145,10 @@ typedef enum {
|
||||
|
||||
/** The raw row value (GhosttyRow). */
|
||||
GHOSTTY_RENDER_STATE_ROW_DATA_RAW = 2,
|
||||
|
||||
/** Populate a pre-allocated GhosttyRenderStateRowCells with cell data for
|
||||
* the current row (GhosttyRenderStateRowCells). */
|
||||
GHOSTTY_RENDER_STATE_ROW_DATA_CELLS = 3,
|
||||
} GhosttyRenderStateRowData;
|
||||
|
||||
/**
|
||||
@@ -370,6 +381,36 @@ GhosttyResult ghostty_render_state_row_set(
|
||||
GhosttyRenderStateRowOption option,
|
||||
const void* value);
|
||||
|
||||
/**
|
||||
* Create a new row cells instance.
|
||||
*
|
||||
* All fields except the allocator are left undefined until populated
|
||||
* via ghostty_render_state_row_get() with
|
||||
* GHOSTTY_RENDER_STATE_ROW_DATA_CELLS.
|
||||
*
|
||||
* You can reuse this value repeatedly with ghostty_render_state_row_get() to
|
||||
* avoid allocating a new cells container for every row.
|
||||
*
|
||||
* @param allocator Pointer to allocator, or NULL to use the default allocator
|
||||
* @param[out] out_cells On success, receives the created row cells handle
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_MEMORY on allocation
|
||||
* failure
|
||||
*
|
||||
* @ingroup render
|
||||
*/
|
||||
GhosttyResult ghostty_render_state_row_cells_new(
|
||||
const GhosttyAllocator* allocator,
|
||||
GhosttyRenderStateRowCells* out_cells);
|
||||
|
||||
/**
|
||||
* Free a row cells instance.
|
||||
*
|
||||
* @param cells The row cells handle to free (may be NULL)
|
||||
*
|
||||
* @ingroup render
|
||||
*/
|
||||
void ghostty_render_state_row_cells_free(GhosttyRenderStateRowCells cells);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -197,6 +197,8 @@ comptime {
|
||||
@export(&c.render_state_row_get, .{ .name = "ghostty_render_state_row_get" });
|
||||
@export(&c.render_state_row_set, .{ .name = "ghostty_render_state_row_set" });
|
||||
@export(&c.render_state_row_iterator_free, .{ .name = "ghostty_render_state_row_iterator_free" });
|
||||
@export(&c.render_state_row_cells_new, .{ .name = "ghostty_render_state_row_cells_new" });
|
||||
@export(&c.render_state_row_cells_free, .{ .name = "ghostty_render_state_row_cells_free" });
|
||||
@export(&c.render_state_free, .{ .name = "ghostty_render_state_free" });
|
||||
@export(&c.terminal_new, .{ .name = "ghostty_terminal_new" });
|
||||
@export(&c.terminal_free, .{ .name = "ghostty_terminal_free" });
|
||||
|
||||
@@ -47,6 +47,8 @@ pub const render_state_row_iterator_next = render.row_iterator_next;
|
||||
pub const render_state_row_get = render.row_get;
|
||||
pub const render_state_row_set = render.row_set;
|
||||
pub const render_state_row_iterator_free = render.row_iterator_free;
|
||||
pub const render_state_row_cells_new = render.row_cells_new;
|
||||
pub const render_state_row_cells_free = render.row_cells_free;
|
||||
|
||||
pub const sgr_new = sgr.new;
|
||||
pub const sgr_free = sgr.free;
|
||||
|
||||
@@ -32,12 +32,23 @@ const RowIteratorWrapper = struct {
|
||||
dirty: []bool,
|
||||
};
|
||||
|
||||
const RowCellsWrapper = struct {
|
||||
alloc: std.mem.Allocator,
|
||||
x: ?size.CellCountInt,
|
||||
raws: []const page.Cell,
|
||||
graphemes: []const []const u21,
|
||||
styles: []const Style,
|
||||
};
|
||||
|
||||
/// C: GhosttyRenderState
|
||||
pub const RenderState = ?*RenderStateWrapper;
|
||||
|
||||
/// C: GhosttyRenderStateRowIterator
|
||||
pub const RowIterator = ?*RowIteratorWrapper;
|
||||
|
||||
/// C: GhosttyRenderStateRowCells
|
||||
pub const RowCells = ?*RowCellsWrapper;
|
||||
|
||||
/// C: GhosttyRenderStateDirty
|
||||
pub const Dirty = renderpkg.RenderState.Dirty;
|
||||
|
||||
@@ -253,8 +264,6 @@ pub fn colors_get(
|
||||
return .success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub fn row_iterator_new(
|
||||
alloc_: ?*const CAllocator,
|
||||
state_: RenderState,
|
||||
@@ -310,11 +319,38 @@ pub fn row_iterator_next(iterator_: RowIterator) callconv(.c) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn row_cells_new(
|
||||
alloc_: ?*const CAllocator,
|
||||
result: *RowCells,
|
||||
) callconv(.c) Result {
|
||||
const alloc = lib_alloc.default(alloc_);
|
||||
const ptr = alloc.create(RowCellsWrapper) catch {
|
||||
result.* = null;
|
||||
return .out_of_memory;
|
||||
};
|
||||
ptr.* = .{
|
||||
.alloc = alloc,
|
||||
.x = undefined,
|
||||
.raws = undefined,
|
||||
.graphemes = undefined,
|
||||
.styles = undefined,
|
||||
};
|
||||
result.* = ptr;
|
||||
return .success;
|
||||
}
|
||||
|
||||
pub fn row_cells_free(cells_: RowCells) callconv(.c) void {
|
||||
const cells = cells_ orelse return;
|
||||
const alloc = cells.alloc;
|
||||
alloc.destroy(cells);
|
||||
}
|
||||
|
||||
/// C: GhosttyRenderStateRowData
|
||||
pub const RowData = enum(c_int) {
|
||||
invalid = 0,
|
||||
dirty = 1,
|
||||
raw = 2,
|
||||
cells = 3,
|
||||
|
||||
/// Output type expected for querying the data of the given kind.
|
||||
pub fn OutType(comptime self: RowData) type {
|
||||
@@ -322,6 +358,7 @@ pub const RowData = enum(c_int) {
|
||||
.invalid => void,
|
||||
.dirty => bool,
|
||||
.raw => row.CRow,
|
||||
.cells => RowCells,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -370,6 +407,17 @@ fn rowGetTyped(
|
||||
.invalid => return .invalid_value,
|
||||
.dirty => out.* = it.dirty[y],
|
||||
.raw => out.* = it.raws[y].cval(),
|
||||
.cells => {
|
||||
const cells = out.* orelse return .invalid_value;
|
||||
const cell_data = it.cells[y].slice();
|
||||
cells.* = .{
|
||||
.alloc = cells.alloc,
|
||||
.x = null,
|
||||
.raws = cell_data.items(.raw),
|
||||
.graphemes = cell_data.items(.grapheme),
|
||||
.styles = cell_data.items(.style),
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
return .success;
|
||||
|
||||
Reference in New Issue
Block a user