libghostty-vt 0.0.0
Loading...
Searching...
No Matches
c-vt-render/src/main.c

Draw a frame from a render state: check what's dirty, walk the rows and cells, and read styles, colors, the cursor and the selection. Use this when you render the terminal yourself.

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <ghostty/vt.h>
static GhosttyColorRgb resolve_color(GhosttyStyleColor color,
const GhosttyRenderStateColors* colors,
GhosttyColorRgb fallback) {
switch (color.tag) {
case GHOSTTY_STYLE_COLOR_RGB:
return color.value.rgb;
case GHOSTTY_STYLE_COLOR_PALETTE:
return colors->palette[color.value.palette];
default:
return fallback;
}
}
int main(void) {
GhosttyResult result;
// Create a terminal and render state, then update the render state
// from the terminal. The render state captures a snapshot of everything
// needed to draw a frame.
GhosttyTerminal terminal = NULL;
result = ghostty_terminal_new(NULL, &terminal, 40, 5);
assert(result == GHOSTTY_SUCCESS);
GhosttyRenderState render_state = NULL;
result = ghostty_render_state_new(NULL, &render_state);
assert(result == GHOSTTY_SUCCESS);
// Feed some styled content into the terminal.
const char* content =
"Hello, \033[1;32mworld\033[0m!\r\n" // bold green "world"
"\033[4munderlined\033[0m text\r\n" // underlined text
"\033[38;2;255;128;0morange\033[0m\r\n"; // 24-bit orange fg
terminal, (const uint8_t*)content, strlen(content));
// Select "underlined" on the second row. Render state exposes this
// later as a row-local selected cell range.
GhosttyGridRef selection_start = {0};
GhosttyPoint selection_start_pt = {
.value = { .coordinate = { .x = 0, .y = 1 } },
};
terminal, selection_start_pt, &selection_start);
assert(result == GHOSTTY_SUCCESS);
GhosttyGridRef selection_end = {0};
GhosttyPoint selection_end_pt = {
.value = { .coordinate = { .x = 9, .y = 1 } },
};
result = ghostty_terminal_grid_ref(terminal, selection_end_pt, &selection_end);
assert(result == GHOSTTY_SUCCESS);
GhosttySelection selection = {0};
selection.start = selection_start;
selection.end = selection_end;
terminal, GHOSTTY_TERMINAL_OPT_SELECTION, &selection);
assert(result == GHOSTTY_SUCCESS);
result = ghostty_render_state_update(render_state, terminal);
assert(result == GHOSTTY_SUCCESS);
// Check the global dirty state to decide how much work the renderer
// needs to do. After rendering, reset it to false.
render_state, GHOSTTY_RENDER_STATE_DATA_DIRTY, &dirty);
assert(result == GHOSTTY_SUCCESS);
switch (dirty) {
printf("Frame is clean, nothing to draw.\n");
break;
printf("Partial redraw needed.\n");
break;
printf("Full redraw needed.\n");
break;
}
// Retrieve colors (background, foreground, palette) from the render
// state. These are needed to resolve palette-indexed cell colors.
render_state, GHOSTTY_RENDER_STATE_DATA_COLORS, &colors);
assert(result == GHOSTTY_SUCCESS);
printf("Background: #%02x%02x%02x\n",
colors.background.r, colors.background.g, colors.background.b);
printf("Foreground: #%02x%02x%02x\n",
colors.foreground.r, colors.foreground.g, colors.foreground.b);
// Read all cursor state in one call.
render_state, GHOSTTY_RENDER_STATE_DATA_CURSOR, &cursor);
assert(result == GHOSTTY_SUCCESS);
if (cursor.visible && cursor.viewport_has_value) {
const char* style_name = "unknown";
switch (cursor.visual_style) {
style_name = "bar";
break;
style_name = "block";
break;
style_name = "underline";
break;
style_name = "hollow";
break;
}
printf("Cursor at (%u, %u), style: %s\n",
cursor.viewport_x, cursor.viewport_y, style_name);
}
// Iterate rows via the row iterator. For each dirty row, iterate its
// cells, read codepoints/graphemes and styles, and emit ANSI-colored
// output as a simple "renderer".
result = ghostty_render_state_row_iterator_new(NULL, &row_iter);
assert(result == GHOSTTY_SUCCESS);
render_state, GHOSTTY_RENDER_STATE_DATA_ROW_ITERATOR, &row_iter);
assert(result == GHOSTTY_SUCCESS);
result = ghostty_render_state_row_cells_new(NULL, &cells);
assert(result == GHOSTTY_SUCCESS);
uint16_t row_y = 0;
printf("Row %2u [dirty]: ", row_y);
// Query the row-local selection range. Rows without a selection return
// GHOSTTY_NO_VALUE; selected rows return inclusive start/end columns.
row_iter, GHOSTTY_RENDER_STATE_ROW_DATA_SELECTION, &row_selection);
assert(result == GHOSTTY_SUCCESS || result == GHOSTTY_NO_VALUE);
if (result == GHOSTTY_SUCCESS) {
printf("selection=%u..%u ",
row_selection.start_x, row_selection.end_x);
}
// Get cells for this row (reuses the same cells handle).
assert(result == GHOSTTY_SUCCESS);
// Get the grapheme length; 0 means the cell is empty.
uint32_t grapheme_len = 0;
&grapheme_len);
if (grapheme_len == 0) {
putchar(' ');
continue;
}
// Read the style for this cell. Returns the default style for
// cells that have no explicit styling.
GhosttyStyle style;
// Resolve foreground color for this cell.
resolve_color(style.fg_color, &colors, colors.foreground);
// Emit ANSI true-color escape for the foreground.
printf("\033[38;2;%u;%u;%um", fg.r, fg.g, fg.b);
if (style.flags & GHOSTTY_STYLE_FLAG_BOLD) printf("\033[1m");
if (GHOSTTY_STYLE_UNDERLINE(style)) printf("\033[4m");
// Read grapheme codepoints into a buffer and print them. If the
// cell has more than 16 codepoints, only the first 16 are written
// and graphemes.len holds the full count, so print what fits.
uint32_t codepoints[16];
GhosttyCodepointBuffer graphemes = {
.ptr = codepoints,
.cap = sizeof(codepoints) / sizeof(codepoints[0]),
};
&graphemes);
size_t len = graphemes.len < graphemes.cap ? graphemes.len : graphemes.cap;
for (size_t i = 0; i < len; i++) {
// Simple ASCII print; a real renderer would handle UTF-8.
if (codepoints[i] < 128)
putchar((char)codepoints[i]);
else
printf("U+%04X", codepoints[i]);
}
printf("\033[0m"); // Reset style after each cell.
}
printf("\n");
}
// After successfully rendering the complete frame, clear both the global
// and per-row dirty state in one call.
result = ghostty_render_state_clean(render_state);
assert(result == GHOSTTY_SUCCESS);
// Cleanup
return 0;
}
GhosttyResult
Definition types.h:143
#define GHOSTTY_INIT_SIZED(type)
Definition types.h:558
@ GHOSTTY_NO_VALUE
Definition types.h:160
@ GHOSTTY_SUCCESS
Definition types.h:145
@ GHOSTTY_POINT_TAG_ACTIVE
Definition point.h:66
GHOSTTY_API GhosttyResult ghostty_render_state_row_cells_new(const GhosttyAllocator *allocator, GhosttyRenderStateRowCells *out_cells)
GHOSTTY_API GhosttyResult ghostty_render_state_row_cells_get(GhosttyRenderStateRowCells cells, GhosttyRenderStateRowCellsData data, void *out)
GHOSTTY_API GhosttyResult ghostty_render_state_clean(GhosttyRenderState state)
GHOSTTY_API bool ghostty_render_state_row_cells_next(GhosttyRenderStateRowCells cells)
GHOSTTY_API GhosttyResult ghostty_render_state_update(GhosttyRenderState state, GhosttyTerminal terminal)
struct GhosttyRenderStateRowIteratorImpl * GhosttyRenderStateRowIterator
Definition types.h:259
struct GhosttyRenderStateImpl * GhosttyRenderState
Definition types.h:252
GHOSTTY_API GhosttyResult ghostty_render_state_new(const GhosttyAllocator *allocator, GhosttyRenderState *state)
GHOSTTY_API GhosttyResult ghostty_render_state_row_iterator_new(const GhosttyAllocator *allocator, GhosttyRenderStateRowIterator *out_iterator)
GHOSTTY_API void ghostty_render_state_row_cells_free(GhosttyRenderStateRowCells cells)
GHOSTTY_API void ghostty_render_state_row_iterator_free(GhosttyRenderStateRowIterator iterator)
GHOSTTY_API void ghostty_render_state_free(GhosttyRenderState state)
GHOSTTY_API GhosttyResult ghostty_render_state_get(GhosttyRenderState state, GhosttyRenderStateData data, void *out)
GHOSTTY_API bool ghostty_render_state_row_iterator_next_dirty(GhosttyRenderStateRowIterator iterator, uint16_t *out_y)
GhosttyRenderStateDirty
Definition render.h:49
GHOSTTY_API GhosttyResult ghostty_render_state_row_get(GhosttyRenderStateRowIterator iterator, GhosttyRenderStateRowData data, void *out)
struct GhosttyRenderStateRowCellsImpl * GhosttyRenderStateRowCells
Definition types.h:266
@ GHOSTTY_RENDER_STATE_ROW_DATA_SELECTION
Definition render.h:455
@ GHOSTTY_RENDER_STATE_ROW_DATA_CELLS
Definition render.h:452
@ GHOSTTY_RENDER_STATE_DATA_DIRTY
Definition render.h:117
@ GHOSTTY_RENDER_STATE_DATA_COLORS
Definition render.h:181
@ GHOSTTY_RENDER_STATE_DATA_ROW_ITERATOR
Definition render.h:128
@ GHOSTTY_RENDER_STATE_DATA_CURSOR
Definition render.h:177
@ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_LEN
Definition render.h:1009
@ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_GRAPHEMES_BUF
Definition render.h:1032
@ GHOSTTY_RENDER_STATE_ROW_CELLS_DATA_STYLE
Definition render.h:1005
@ GHOSTTY_RENDER_STATE_DIRTY_FALSE
Definition render.h:51
@ GHOSTTY_RENDER_STATE_DIRTY_PARTIAL
Definition render.h:54
@ GHOSTTY_RENDER_STATE_DIRTY_FULL
Definition render.h:57
#define GHOSTTY_STYLE_UNDERLINE(style)
Definition style.h:191
#define GHOSTTY_STYLE_FLAG_BOLD
Definition style.h:140
GHOSTTY_API GhosttyResult ghostty_terminal_set(GhosttyTerminal terminal, GhosttyTerminalOption option, const void *value)
struct GhosttyTerminalImpl * GhosttyTerminal
Definition types.h:196
GHOSTTY_API void ghostty_terminal_free(GhosttyTerminal terminal)
GHOSTTY_API void ghostty_terminal_vt_write(GhosttyTerminal terminal, const uint8_t *data, size_t len)
GHOSTTY_API GhosttyResult ghostty_terminal_grid_ref(GhosttyTerminal terminal, GhosttyPoint point, GhosttyGridRef *out_ref)
GHOSTTY_API GhosttyResult ghostty_terminal_new(const GhosttyAllocator *allocator, GhosttyTerminal *terminal, uint16_t cols, uint16_t rows)
@ GHOSTTY_CURSOR_STYLE_BAR
Definition types.h:357
@ GHOSTTY_CURSOR_STYLE_UNDERLINE
Definition types.h:363
@ GHOSTTY_CURSOR_STYLE_BLOCK_HOLLOW
Definition types.h:366
@ GHOSTTY_CURSOR_STYLE_BLOCK
Definition types.h:360
@ GHOSTTY_TERMINAL_OPT_SELECTION
Definition terminal.h:2251
uint8_t g
Definition color.h:50
uint8_t b
Definition color.h:51
uint8_t r
Definition color.h:49
GhosttyColorRgb foreground
Definition render.h:592
GhosttyColorRgb background
Definition render.h:589
GhosttyColorRgb palette[256]
Definition render.h:605
GhosttyCursorStyle visual_style
Definition render.h:566
GhosttyGridRef end
Definition selection.h:123
GhosttyGridRef start
Definition selection.h:120
uint8_t tag
Definition style.h:115
GhosttyStyleColorValue value
Definition style.h:118
GhosttyStyleFlags flags
Definition style.h:238
GhosttyStyleColor fg_color
Definition style.h:229